Add PIM_SEQSCAN for HBA misc flags and code that understands
authorPeter Avalos <pavalos@dragonflybsd.org>
Sun, 2 Dec 2007 04:22:31 +0000 (04:22 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sun, 2 Dec 2007 04:22:31 +0000 (04:22 +0000)
what to do with it.

This forces us to scan targets sequentially, not in parallel.
The reason we might want to do this is that SPI negotiation
might not work right at the SIM level if we try to do it
in parallel.

If PIM_SEQSCAN is not set (default), the original behaviour for
probing is unchanged.

LUN probing is still done in parallel for each target in either
case.

Obtained-from: FreeBSD

sys/bus/cam/cam_ccb.h
sys/bus/cam/cam_xpt.c

index 6fc4101..90b4843 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/cam/cam_ccb.h,v 1.15.2.3 2003/07/29 04:00:34 njl Exp $
- * $DragonFly: src/sys/bus/cam/cam_ccb.h,v 1.14 2007/12/02 03:01:55 pavalos Exp $
+ * $DragonFly: src/sys/bus/cam/cam_ccb.h,v 1.15 2007/12/02 04:22:31 pavalos Exp $
  */
 
 #ifndef _CAM_CAM_CCB_H
@@ -513,7 +513,8 @@ typedef enum {
        PIM_NOREMOVE    = 0x40, /* Removeable devices not included in scan */
        PIM_NOINITIATOR = 0x20, /* Initiator role not supported. */
        PIM_NOBUSRESET  = 0x10, /* User has disabled initial BUS RESET */
-       PIM_NO_6_BYTE   = 0x08  /* Do not send 6-byte commands */
+       PIM_NO_6_BYTE   = 0x08, /* Do not send 6-byte commands */
+       PIM_SEQSCAN     = 0x04  /* Do bus scans sequentially, not in parallel */
 } pi_miscflag;
 
 #ifdef CAM_NEW_TRAN_CODE
index 74f0813..ffaec17 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/cam/cam_xpt.c,v 1.80.2.18 2002/12/09 17:31:55 gibbs Exp $
- * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.58 2007/12/02 03:41:58 pavalos Exp $
+ * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.59 2007/12/02 04:22:31 pavalos Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -5116,7 +5116,7 @@ xpt_find_device(struct cam_et *target, lun_id_t lun_id)
 typedef struct {
        union   ccb *request_ccb;
        struct  ccb_pathinq *cpi;
-       int     pending_count;
+       int     counter;
 } xpt_scan_bus_info;
 
 /*
@@ -5173,17 +5173,23 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
                max_target = scan_info->cpi->max_target;
                initiator_id = scan_info->cpi->initiator_id;
 
+
                /*
-                * Don't count the initiator if the
-                * initiator is addressable.
+                * We can scan all targets in parallel, or do it sequentially.
                 */
-               scan_info->pending_count = max_target + 1;
-               if (initiator_id <= max_target)
-                       scan_info->pending_count--;
-
+               if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
+                       max_target = 0;
+                       scan_info->counter = 0;
+               } else {
+                       scan_info->counter = scan_info->cpi->max_target + 1;
+                       if (scan_info->cpi->initiator_id < scan_info->counter) {
+                               scan_info->counter--;
+                       }
+               }
+               
                for (i = 0; i <= max_target; i++) {
                        cam_status status;
-                       if (i == initiator_id)
+                       if (i == initiator_id)
                                continue;
 
                        status = xpt_create_path(&path, xpt_periph,
@@ -5193,6 +5199,10 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
                                kprintf("xpt_scan_bus: xpt_create_path failed"
                                       " with status %#x, bus scan halted\n",
                                       status);
+                               kfree(scan_info, M_TEMP);
+                               request_ccb->ccb_h.status = status;
+                               xpt_free_ccb(work_ccb);
+                               xpt_done(request_ccb);
                                break;
                        }
                        work_ccb = xpt_alloc_ccb();
@@ -5208,6 +5218,8 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
        }
        case XPT_SCAN_LUN:
        {
+               cam_status status;
+               struct cam_path *path;
                xpt_scan_bus_info *scan_info;
                path_id_t path_id;
                target_id_t target_id;
@@ -5269,44 +5281,79 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
                        }
                }
 
+               /*
+                * Free the current request path- we're done with it.
+                */
                xpt_free_path(request_ccb->ccb_h.path);
 
-               /* Check Bounds */
-               if ((lun_id == request_ccb->ccb_h.target_lun)
-                || lun_id > scan_info->cpi->max_lun) {
-                       /* We're done */
-
-                       xpt_free_ccb(request_ccb);
-                       scan_info->pending_count--;
-                       if (scan_info->pending_count == 0) {
+               /*
+                * Check to see if we scan any further luns.
+                */
+               if (lun_id == request_ccb->ccb_h.target_lun
+                 || lun_id > scan_info->cpi->max_lun) {
+                       int done;
+
+ hop_again:
+                       done = 0;
+                       if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
+                               scan_info->counter++;
+                               if (scan_info->counter == 
+                                   scan_info->cpi->initiator_id) {
+                                       scan_info->counter++;
+                               }
+                               if (scan_info->counter >=
+                                   scan_info->cpi->max_target+1) {
+                                       done = 1;
+                               }
+                       } else {
+                               scan_info->counter--;
+                               if (scan_info->counter == 0) {
+                                       done = 1;
+                               }
+                       }
+                       if (done) {
+                               xpt_free_ccb(request_ccb);
                                xpt_free_ccb((union ccb *)scan_info->cpi);
                                request_ccb = scan_info->request_ccb;
                                kfree(scan_info, M_TEMP);
                                request_ccb->ccb_h.status = CAM_REQ_CMP;
                                xpt_done(request_ccb);
+                               break;
                        }
-               } else {
-                       /* Try the next device */
-                       struct cam_path *path;
-                       cam_status status;
 
+                       if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) {
+                               break;
+                       }
+                       status = xpt_create_path(&path, xpt_periph,
+                           scan_info->request_ccb->ccb_h.path_id,
+                           scan_info->counter, 0);
+                       if (status != CAM_REQ_CMP) {
+                               kprintf("xpt_scan_bus: xpt_create_path failed"
+                                   " with status %#x, bus scan halted\n",
+                                   status);
+                               xpt_free_ccb(request_ccb);
+                               xpt_free_ccb((union ccb *)scan_info->cpi);
+                               request_ccb = scan_info->request_ccb;
+                               kfree(scan_info, M_TEMP);
+                               request_ccb->ccb_h.status = status;
+                               xpt_done(request_ccb);
+                               break;
+                       }
+                       xpt_setup_ccb(&request_ccb->ccb_h, path,
+                           request_ccb->ccb_h.pinfo.priority);
+                       request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+                       request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
+                       request_ccb->ccb_h.ppriv_ptr0 = scan_info;
+                       request_ccb->crcn.flags =
+                           scan_info->request_ccb->crcn.flags;
+               } else {
                        status = xpt_create_path(&path, xpt_periph,
                                                 path_id, target_id, lun_id);
                        if (status != CAM_REQ_CMP) {
                                kprintf("xpt_scan_bus: xpt_create_path failed "
                                       "with status %#x, halting LUN scan\n",
                                       status);
-                               xpt_free_ccb(request_ccb);
-                               scan_info->pending_count--;
-                               if (scan_info->pending_count == 0) {
-                                       xpt_free_ccb(
-                                               (union ccb *)scan_info->cpi);
-                                       request_ccb = scan_info->request_ccb;
-                                       kfree(scan_info, M_TEMP);
-                                       request_ccb->ccb_h.status = CAM_REQ_CMP;
-                                       xpt_done(request_ccb);
-                               }
-                               break;
+                               goto hop_again;
                        }
                        xpt_setup_ccb(&request_ccb->ccb_h, path,
                                      request_ccb->ccb_h.pinfo.priority);
@@ -5315,8 +5362,8 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
                        request_ccb->ccb_h.ppriv_ptr0 = scan_info;
                        request_ccb->crcn.flags =
                                scan_info->request_ccb->crcn.flags;
-                       xpt_action(request_ccb);
                }
+               xpt_action(request_ccb);
                break;
        }
        default: