summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2010-05-26 22:49:42 +0000
committermjacob <mjacob@FreeBSD.org>2010-05-26 22:49:42 +0000
commit39b696507f1a5623910a10e31faedf7281e3cc41 (patch)
tree814f54bc94bcdd3b953da0eada061521fa6b750d /sys/cam
parent7201725878b6cb600187de6a38ff7c846c85ba0b (diff)
downloadFreeBSD-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.c2
-rw-r--r--sys/cam/cam_ccb.h5
-rw-r--r--sys/cam/cam_xpt.c43
-rw-r--r--sys/cam/scsi/scsi_xpt.c17
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:
OpenPOWER on IntegriCloud