Author: ken
Date: Fri Dec 10 21:38:51 2010
New Revision: 216361
URL: http://svn.freebsd.org/changeset/base/216361

Log:
  Fix a few issues related to the XPT_GDEV_ADVINFO CCB.
  
  camcontrol.c: In buildbusdevlist(), don't attempt to get call
                getdevid() for an unconfigured device, even when the
                verbose flag is set.  The cam_open_btl() call will almost
                certainly fail.
  
                Probe for the buffer size when issuing the XPT_GDEV_ADVINFO
                CCB.  Probing for the buffer size first helps us avoid
                allocating the maximum buffer size when it really may not
                be necessary.  This also helps avoid errors from
                cam_periph_mapmem() if we attempt to map more than MAXPHYS.
  
  cam_periph.c: In cam_periph_mapmem(), if the XPT_GDEV_ADVINFO CCB
                shows a bufsiz of 0, we don't have anything to map,
                so just return.
  
                Also, set the maximum mapping size to MAXPHYS
                instead of DFLTPHYS for XPT_GDEV_ADVINFO CCBs,
                since they don't actually go down to the hardware.
  
  scsi_pass.c:  Don't bother mapping the buffer in XPT_GDEV_ADVINFO
                CCBs if bufsiz is 0.

Modified:
  head/sbin/camcontrol/camcontrol.c
  head/sys/cam/cam_periph.c
  head/sys/cam/scsi/scsi_pass.c

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c   Fri Dec 10 20:27:50 2010        
(r216360)
+++ head/sbin/camcontrol/camcontrol.c   Fri Dec 10 21:38:51 2010        
(r216361)
@@ -5026,14 +5026,7 @@ getdevid(struct cam_devitem *item)
                goto bailout;
        }
 
-       item->device_id_len = CAM_SCSI_DEVID_MAXLEN;
-       item->device_id = malloc(item->device_id_len);
-       if (item->device_id == NULL) {
-               warn("%s: unable to allocate %d bytes", __func__,
-                    item->device_id_len);
-               retval = 1;
-               goto bailout;
-       }
+       item->device_id_len = 0;
 
        ccb = cam_getccb(dev);
        if (ccb == NULL) {
@@ -5044,12 +5037,19 @@ getdevid(struct cam_devitem *item)
 
        bzero(&(&ccb->ccb_h)[1],
              sizeof(union ccb) - sizeof(struct ccb_hdr));
+
+       /*
+        * On the first try, we just probe for the size of the data, and
+        * then allocate that much memory and try again.
+        */
+retry:
        ccb->ccb_h.func_code = XPT_GDEV_ADVINFO;
        ccb->ccb_h.flags = CAM_DIR_IN;
        ccb->cgdai.flags = CGDAI_FLAG_PROTO;
        ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID;
        ccb->cgdai.bufsiz = item->device_id_len;
-       ccb->cgdai.buf = (uint8_t *)item->device_id;
+       if (item->device_id_len != 0)
+               ccb->cgdai.buf = (uint8_t *)item->device_id;
 
        if (cam_send_ccb(dev, ccb) < 0) {
                warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
@@ -5063,6 +5063,29 @@ getdevid(struct cam_devitem *item)
                goto bailout;
        }
 
+       if (item->device_id_len == 0) {
+               /*
+                * This is our first time through.  Allocate the buffer,
+                * and then go back to get the data.
+                */
+               if (ccb->cgdai.provsiz == 0) {
+                       warnx("%s: invalid .provsiz field returned with "
+                            "XPT_GDEV_ADVINFO CCB", __func__);
+                       retval = 1;
+                       goto bailout;
+               }
+               item->device_id_len = ccb->cgdai.provsiz;
+               item->device_id = malloc(item->device_id_len);
+               if (item->device_id == NULL) {
+                       warn("%s: unable to allocate %d bytes", __func__,
+                            item->device_id_len);
+                       retval = 1;
+                       goto bailout;
+               }
+               ccb->ccb_h.status = CAM_REQ_INPROG;
+               goto retry;
+       }
+
 bailout:
        if (dev != NULL)
                cam_close_device(dev);
@@ -5158,9 +5181,8 @@ buildbusdevlist(struct cam_devlist *devl
                                dev_result = 
                                     &ccb.cdm.matches[i].result.device_result;
 
-                               if ((dev_result->flags
-                                    & DEV_RESULT_UNCONFIGURED)
-                                && ((arglist & CAM_ARG_VERBOSE) == 0)) {
+                               if (dev_result->flags &
+                                   DEV_RESULT_UNCONFIGURED) {
                                        skip_device = 1;
                                        break;
                                } else

Modified: head/sys/cam/cam_periph.c
==============================================================================
--- head/sys/cam/cam_periph.c   Fri Dec 10 20:27:50 2010        (r216360)
+++ head/sys/cam/cam_periph.c   Fri Dec 10 21:38:51 2010        (r216361)
@@ -658,10 +658,19 @@ cam_periph_mapmem(union ccb *ccb, struct
                numbufs = 2;
                break;
        case XPT_GDEV_ADVINFO:
+               if (ccb->cgdai.bufsiz == 0)
+                       return (0);
+
                data_ptrs[0] = (uint8_t **)&ccb->cgdai.buf;
                lengths[0] = ccb->cgdai.bufsiz;
                dirs[0] = CAM_DIR_IN;
                numbufs = 1;
+
+               /*
+                * This request will not go to the hardware, no reason
+                * to be so strict. vmapbuf() is able to map up to MAXPHYS.
+                */
+               maxmap = MAXPHYS;
                break;
        default:
                return(EINVAL);

Modified: head/sys/cam/scsi/scsi_pass.c
==============================================================================
--- head/sys/cam/scsi/scsi_pass.c       Fri Dec 10 20:27:50 2010        
(r216360)
+++ head/sys/cam/scsi/scsi_pass.c       Fri Dec 10 21:38:51 2010        
(r216361)
@@ -525,9 +525,9 @@ passsendccb(struct cam_periph *periph, u
         * if they haven't passed in a physical memory pointer,
         * and if there is actually an I/O operation to perform.
         * cam_periph_mapmem() supports SCSI, ATA, SMP, ADVINFO and device
-        * match CCBs.  For the SCSI and ATA CCBs, we only pass the CCB in if
-        * there's actually data to map.  cam_periph_mapmem() will do the
-        * right thing, even if there isn't data to map, but since CCBs
+        * match CCBs.  For the SCSI, ATA and ADVINFO CCBs, we only pass the
+        * CCB in if there's actually data to map.  cam_periph_mapmem() will
+        * 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.
         */
@@ -537,7 +537,8 @@ passsendccb(struct cam_periph *periph, u
            && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE))
          || (ccb->ccb_h.func_code == XPT_DEV_MATCH)
          || (ccb->ccb_h.func_code == XPT_SMP_IO)
-         || (ccb->ccb_h.func_code == XPT_GDEV_ADVINFO))) {
+         || ((ccb->ccb_h.func_code == XPT_GDEV_ADVINFO)
+          && (ccb->cgdai.bufsiz > 0)))) {
 
                bzero(&mapinfo, sizeof(mapinfo));
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to