summaryrefslogtreecommitdiffstats
path: root/sys/dev/aac
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2012-09-25 19:12:12 +0000
committerrstone <rstone@FreeBSD.org>2012-09-25 19:12:12 +0000
commit95b43675385916a51b0631b412c1affc748126a0 (patch)
tree7e0d1e1097fc5ed201a3d7c3e4bf6fbd7ca2f71d /sys/dev/aac
parentcabd8b8de74ed56244621b305e859bf472197ae1 (diff)
downloadFreeBSD-src-95b43675385916a51b0631b412c1affc748126a0.zip
FreeBSD-src-95b43675385916a51b0631b412c1affc748126a0.tar.gz
Some aac(4) adapters will always report that a direct access device is
offline in response to a INQUIRY command that does not retreive vital product data(I personally have observed the behaviour on an Adaptec 2405 and a 5805). Force the peripheral qualifier to "connected" so that upper layers correctly recognize that a disk is present. This bug was uncovered by r216236. Prior to that fix, aac(4) was accidentally clearing the peripheral qualifier for all inquiry commands. This fixes an issue where passthrough devices were not created for disks behind aac(4) controllers suffering from the bug. I have verified that if a disk is not present that we still properly detect that and not create the passthrough device. Sponsored by: Sandvine Incorporated MFC after: 1 week
Diffstat (limited to 'sys/dev/aac')
-rw-r--r--sys/dev/aac/aac_cam.c75
1 files changed, 48 insertions, 27 deletions
diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c
index 2fafa97..57e87da 100644
--- a/sys/dev/aac/aac_cam.c
+++ b/sys/dev/aac/aac_cam.c
@@ -527,6 +527,53 @@ aac_cam_poll(struct cam_sim *sim)
}
static void
+aac_cam_fix_inquiry(struct aac_softc *sc, union ccb *ccb)
+{
+ struct scsi_inquiry_data *inq;
+ uint8_t *data;
+ uint8_t device, qual;
+
+ /* If this is an inquiry command, fake things out */
+ if (ccb->ccb_h.flags & CAM_CDB_POINTER)
+ data = ccb->csio.cdb_io.cdb_ptr;
+ else
+ data = ccb->csio.cdb_io.cdb_bytes;
+
+ if (data[0] != INQUIRY)
+ return;
+
+ if (ccb->ccb_h.status == CAM_REQ_CMP) {
+ inq = (struct scsi_inquiry_data *)ccb->csio.data_ptr;
+ device = SID_TYPE(inq);
+ qual = SID_QUAL(inq);
+
+ /*
+ * We want DASD and PROC devices to only be
+ * visible through the pass device.
+ */
+ if (((device == T_DIRECT) ||
+ (device == T_PROCESSOR) ||
+ (sc->flags & AAC_FLAGS_CAM_PASSONLY))) {
+ /*
+ * Some aac(4) adapters will always report that a direct
+ * access device is offline in response to a INQUIRY
+ * command that does not retreive vital product data.
+ * Force the qualifier to connected so that upper layers
+ * correctly recognize that a disk is present.
+ */
+ if ((data[1] & SI_EVPD) == 0 && device == T_DIRECT &&
+ qual == SID_QUAL_LU_OFFLINE)
+ qual = SID_QUAL_LU_CONNECTED;
+ ccb->csio.data_ptr[0] = (qual << 5) | T_NODEVICE;
+ }
+ } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT &&
+ ccb->ccb_h.target_lun != 0) {
+ /* fix for INQUIRYs on Lun>0 */
+ ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+ }
+}
+
+static void
aac_cam_complete(struct aac_command *cm)
{
union ccb *ccb;
@@ -551,8 +598,6 @@ aac_cam_complete(struct aac_command *cm)
/* Take care of SCSI_IO ops. */
if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
- u_int8_t command, device;
-
ccb->csio.scsi_status = srbr->scsi_status;
/* Take care of autosense */
@@ -572,31 +617,7 @@ aac_cam_complete(struct aac_command *cm)
// scsi_sense_print(&ccb->csio);
}
- /* If this is an inquiry command, fake things out */
- if (ccb->ccb_h.flags & CAM_CDB_POINTER)
- command = ccb->csio.cdb_io.cdb_ptr[0];
- else
- command = ccb->csio.cdb_io.cdb_bytes[0];
-
- if (command == INQUIRY) {
- if (ccb->ccb_h.status == CAM_REQ_CMP) {
- device = ccb->csio.data_ptr[0] & 0x1f;
- /*
- * We want DASD and PROC devices to only be
- * visible through the pass device.
- */
- if ((device == T_DIRECT) ||
- (device == T_PROCESSOR) ||
- (sc->flags & AAC_FLAGS_CAM_PASSONLY))
- ccb->csio.data_ptr[0] =
- ((ccb->csio.data_ptr[0] & 0xe0) |
- T_NODEVICE);
- } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT &&
- ccb->ccb_h.target_lun != 0) {
- /* fix for INQUIRYs on Lun>0 */
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
- }
- }
+ aac_cam_fix_inquiry(sc, ccb);
}
}
OpenPOWER on IntegriCloud