diff options
author | kib <kib@FreeBSD.org> | 2013-02-12 16:57:20 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-02-12 16:57:20 +0000 |
commit | bd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0 (patch) | |
tree | e550f2c754f1edf951a8b93963ebcfc4fa0d20ce /sys/cam | |
parent | e0a463e76c719f11788ec107b5aa3e2da4e57c0b (diff) | |
download | FreeBSD-src-bd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0.zip FreeBSD-src-bd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0.tar.gz |
Reform the busdma API so that new types may be added without modifying
every architecture's busdma_machdep.c. It is done by unifying the
bus_dmamap_load_buffer() routines so that they may be called from MI
code. The MD busdma is then given a chance to do any final processing
in the complete() callback.
The cam changes unify the bus_dmamap_load* handling in cam drivers.
The arm and mips implementations are updated to track virtual
addresses for sync(). Previously this was done in a type specific
way. Now it is done in a generic way by recording the list of
virtuals in the map.
Submitted by: jeff (sponsored by EMC/Isilon)
Reviewed by: kan (previous version), scottl,
mjacob (isp(4), no objections for target mode changes)
Discussed with: ian (arm changes)
Tested by: marius (sparc64), mips (jmallet), isci(4) on x86 (jharris),
amd64 (Fabian Keil <freebsd-listen@fabiankeil.de>)
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam_ccb.h | 10 | ||||
-rw-r--r-- | sys/cam/cam_xpt.c | 3 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend_cam_sim.c | 47 | ||||
-rw-r--r-- | sys/cam/ctl/scsi_ctl.c | 10 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_pass.c | 5 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_target.c | 2 |
6 files changed, 43 insertions, 34 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 1f12d91..a80880a 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -64,13 +64,19 @@ typedef enum { * Perform transport negotiation * with this command. */ - CAM_SCATTER_VALID = 0x00000010,/* Scatter/gather list is valid */ + CAM_DATA_ISPHYS = 0x00000010,/* Data type with physical addrs */ CAM_DIS_AUTOSENSE = 0x00000020,/* Disable autosense feature */ CAM_DIR_BOTH = 0x00000000,/* Data direction (00:IN/OUT) */ CAM_DIR_IN = 0x00000040,/* Data direction (01:DATA IN) */ CAM_DIR_OUT = 0x00000080,/* Data direction (10:DATA OUT) */ CAM_DIR_NONE = 0x000000C0,/* Data direction (11:no data) */ CAM_DIR_MASK = 0x000000C0,/* Data direction Mask */ + CAM_DATA_VADDR = 0x00000000,/* Data type (000:Virtual) */ + CAM_DATA_PADDR = 0x00000010,/* Data type (001:Physical) */ + CAM_DATA_SG = 0x00040000,/* Data type (010:sglist) */ + CAM_DATA_SG_PADDR = 0x00040010,/* Data type (011:sglist phys) */ + CAM_DATA_BIO = 0x00200000,/* Data type (100:bio) */ + CAM_DATA_MASK = 0x00240010,/* Data type mask */ CAM_SOFT_RST_OP = 0x00000100,/* Use Soft reset alternative */ CAM_ENG_SYNC = 0x00000200,/* Flush resid bytes on complete */ CAM_DEV_QFRZDIS = 0x00000400,/* Disable DEV Q freezing */ @@ -81,10 +87,8 @@ typedef enum { CAM_TAG_ACTION_VALID = 0x00008000,/* Use the tag action in this ccb*/ CAM_PASS_ERR_RECOVER = 0x00010000,/* Pass driver does err. recovery*/ CAM_DIS_DISCONNECT = 0x00020000,/* Disable disconnect */ - CAM_SG_LIST_PHYS = 0x00040000,/* SG list has physical addrs. */ CAM_MSG_BUF_PHYS = 0x00080000,/* Message buffer ptr is physical*/ CAM_SNS_BUF_PHYS = 0x00100000,/* Autosense data ptr is physical*/ - CAM_DATA_PHYS = 0x00200000,/* SG/Buffer data ptrs are phys. */ CAM_CDB_PHYS = 0x00400000,/* CDB poiner is physical */ CAM_ENG_SGLIST = 0x00800000,/* SG list is for the HBA engine */ diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 304d8c7..6bda94d 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -547,7 +547,8 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td * We can't deal with physical addresses for this * type of transaction. */ - if (inccb->ccb_h.flags & CAM_DATA_PHYS) { + if ((inccb->ccb_h.flags & CAM_DATA_MASK) != + CAM_DATA_VADDR) { error = EINVAL; break; } diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c index 43e4d61d..b885cbf 100644 --- a/sys/cam/ctl/ctl_frontend_cam_sim.c +++ b/sys/cam/ctl/ctl_frontend_cam_sim.c @@ -93,8 +93,8 @@ struct cfcs_softc { * handle physical addresses yet. That would require mapping things in * order to do the copy. */ -#define CFCS_BAD_CCB_FLAGS (CAM_DATA_PHYS | CAM_SG_LIST_PHYS | \ - CAM_MSG_BUF_PHYS | CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR |\ +#define CFCS_BAD_CCB_FLAGS (CAM_DATA_ISPHYS | CAM_MSG_BUF_PHYS | \ + CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR | \ CAM_SENSE_PHYS) int cfcs_init(void); @@ -379,36 +379,35 @@ cfcs_datamove(union ctl_io *io) * Simplify things on both sides by putting single buffers into a * single entry S/G list. */ - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) { - /* We should filter this out on entry */ - panic("%s: physical S/G list, should not get here", - __func__); - } else { - int len_seen; - - cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; - cam_sg_count = ccb->csio.sglist_cnt; - - for (i = 0, len_seen = 0; i < cam_sg_count; i++) { - if ((len_seen + cam_sglist[i].ds_len) >= - io->scsiio.kern_rel_offset) { - cam_sg_start = i; - cam_sg_offset = - io->scsiio.kern_rel_offset - - len_seen; - break; - } - len_seen += cam_sglist[i].ds_len; + switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { + case CAM_DATA_SG: { + int len_seen; + + cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; + cam_sg_count = ccb->csio.sglist_cnt; + + for (i = 0, len_seen = 0; i < cam_sg_count; i++) { + if ((len_seen + cam_sglist[i].ds_len) >= + io->scsiio.kern_rel_offset) { + cam_sg_start = i; + cam_sg_offset = io->scsiio.kern_rel_offset - + len_seen; + break; } + len_seen += cam_sglist[i].ds_len; } - } else { + break; + } + case CAM_DATA_VADDR: cam_sglist = &cam_sg_entry; cam_sglist[0].ds_len = ccb->csio.dxfer_len; cam_sglist[0].ds_addr = (bus_addr_t)ccb->csio.data_ptr; cam_sg_count = 1; cam_sg_start = 0; cam_sg_offset = io->scsiio.kern_rel_offset; + break; + default: + panic("Invalid CAM flags %#x", ccb->ccb_h.flags); } if (io->scsiio.kern_sg_entries > 0) { diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 5dc20e5..e9af881 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -876,6 +876,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) csio->cdb_len = atio->cdb_len; + flags &= ~CAM_DATA_MASK; if (io->scsiio.kern_sg_entries == 0) { /* No S/G list */ data_ptr = io->scsiio.kern_data_ptr; @@ -883,7 +884,9 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) csio->sglist_cnt = 0; if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) - flags |= CAM_DATA_PHYS; + flags |= CAM_DATA_PADDR; + else + flags |= CAM_DATA_VADDR; } else if (io->scsiio.kern_sg_entries <= (sizeof(cmd_info->cam_sglist)/ sizeof(cmd_info->cam_sglist[0]))) { @@ -907,11 +910,10 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) ctl_sglist[i].len; } csio->sglist_cnt = io->scsiio.kern_sg_entries; - flags |= CAM_SCATTER_VALID; if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) - flags |= CAM_SG_LIST_PHYS; + flags |= CAM_DATA_SG_PADDR; else - flags &= ~CAM_SG_LIST_PHYS; + flags &= ~CAM_DATA_SG; data_ptr = (uint8_t *)cam_sglist; dxfer_len = io->scsiio.kern_data_len; } else { diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c index fa6af7c..f3710c8 100644 --- a/sys/cam/scsi/scsi_pass.c +++ b/sys/cam/scsi/scsi_pass.c @@ -696,8 +696,11 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) * do the right thing, even if there isn't data to map, but since CCBs * without data are a reasonably common occurance (e.g. test unit * ready), it will save a few cycles if we check for it here. + * + * XXX What happens if a sg list is supplied? We don't filter that + * out. */ - if (((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) + if (((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && (((ccb->ccb_h.func_code == XPT_SCSI_IO || ccb->ccb_h.func_code == XPT_ATA_IO) && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)) diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c index c45e8d5..963b4e6 100644 --- a/sys/cam/scsi/scsi_target.c +++ b/sys/cam/scsi/scsi_target.c @@ -737,7 +737,7 @@ targsendccb(struct targ_softc *softc, union ccb *ccb, * without data are a reasonably common occurance (e.g. test unit * ready), it will save a few cycles if we check for it here. */ - if (((ccb_h->flags & CAM_DATA_PHYS) == 0) + if (((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && (((ccb_h->func_code == XPT_CONT_TARGET_IO) && ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE)) || (ccb_h->func_code == XPT_DEV_MATCH))) { |