When probing a newly found device, don't automatically assume that the

device supports retrieving a serial number.  Instead, first query the
list of VPD pages it does support, and only query the serial number if
it's supported, else silently move on.  This eliminates a lot of noise
during verbose booting, and will likely eliminate the need for most
NOSERIAL quirks.
This commit is contained in:
Scott Long 2008-02-27 08:47:13 +00:00
parent 6c1f51148a
commit 4b800c7df1

View File

@ -464,7 +464,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
{
/* I can't believe we need a quirk for DPT volumes. */
{ T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" },
CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS,
CAM_QUIRK_NOLUNS,
/*mintags*/0, /*maxtags*/255
},
{
@ -495,7 +495,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
"EXB-8200*", "*"
},
CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
/*
@ -506,7 +506,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
"IPL-6860*", "*"
},
CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
/*
@ -549,17 +549,6 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
},
CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
},
{
/*
* Maxtor Personal Storage 3000XT (Firewire)
* hangs upon serial number probing.
*/
{
T_DIRECT, SIP_MEDIA_FIXED, "Maxtor",
"1394 storage", "*"
},
CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
},
{
/*
* Would repond to all LUNs if asked for.
@ -619,18 +608,6 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
{ T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" },
CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
/*
* Western Digital My Book 250GB (USB)
* hangs upon serial number probing.
* PR: 107495
*/
{
T_DIRECT, SIP_MEDIA_FIXED, "WD",
"2500JB External", "*"
},
CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
},
{
/* Default tagged queuing parameters for all devices */
{
@ -5474,7 +5451,8 @@ typedef enum {
PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */
PROBE_FULL_INQUIRY,
PROBE_MODE_SENSE,
PROBE_SERIAL_NUM,
PROBE_SERIAL_NUM_0,
PROBE_SERIAL_NUM_1,
PROBE_TUR_FOR_NEGOTIATION,
PROBE_INQUIRY_BASIC_DV1,
PROBE_INQUIRY_BASIC_DV2,
@ -5817,10 +5795,42 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
}
xpt_print(periph->path, "Unable to mode sense control page - "
"malloc failure\n");
softc->action = PROBE_SERIAL_NUM;
softc->action = PROBE_SERIAL_NUM_0;
}
/* FALLTHROUGH */
case PROBE_SERIAL_NUM:
case PROBE_SERIAL_NUM_0:
{
struct scsi_vpd_supported_page_list *vpd_list = NULL;
struct cam_ed *device;
device = periph->path->device;
if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0) {
vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT,
M_NOWAIT | M_ZERO);
}
if (vpd_list != NULL) {
scsi_inquiry(csio,
/*retries*/4,
probedone,
MSG_SIMPLE_Q_TAG,
(u_int8_t *)vpd_list,
sizeof(*vpd_list),
/*evpd*/TRUE,
SVPD_SUPPORTED_PAGE_LIST,
SSD_MIN_SIZE,
/*timeout*/60 * 1000);
break;
}
/*
* We'll have to do without, let our probedone
* routine finish up for us.
*/
start_ccb->csio.data_ptr = NULL;
probedone(periph, start_ccb);
return;
}
case PROBE_SERIAL_NUM_1:
{
struct scsi_vpd_unit_serial_number *serial_buf;
struct cam_ed* device;
@ -5830,10 +5840,8 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
device->serial_num = NULL;
device->serial_num_len = 0;
if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0)
serial_buf = (struct scsi_vpd_unit_serial_number *)
malloc(sizeof(*serial_buf), M_CAMXPT,
M_NOWAIT | M_ZERO);
serial_buf = (struct scsi_vpd_unit_serial_number *)
malloc(sizeof(*serial_buf), M_CAMXPT, M_NOWAIT|M_ZERO);
if (serial_buf != NULL) {
scsi_inquiry(csio,
@ -6058,7 +6066,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
if (INQ_DATA_TQ_ENABLED(inq_buf))
softc->action = PROBE_MODE_SENSE;
else
softc->action = PROBE_SERIAL_NUM;
softc->action = PROBE_SERIAL_NUM_0;
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
@ -6123,11 +6131,62 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
}
xpt_release_ccb(done_ccb);
free(mode_hdr, M_CAMXPT);
softc->action = PROBE_SERIAL_NUM;
softc->action = PROBE_SERIAL_NUM_0;
xpt_schedule(periph, priority);
return;
}
case PROBE_SERIAL_NUM:
case PROBE_SERIAL_NUM_0:
{
struct ccb_scsiio *csio;
struct scsi_vpd_supported_page_list *page_list;
int length, serialnum_supported, i;
serialnum_supported = 0;
csio = &done_ccb->csio;
page_list =
(struct scsi_vpd_supported_page_list *)csio->data_ptr;
if (page_list == NULL) {
/*
* Don't process the command as it was never sent
*/
} else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
&& (page_list->length > 0)) {
length = min(page_list->length,
SVPD_SUPPORTED_PAGES_SIZE);
for (i = 0; i < length; i++) {
if (page_list->list[i] ==
SVPD_UNIT_SERIAL_NUMBER) {
serialnum_supported = 1;
break;
}
}
} else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA|SF_NO_PRINT,
&softc->saved_ccb) == ERESTART) {
return;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
/*run_queue*/TRUE);
}
if (page_list != NULL)
free(page_list, M_DEVBUF);
if (serialnum_supported) {
xpt_release_ccb(done_ccb);
softc->action = PROBE_SERIAL_NUM_1;
xpt_schedule(periph, priority);
return;
}
xpt_release_ccb(done_ccb);
softc->action = PROBE_TUR_FOR_NEGOTIATION;
xpt_schedule(periph, done_ccb->ccb_h.pinfo.priority);
return;
}
case PROBE_SERIAL_NUM_1:
{
struct ccb_scsiio *csio;
struct scsi_vpd_unit_serial_number *serial_buf;