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.
This commit is contained in:
Alexander Motin 2012-10-27 10:14:12 +00:00
parent 15a2601b29
commit 8cff7eb82f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=242175
3 changed files with 9 additions and 6 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -521,6 +521,7 @@ passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
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, caddr_t addr, int flag, struct thread *t
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, caddr_t addr, int flag, struct thread *t
*/
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;
}