summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-01-11 16:10:11 +0000
committermav <mav@FreeBSD.org>2013-01-11 16:10:11 +0000
commit7abdc5dedac23730ba10af357dc5b40406a1b550 (patch)
treeaa6d0f0a2db002511f4306e0d0ccd1b9164e28a4
parent4059b9293fea590e8986a3c9ae8be3cea3f02a11 (diff)
downloadFreeBSD-src-7abdc5dedac23730ba10af357dc5b40406a1b550.zip
FreeBSD-src-7abdc5dedac23730ba10af357dc5b40406a1b550.tar.gz
Do not schedule periph for payload/TUR requests if reprobe is in progress
to avoid sending extra READ CAPACITY requests by dastart(). Schedule periph again on reprobe completion, or otherwise it may stuck indefinitely long. This should fix USB explore thread hanging on device unplug, waiting for periph destruction. Reported by: hselasky
-rw-r--r--sys/cam/scsi/scsi_da.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index cc61b8d..7854215 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1081,6 +1081,9 @@ daschedule(struct cam_periph *periph)
struct da_softc *softc = (struct da_softc *)periph->softc;
uint32_t prio;
+ if (softc->state != DA_STATE_NORMAL)
+ return;
+
/* Check if cam_periph_getccb() was called. */
prio = periph->immediate_priority;
@@ -1425,10 +1428,10 @@ daasync(void *callback_arg, u_int32_t code,
}
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ daschedule(periph);
}
}
/* FALLTHROUGH */
@@ -2168,6 +2171,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
struct da_softc *softc;
struct ccb_scsiio *csio;
u_int32_t priority;
+ da_ccb_state state;
softc = (struct da_softc *)periph->softc;
priority = done_ccb->ccb_h.pinfo.priority;
@@ -2175,7 +2179,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
csio = &done_ccb->csio;
- switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
+ state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
+ switch (state) {
case DA_CCB_BUFFER_IO:
case DA_CCB_DELETE:
{
@@ -2273,8 +2278,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
softc->outstanding_cmds);
}
- if ((csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) ==
- DA_CCB_DELETE) {
+ if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) {
bp1->bio_resid = bp->bio_resid;
@@ -2300,7 +2304,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
rdcap = NULL;
rcaplong = NULL;
- if (softc->state == DA_STATE_PROBE)
+ if (state == DA_CCB_PROBE)
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
else
rcaplong = (struct scsi_read_capacity_data_long *)
@@ -2313,7 +2317,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
u_int lbppbe; /* LB per physical block exponent. */
u_int lalba; /* Lowest aligned LBA. */
- if (softc->state == DA_STATE_PROBE) {
+ if (state == DA_CCB_PROBE) {
block_size = scsi_4btoul(rdcap->length);
maxsector = scsi_4btoul(rdcap->addr);
lbppbe = 0;
@@ -2426,7 +2430,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* If we tried READ CAPACITY(16) and failed,
* fallback to READ CAPACITY(10).
*/
- if ((softc->state == DA_STATE_PROBE2) &&
+ if ((state == DA_CCB_PROBE2) &&
(softc->flags & DA_FLAG_CAN_RC16) &&
(((csio->ccb_h.status & CAM_STATUS_MASK) ==
CAM_REQ_INVALID) ||
@@ -2506,7 +2510,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- softc->state = DA_STATE_NORMAL;
+ softc->state = DA_STATE_NORMAL;
+ daschedule(periph);
wakeup(&softc->disk->d_mediasize);
if ((softc->flags & DA_FLAG_PROBED) == 0) {
softc->flags |= DA_FLAG_PROBED;
@@ -2631,7 +2636,7 @@ damediapoll(void *arg)
struct cam_periph *periph = arg;
struct da_softc *softc = periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur && softc->outstanding_cmds == 0) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
daschedule(periph);
OpenPOWER on IntegriCloud