Author: mjacob
Date: Wed May 26 22:49:42 2010
New Revision: 208582
URL: http://svn.freebsd.org/changeset/base/208582

Log:
  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

Modified:
  head/sys/cam/ata/ata_xpt.c
  head/sys/cam/cam_ccb.h
  head/sys/cam/cam_xpt.c
  head/sys/cam/scsi/scsi_xpt.c
  head/sys/dev/isp/isp_freebsd.c

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c  Wed May 26 22:38:45 2010        (r208581)
+++ head/sys/cam/ata/ata_xpt.c  Wed May 26 22:49:42 2010        (r208582)
@@ -1185,6 +1185,7 @@ ata_scan_bus(struct cam_periph *periph, 
                  ("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:

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h      Wed May 26 22:38:45 2010        (r208581)
+++ head/sys/cam/cam_ccb.h      Wed May 26 22:49:42 2010        (r208582)
@@ -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 */

Modified: head/sys/cam/cam_xpt.c
==============================================================================
--- head/sys/cam/cam_xpt.c      Wed May 26 22:38:45 2010        (r208581)
+++ head/sys/cam/cam_xpt.c      Wed May 26 22:49:42 2010        (r208582)
@@ -446,23 +446,36 @@ xptioctl(struct cdev *dev, u_long cmd, c
                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);

Modified: head/sys/cam/scsi/scsi_xpt.c
==============================================================================
--- head/sys/cam/scsi/scsi_xpt.c        Wed May 26 22:38:45 2010        
(r208581)
+++ head/sys/cam/scsi/scsi_xpt.c        Wed May 26 22:49:42 2010        
(r208582)
@@ -1494,12 +1494,13 @@ scsi_scan_bus(struct cam_periph *periph,
                  ("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,
 
                /* 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,
                        }
                }
 
-               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,
 
  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:

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c      Wed May 26 22:38:45 2010        
(r208581)
+++ head/sys/dev/isp/isp_freebsd.c      Wed May 26 22:49:42 2010        
(r208582)
@@ -3893,19 +3893,14 @@ isp_make_here(ispsoftc_t *isp, int chan,
        }
 
        /*
-        * Allocate a CCB, create a wildcard path for this bus/target and 
schedule a rescan.
+        * Allocate a CCB, create a wildcard path for this target and schedule 
a rescan.
         */
        ccb = xpt_alloc_ccb_nowait();
        if (ccb == NULL) {
                isp_prt(isp, ISP_LOGWARN, "Chan %d unable to alloc CCB for 
rescan", chan);
                return;
        }
-       /*
-        * xpt_rescan only honors wildcard in the target field. 
-        * Scan the whole bus instead of target, which will then
-        * force a scan of all luns.
-        */
-       if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, 
cam_sim_path(fc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+       if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, 
cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
                isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
                xpt_free_ccb(ccb);
                return;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to