Author: mav
Date: Sat Oct 27 10:14:12 2012
New Revision: 242175
URL: http://svn.freebsd.org/changeset/base/242175

Log:
  Remove priority enforcement from xpt_ation().  It is not good and even not
  safe in some cases to reduce CCB priority after it was scheduled with high
  priority.  This fixes reproducible deadlock when command sent through the
  pass interface while ATA XPT recovers from command timeout.
  
  Instead of that enforce priority at passioctl().  libcam provides no obvious
  interface to specify CCB priority and so much (all?) code specifies zero
  (highest) priority.  This change limits pass CCBs priority to NORMAL run
  level, allowing XPT to complete bus and device recovery after reset before
  running any payload.

Modified:
  head/sys/cam/cam.h
  head/sys/cam/cam_xpt.c
  head/sys/cam/scsi/scsi_pass.c

Modified: head/sys/cam/cam.h
==============================================================================
--- head/sys/cam/cam.h  Sat Oct 27 09:40:29 2012        (r242174)
+++ head/sys/cam/cam.h  Sat Oct 27 10:14:12 2012        (r242175)
@@ -83,6 +83,7 @@ typedef struct {
 #define CAM_PRIORITY_NORMAL    ((CAM_RL_NORMAL << 8) + 0x80)
 #define CAM_PRIORITY_NONE      (u_int32_t)-1
 #define CAM_PRIORITY_TO_RL(x)  ((x) >> 8)
+#define CAM_RL_TO_PRIORITY(x)  ((x) << 8)
        u_int32_t generation;
        int       index;
 #define CAM_UNQUEUED_INDEX     -1

Modified: head/sys/cam/cam_xpt.c
==============================================================================
--- head/sys/cam/cam_xpt.c      Sat Oct 27 09:40:29 2012        (r242174)
+++ head/sys/cam/cam_xpt.c      Sat Oct 27 10:14:12 2012        (r242175)
@@ -2468,9 +2468,6 @@ xpt_action(union ccb *start_ccb)
        CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action\n"));
 
        start_ccb->ccb_h.status = CAM_REQ_INPROG;
-       /* Compatibility for RL-unaware code. */
-       if (CAM_PRIORITY_TO_RL(start_ccb->ccb_h.pinfo.priority) == 0)
-           start_ccb->ccb_h.pinfo.priority += CAM_PRIORITY_NORMAL - 1;
        (*(start_ccb->ccb_h.path->bus->xport->action))(start_ccb);
 }
 

Modified: head/sys/cam/scsi/scsi_pass.c
==============================================================================
--- head/sys/cam/scsi/scsi_pass.c       Sat Oct 27 09:40:29 2012        
(r242174)
+++ head/sys/cam/scsi/scsi_pass.c       Sat Oct 27 10:14:12 2012        
(r242175)
@@ -521,6 +521,7 @@ passioctl(struct cdev *dev, u_long cmd, 
        struct  cam_periph *periph;
        struct  pass_softc *softc;
        int     error;
+       uint32_t priority;
 
        periph = (struct cam_periph *)dev->si_drv1;
        if (periph == NULL)
@@ -553,6 +554,11 @@ passioctl(struct cdev *dev, u_long cmd, 
                        break;
                }
 
+               /* Compatibility for RL/priority-unaware code. */
+               priority = inccb->ccb_h.pinfo.priority;
+               if (priority < CAM_RL_TO_PRIORITY(CAM_RL_NORMAL))
+                   priority += CAM_RL_TO_PRIORITY(CAM_RL_NORMAL);
+
                /*
                 * Non-immediate CCBs need a CCB from the per-device pool
                 * of CCBs, which is scheduled by the transport layer.
@@ -561,15 +567,14 @@ passioctl(struct cdev *dev, u_long cmd, 
                 */
                if ((inccb->ccb_h.func_code & XPT_FC_QUEUED)
                 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) {
-                       ccb = cam_periph_getccb(periph,
-                                               inccb->ccb_h.pinfo.priority);
+                       ccb = cam_periph_getccb(periph, priority);
                        ccb_malloced = 0;
                } else {
                        ccb = xpt_alloc_ccb_nowait();
 
                        if (ccb != NULL)
                                xpt_setup_ccb(&ccb->ccb_h, periph->path,
-                                             inccb->ccb_h.pinfo.priority);
+                                             priority);
                        ccb_malloced = 1;
                }
 
_______________________________________________
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