diff options
author | mjacob <mjacob@FreeBSD.org> | 2010-05-26 22:49:42 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2010-05-26 22:49:42 +0000 |
commit | 39b696507f1a5623910a10e31faedf7281e3cc41 (patch) | |
tree | 814f54bc94bcdd3b953da0eada061521fa6b750d /sys/cam | |
parent | 7201725878b6cb600187de6a38ff7c846c85ba0b (diff) | |
download | FreeBSD-src-39b696507f1a5623910a10e31faedf7281e3cc41.zip FreeBSD-src-39b696507f1a5623910a10e31faedf7281e3cc41.tar.gz |
Add a new primitive, XPT_SCAN_TGT, to cover the range between scanning a
whole bus (XPT_SCAN_BUS) and a single lun on that bus (XPT_SCAN_LUN).
It's less resource comsumptive than scanning a whole bus when the
caller knows only one target has changes.
Reviewed by: scsi@
Sponsored by: Panasas
MFC after: 1 month
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ata/ata_xpt.c | 2 | ||||
-rw-r--r-- | sys/cam/cam_ccb.h | 5 | ||||
-rw-r--r-- | sys/cam/cam_xpt.c | 43 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_xpt.c | 17 |
4 files changed, 53 insertions, 14 deletions
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index daadc36..c9be596 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -1185,6 +1185,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) ("xpt_scan_bus\n")); switch (request_ccb->ccb_h.func_code) { case XPT_SCAN_BUS: + case XPT_SCAN_TGT: /* Find out the characteristics of the bus */ work_ccb = xpt_alloc_ccb_nowait(); if (work_ccb == NULL) { @@ -1526,6 +1527,7 @@ ata_action(union ccb *start_ccb) break; } case XPT_SCAN_BUS: + case XPT_SCAN_TGT: ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); break; case XPT_SCAN_LUN: diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index c5ac35e..73ddb33 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -184,6 +184,11 @@ typedef enum { /* * Set SIM specific knob values. */ + + XPT_SCAN_TGT = 0x1E | XPT_FC_QUEUED | XPT_FC_USER_CCB + | XPT_FC_XPT_ONLY, + /* Scan Target */ + /* HBA engine commands 0x20->0x2F */ XPT_ENG_INQ = 0x20 | XPT_FC_XPT_ONLY, /* HBA engine feature inquiry */ diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 5d83539..2284006 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -446,23 +446,36 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td inccb = (union ccb *)addr; bus = xpt_find_bus(inccb->ccb_h.path_id); - if (bus == NULL) { - error = EINVAL; + if (bus == NULL) + return (EINVAL); + + switch (inccb->ccb_h.func_code) { + case XPT_SCAN_BUS: + case XPT_RESET_BUS: + if (inccb->ccb_h.target_id != CAM_TARGET_WILDCARD || + inccb->ccb_h.target_lun != CAM_LUN_WILDCARD) { + xpt_release_bus(bus); + return (EINVAL); + } + break; + case XPT_SCAN_TGT: + if (inccb->ccb_h.target_id == CAM_TARGET_WILDCARD || + inccb->ccb_h.target_lun != CAM_LUN_WILDCARD) { + xpt_release_bus(bus); + return (EINVAL); + } + break; + default: break; } switch(inccb->ccb_h.func_code) { case XPT_SCAN_BUS: case XPT_RESET_BUS: - if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD) - || (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD)) { - error = EINVAL; - break; - } - /* FALLTHROUGH */ case XPT_PATH_INQ: case XPT_ENG_INQ: case XPT_SCAN_LUN: + case XPT_SCAN_TGT: ccb = xpt_alloc_ccb(); @@ -839,11 +852,21 @@ xpt_rescan(union ccb *ccb) struct ccb_hdr *hdr; /* Prepare request */ - if (ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD || + if (ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD && ccb->ccb_h.path->device->lun_id == CAM_LUN_WILDCARD) ccb->ccb_h.func_code = XPT_SCAN_BUS; - else + else if (ccb->ccb_h.path->target->target_id != CAM_TARGET_WILDCARD && + ccb->ccb_h.path->device->lun_id == CAM_LUN_WILDCARD) + ccb->ccb_h.func_code = XPT_SCAN_TGT; + else if (ccb->ccb_h.path->target->target_id != CAM_TARGET_WILDCARD && + ccb->ccb_h.path->device->lun_id != CAM_LUN_WILDCARD) ccb->ccb_h.func_code = XPT_SCAN_LUN; + else { + xpt_print(ccb->ccb_h.path, "illegal scan path\n"); + xpt_free_path(ccb->ccb_h.path); + xpt_free_ccb(ccb); + return; + } ccb->ccb_h.ppriv_ptr1 = ccb->ccb_h.cbfcnp; ccb->ccb_h.cbfcnp = xpt_rescan_done; xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, CAM_PRIORITY_XPT); diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 6e61cb8..c4043ad 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -1494,12 +1494,13 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) ("scsi_scan_bus\n")); switch (request_ccb->ccb_h.func_code) { case XPT_SCAN_BUS: + case XPT_SCAN_TGT: { scsi_scan_bus_info *scan_info; union ccb *work_ccb, *reset_ccb; struct cam_path *path; u_int i; - u_int max_target; + u_int low_target, max_target; u_int initiator_id; /* Find out the characteristics of the bus */ @@ -1564,13 +1565,18 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) /* Cache on our stack so we can work asynchronously */ max_target = scan_info->cpi->max_target; + low_target = 0; initiator_id = scan_info->cpi->initiator_id; /* * We can scan all targets in parallel, or do it sequentially. */ - if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { + + if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { + max_target = low_target = request_ccb->ccb_h.target_id; + scan_info->counter = 0; + } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { max_target = 0; scan_info->counter = 0; } else { @@ -1580,7 +1586,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) } } - for (i = 0; i <= max_target; i++) { + for (i = low_target; i <= max_target; i++) { cam_status status; if (i == initiator_id) continue; @@ -1695,7 +1701,9 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) hop_again: done = 0; - if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { + if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { + done = 1; + } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { scan_info->counter++; if (scan_info->counter == scan_info->cpi->initiator_id) { @@ -2016,6 +2024,7 @@ scsi_action(union ccb *start_ccb) break; } case XPT_SCAN_BUS: + case XPT_SCAN_TGT: scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); break; case XPT_SCAN_LUN: |