Date: Tue, 24 Apr 2007 22:44:54 -0700 From: "Josh Carroll" <josh.carroll@gmail.com> To: "Thomas Quinot" <thomas@freebsd.org> Cc: freebsd-scsi@freebsd.org, bug-followup@freebsd.org, c47g@gmx.at Subject: Re: kern/103602: drive gets wedged on READ CD CAPACITY if no disc is in Message-ID: <8cb6106e0704242244i6b23e0a3s9a7c47cefd7975d7@mail.gmail.com> In-Reply-To: <8cb6106e0704242119h4a09d7d4v667d64071b3bd053@mail.gmail.com> References: <8cb6106e0703261318o120c620ar6b2461802632fc01@mail.gmail.com> <8cb6106e0703281531k4c5bebecp5566c64c8f458a74@mail.gmail.com> <8cb6106e0704030039if46397fvfc993d9c9e19e1fc@mail.gmail.com> <8cb6106e0704032107w457026b1t1e04ed11008af48a@mail.gmail.com> <20070424162008.GA7087@melamine.cuivre.fr.eu.org> <8cb6106e0704240929j38178df6k1b6391446c69a2ae@mail.gmail.com> <20070424165843.GD7087@melamine.cuivre.fr.eu.org> <8cb6106e0704241132vfa6b312s3b4cbea0c823b796@mail.gmail.com> <8cb6106e0704241845r737dca05p50fc967a61d66677@mail.gmail.com> <8cb6106e0704242119h4a09d7d4v667d64071b3bd053@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Oops, I think gmail attached the patch as a MIME encoded attachment. Here's the patch: diff -urN sys.old/cam/cam_xpt.c sys/cam/cam_xpt.c --- sys.old/cam/cam_xpt.c Sat Sep 23 11:42:08 2006 +++ sys/cam/cam_xpt.c Tue Apr 24 13:31:28 2007 @@ -254,6 +254,11 @@ static struct xpt_quirk_entry xpt_quirk_table[] = { { + /* Hangs on INQUIRY with EVPD flag??? */ + { T_CDROM, SIP_MEDIA_REMOVABLE, sony, "DVD RW DRU*", "*" }, + CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0 + }, + { /* Reports QUEUE FULL for temporary resource shortages */ { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" }, /*quirks*/0, /*mintags*/24, /*maxtags*/32 diff -urN sys.old/cam/scsi/scsi_cd.c sys/cam/scsi/scsi_cd.c --- sys.old/cam/scsi/scsi_cd.c Wed Jul 26 00:48:51 2006 +++ sys/cam/scsi/scsi_cd.c Tue Apr 24 13:31:28 2007 @@ -107,9 +107,10 @@ } cd_flags; typedef enum { - CD_CCB_PROBE = 0x01, - CD_CCB_BUFFER_IO = 0x02, - CD_CCB_WAITING = 0x03, + CD_CCB_PROBE_TUR = 0x01, + CD_CCB_PROBE_RCAP = 0x02, + CD_CCB_BUFFER_IO = 0x03, + CD_CCB_WAITING = 0x04, CD_CCB_TYPE_MASK = 0x0F, CD_CCB_RETRY_UA = 0x10 } cd_ccb_state; @@ -135,7 +136,8 @@ }; typedef enum { - CD_STATE_PROBE, + CD_STATE_PROBE_RCAP, + CD_STATE_PROBE_TUR, CD_STATE_NORMAL } cd_state; @@ -675,7 +677,7 @@ bzero(softc, sizeof(*softc)); LIST_INIT(&softc->pending_ccbs); STAILQ_INIT(&softc->mode_queue); - softc->state = CD_STATE_PROBE; + softc->state = CD_STATE_PROBE_TUR; bioq_init(&softc->bio_queue); if (SID_IS_REMOVABLE(&cgd->inq_data)) softc->flags |= CD_FLAG_DISC_REMOVABLE; @@ -1561,7 +1563,21 @@ } break; } - case CD_STATE_PROBE: + case CD_STATE_PROBE_TUR: + { + csio = &start_ccb->csio; + scsi_test_unit_ready(csio, + /*retries*/4, + cddone, + MSG_SIMPLE_Q_TAG, + SSD_FULL_SIZE, + /*timeout*/10000); + start_ccb->ccb_h.ccb_bp = NULL; + start_ccb->ccb_h.ccb_state = CD_CCB_PROBE_TUR; + xpt_action(start_ccb); + break; + } + case CD_STATE_PROBE_RCAP: { rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), @@ -1582,7 +1598,7 @@ SSD_FULL_SIZE, /*timeout*/20000); start_ccb->ccb_h.ccb_bp = NULL; - start_ccb->ccb_h.ccb_state = CD_CCB_PROBE; + start_ccb->ccb_h.ccb_state = CD_CCB_PROBE_RCAP; xpt_action(start_ccb); break; } @@ -1673,7 +1689,35 @@ biofinish(bp, NULL, 0); break; } - case CD_CCB_PROBE: + case CD_CCB_PROBE_TUR: + { + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->state = CD_STATE_PROBE_RCAP; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, /*priority*/5); + return; + } + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + /* Don't wedge the queue */ + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + if (bootverbose) + cam_error_print(done_ccb, CAM_ESF_ALL, CAM_EPF_ALL); + /* + * The TUR generated an error, so there likely isn't media in + * the drive. Some drives lock up if they are sent a read + * capacity command while in this state, so avoid doing that. + */ + softc->state = CD_STATE_NORMAL; + xpt_release_ccb(done_ccb); + cam_periph_unlock(periph); + return; + } + case CD_CCB_PROBE_RCAP: { struct scsi_read_capacity_data *rdcap; char announce_buf[120]; /* diff -urN sys.old/dev/ata/atapi-cam.c sys/dev/ata/atapi-cam.c --- sys.old/dev/ata/atapi-cam.c Tue Apr 4 09:07:42 2006 +++ sys/dev/ata/atapi-cam.c Tue Apr 24 13:31:22 2007 @@ -505,10 +505,10 @@ switch (ccb_h->flags & CAM_DIR_MASK) { case CAM_DIR_IN: - request_flags |= ATA_R_READ|ATA_R_DMA; + request_flags |= ATA_R_READ; break; case CAM_DIR_OUT: - request_flags |= ATA_R_WRITE|ATA_R_DMA; + request_flags |= ATA_R_WRITE; break; case CAM_DIR_NONE: /* No flags need to be set */ @@ -517,8 +517,6 @@ device_printf(softc->dev, "unknown IO operation\n"); goto action_invalid; } - if (softc->atadev[tid]->mode < ATA_DMA) - request_flags &= ~ATA_R_DMA; if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) { printf("cannot allocate ATAPI/CAM hcb\n"); @@ -580,7 +578,23 @@ request->u.atapi.ccb[3] = request->u.atapi.ccb[1] & 0x1f; request->u.atapi.ccb[2] = 0; request->u.atapi.ccb[1] = 0; + + case READ_10: + /* FALLTHROUGH */ + case WRITE_10: + /* FALLTHROUGH */ + case READ_12: + /* FALLTHROUGH */ + case WRITE_12: + /* + * Enable DMA (if target supports it) for READ and WRITE commands + * only, as some combinations of drive, controller and chipset do + * not behave correctly when DMA is enabled for other commands. + */ + if (softc->atadev[tid]->mode >= ATA_DMA) + request_flags |= ATA_R_DMA; break; + } if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) { @@ -746,7 +760,9 @@ free_hcb(hcb); ccb->ccb_h.status = status | (ccb->ccb_h.status & ~(CAM_STATUS_MASK | CAM_SIM_QUEUED)); + mtx_lock(&Giant); xpt_done(ccb); + mtx_unlock(&Giant); } static void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?8cb6106e0704242244i6b23e0a3s9a7c47cefd7975d7>