|
Lines 66-71
__FBSDID("$FreeBSD$");
Link Here
|
| 66 |
#include <dev/virtio/scsi/virtio_scsi.h> |
66 |
#include <dev/virtio/scsi/virtio_scsi.h> |
| 67 |
#include <dev/virtio/scsi/virtio_scsivar.h> |
67 |
#include <dev/virtio/scsi/virtio_scsivar.h> |
| 68 |
|
68 |
|
|
|
69 |
#include <sys/types.h> |
| 70 |
#include <machine/atomic.h> |
| 71 |
|
| 69 |
#include "virtio_if.h" |
72 |
#include "virtio_if.h" |
| 70 |
|
73 |
|
| 71 |
static int vtscsi_modevent(module_t, int, void *); |
74 |
static int vtscsi_modevent(module_t, int, void *); |
|
Lines 1629-1634
vtscsi_set_request_lun(struct ccb_hdr *ccbh, uint8_t lun[])
Link Here
|
| 1629 |
lun[3] = ccbh->target_lun & 0xFF; |
1632 |
lun[3] = ccbh->target_lun & 0xFF; |
| 1630 |
} |
1633 |
} |
| 1631 |
|
1634 |
|
|
|
1635 |
static uint32_t counter = 0; |
| 1636 |
|
| 1632 |
static void |
1637 |
static void |
| 1633 |
vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio, |
1638 |
vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio, |
| 1634 |
struct virtio_scsi_cmd_req *cmd_req) |
1639 |
struct virtio_scsi_cmd_req *cmd_req) |
|
Lines 1650-1657
vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio,
Link Here
|
| 1650 |
break; |
1655 |
break; |
| 1651 |
} |
1656 |
} |
| 1652 |
|
1657 |
|
|
|
1658 |
// This code used to use the csio pointer as tag, but |
| 1659 |
// CTL truncates the tag to 32 bit which resulted in |
| 1660 |
// overlapping tags under load. Cargo cult the iSCSI |
| 1661 |
// tag handling. |
| 1662 |
// The iSCSI code assumes that operations won't be pending |
| 1663 |
// long enough to still to witness the 32 bit counter |
| 1664 |
// wrapping. The maximum value was reserved. |
| 1665 |
// The reservation could be an iSCSI only special case, |
| 1666 |
// but it shouldn't hurt performance to increment twice |
| 1667 |
// once every 2**32 commands. |
| 1668 |
// |
| 1669 |
// As I'm just hacking on this code without a sufficient |
| 1670 |
// understanding of its threading and locking I used an |
| 1671 |
// attomic fetchadd to increment the tag counter. |
| 1672 |
// The fetchadd operation is an atomic *post*-increment |
| 1673 |
// aka it returns the old tag value. |
| 1674 |
// |
| 1675 |
// TODO: Have this reviewed by someone with an understand of the |
| 1676 |
// SCSI specifications, VirtIO, and CAM. |
| 1677 |
// |
| 1678 |
// Questions: |
| 1679 |
// * The old code used the csio pointer as tag. Are there places |
| 1680 |
// expecting to map a tag back to the csio pointer? |
| 1681 |
// (Shouldn't have worked on 64 bit systems anyway). |
| 1682 |
// |
| 1683 |
// * Does the tag have to be stable for csio's lifetime e.g. |
| 1684 |
// during retries? |
| 1685 |
// |
| 1686 |
// Observations: |
| 1687 |
// * This change alone didn't prevent the (0x4D, 0xNN) |
| 1688 |
// overlapping tag. |
| 1689 |
uintptr_t tag; |
| 1690 |
do { |
| 1691 |
tag = atomic_fetchadd_32(&counter, 1); |
| 1692 |
} while ( __builtin_expect(tag == UINT32_MAX, false) ); |
| 1693 |
|
| 1653 |
vtscsi_set_request_lun(&csio->ccb_h, cmd_req->lun); |
1694 |
vtscsi_set_request_lun(&csio->ccb_h, cmd_req->lun); |
| 1654 |
cmd_req->tag = vtscsi_gtoh64(sc, (uintptr_t) csio); |
1695 |
cmd_req->tag = vtscsi_gtoh64(sc, tag); |
| 1655 |
cmd_req->task_attr = attr; |
1696 |
cmd_req->task_attr = attr; |
| 1656 |
|
1697 |
|
| 1657 |
memcpy(cmd_req->cdb, |
1698 |
memcpy(cmd_req->cdb, |
|
Lines 1664-1669
static void
Link Here
|
| 1664 |
vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *sc, struct ccb_hdr *ccbh, |
1705 |
vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *sc, struct ccb_hdr *ccbh, |
| 1665 |
uint32_t subtype, uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req) |
1706 |
uint32_t subtype, uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req) |
| 1666 |
{ |
1707 |
{ |
|
|
1708 |
// I don't know what if anything I'm breaking by silently replacing |
| 1709 |
// the tag value with a second atomic 32 bit counter. |
| 1710 |
// |
| 1711 |
// Silence compiler warnings about unused arguments. |
| 1712 |
(void)tag; |
| 1713 |
|
| 1714 |
do { |
| 1715 |
tag = atomic_fetchadd_32(&counter, 1); |
| 1716 |
} while ( __builtin_expect(tag == UINT32_MAX, false) ); |
| 1667 |
|
1717 |
|
| 1668 |
vtscsi_set_request_lun(ccbh, tmf_req->lun); |
1718 |
vtscsi_set_request_lun(ccbh, tmf_req->lun); |
| 1669 |
|
1719 |
|