Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Feb 2015 00:12:21 +0000 (UTC)
From:      "Kenneth D. Merry" <ken@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278228 - in head/sys: cam cam/scsi sys
Message-ID:  <201502050012.t150CLaH051225@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ken
Date: Thu Feb  5 00:12:21 2015
New Revision: 278228
URL: https://svnweb.freebsd.org/changeset/base/278228

Log:
  Add support for probing the SCSI VPD Extended Inquiry page (0x86).
  
  This VPD page is effectively an extension of the standard Inquiry
  data page, and includes lots of additional bits.
  
  This commit includes support for probing the page in the SCSI probe code,
  and an additional request type for the XPT_DEV_ADVINFO CCB.  CTL already
  supports the Extended Inquiry page.
  
  Support for querying this page in the sa(4) driver will come later.
  
  sys/cam/scsi/scsi_xpt.c:
  	Probe the Extended Inquiry page, if the device supports it, and
  	return it in response to a XPT_DEV_ADVINFO CCB if it is requested.
  
  sys/cam/scsi/cam_ccb.h:
  	Define a new advanced information CCB data type, CDAI_TYPE_EXT_INQ.
  
  sys/cam/cam_xpt.c:
  	Free the extended inquiry data in a device when the device goes
  	away.
  
  sys/cam/cam_xpt_internal.h:
  	Add an extended inquiry data pointer and length to struct cam_ed.
  
  sys/sys/param.h
  	Bump __FreeBSD_version for the addition of the new
  	CDAI_TYPE_EXT_INQ advanced information type.
  
  Sponsored by:	Spectra Logic
  MFC after:	1 week

Modified:
  head/sys/cam/cam_ccb.h
  head/sys/cam/cam_xpt.c
  head/sys/cam/cam_xpt_internal.h
  head/sys/cam/scsi/scsi_xpt.c
  head/sys/sys/param.h

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Thu Feb  5 00:11:05 2015	(r278227)
+++ head/sys/cam/cam_ccb.h	Thu Feb  5 00:12:21 2015	(r278228)
@@ -1147,6 +1147,7 @@ struct ccb_dev_advinfo {
 #define	CDAI_TYPE_SERIAL_NUM	2
 #define	CDAI_TYPE_PHYS_PATH	3
 #define	CDAI_TYPE_RCAPLONG	4
+#define	CDAI_TYPE_EXT_INQ	5
 	off_t bufsiz;			/* IN: Size of external buffer */
 #define	CAM_SCSI_DEVID_MAXLEN	65536	/* length in buffer is an uint16_t */
 	off_t provsiz;			/* OUT: Size required/used */

Modified: head/sys/cam/cam_xpt.c
==============================================================================
--- head/sys/cam/cam_xpt.c	Thu Feb  5 00:11:05 2015	(r278227)
+++ head/sys/cam/cam_xpt.c	Thu Feb  5 00:12:21 2015	(r278228)
@@ -4795,6 +4795,7 @@ xpt_release_device(struct cam_ed *device
 	 */
 	free(device->supported_vpds, M_CAMXPT);
 	free(device->device_id, M_CAMXPT);
+	free(device->ext_inq, M_CAMXPT);
 	free(device->physpath, M_CAMXPT);
 	free(device->rcap_buf, M_CAMXPT);
 	free(device->serial_num, M_CAMXPT);

Modified: head/sys/cam/cam_xpt_internal.h
==============================================================================
--- head/sys/cam/cam_xpt_internal.h	Thu Feb  5 00:11:05 2015	(r278227)
+++ head/sys/cam/cam_xpt_internal.h	Thu Feb  5 00:12:21 2015	(r278228)
@@ -83,6 +83,8 @@ struct cam_ed {
 	uint8_t		 supported_vpds_len;
 	uint32_t	 device_id_len;
 	uint8_t		 *device_id;
+	uint32_t	 ext_inq_len;
+	uint8_t		 *ext_inq;
 	uint8_t		 physpath_len;
 	uint8_t		 *physpath;	/* physical path string form */
 	uint32_t	 rcap_len;

Modified: head/sys/cam/scsi/scsi_xpt.c
==============================================================================
--- head/sys/cam/scsi/scsi_xpt.c	Thu Feb  5 00:11:05 2015	(r278227)
+++ head/sys/cam/scsi/scsi_xpt.c	Thu Feb  5 00:12:21 2015	(r278228)
@@ -139,6 +139,7 @@ typedef enum {
 	PROBE_MODE_SENSE,
 	PROBE_SUPPORTED_VPD_LIST,
 	PROBE_DEVICE_ID,
+	PROBE_EXTENDED_INQUIRY,
 	PROBE_SERIAL_NUM,
 	PROBE_TUR_FOR_NEGOTIATION,
 	PROBE_INQUIRY_BASIC_DV1,
@@ -156,6 +157,7 @@ static char *probe_action_text[] = {
 	"PROBE_MODE_SENSE",
 	"PROBE_SUPPORTED_VPD_LIST",
 	"PROBE_DEVICE_ID",
+	"PROBE_EXTENDED_INQUIRY",
 	"PROBE_SERIAL_NUM",
 	"PROBE_TUR_FOR_NEGOTIATION",
 	"PROBE_INQUIRY_BASIC_DV1",
@@ -923,6 +925,34 @@ done:
 		}
 		goto done;
 	}
+	case PROBE_EXTENDED_INQUIRY:
+	{
+		struct scsi_vpd_extended_inquiry_data *ext_inq;
+
+		ext_inq = NULL;
+		if (scsi_vpd_supported_page(periph, SVPD_EXTENDED_INQUIRY_DATA))
+			ext_inq = malloc(sizeof(*ext_inq), M_CAMXPT,
+			    M_NOWAIT | M_ZERO);
+
+		if (ext_inq != NULL) {
+			scsi_inquiry(csio,
+				     /*retries*/4,
+				     probedone,
+				     MSG_SIMPLE_Q_TAG,
+				     (uint8_t *)ext_inq,
+				     sizeof(*ext_inq),
+				     /*evpd*/TRUE,
+				     SVPD_EXTENDED_INQUIRY_DATA,
+				     SSD_MIN_SIZE,
+				     /*timeout*/60 * 1000);
+			break;
+		}
+		/*
+		 * We'll have to do without, let our probedone
+		 * routine finish up for us.
+		 */
+		goto done;
+	}
 	case PROBE_SERIAL_NUM:
 	{
 		struct scsi_vpd_unit_serial_number *serial_buf;
@@ -1454,6 +1484,50 @@ out:
 		if (devid && length == 0)
 			free(devid, M_CAMXPT);
 		xpt_release_ccb(done_ccb);
+		PROBE_SET_ACTION(softc, PROBE_EXTENDED_INQUIRY);
+		xpt_schedule(periph, priority);
+		goto out;
+	}
+	case PROBE_EXTENDED_INQUIRY: {
+		struct scsi_vpd_extended_inquiry_data *ext_inq;
+		struct ccb_scsiio *csio;
+		int32_t length = 0;
+
+		csio = &done_ccb->csio;
+		ext_inq = (struct scsi_vpd_extended_inquiry_data *)
+		    csio->data_ptr;
+		if (path->device->ext_inq != NULL) {
+			path->device->ext_inq_len = 0;
+			free(path->device->ext_inq, M_CAMXPT);
+			path->device->ext_inq = NULL;
+		}
+
+		if (ext_inq == NULL) {
+			/* Don't process the command as it was never sent */
+		} else if (CCB_COMPLETED_OK(csio->ccb_h)) {
+			length = scsi_2btoul(ext_inq->page_length) +
+			    __offsetof(struct scsi_vpd_extended_inquiry_data,
+			    flags1);
+			length = min(length, sizeof(*ext_inq));
+			length -= csio->resid;
+			if (length > 0) {
+				path->device->ext_inq_len = length;
+				path->device->ext_inq = (uint8_t *)ext_inq;
+			}
+		} else if (cam_periph_error(done_ccb, 0,
+					    SF_RETRY_UA,
+					    &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);
+		}
+
+		/* Free the device id space if we don't use it */
+		if (ext_inq && length <= 0)
+			free(ext_inq, M_CAMXPT);
+		xpt_release_ccb(done_ccb);
 		PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM);
 		xpt_schedule(periph, priority);
 		goto out;
@@ -2477,6 +2551,21 @@ scsi_dev_advinfo(union ccb *start_ccb)
 			memcpy(cdai->buf, device->rcap_buf, amt);
 		}
 		break;
+	case CDAI_TYPE_EXT_INQ:
+		/*
+		 * We fetch extended inquiry data during probe, if
+		 * available.  We don't allow changing it.
+		 */
+		if (cdai->flags & CDAI_FLAG_STORE) 
+			return;
+		cdai->provsiz = device->ext_inq_len;
+		if (device->ext_inq_len == 0)
+			break;
+		amt = device->ext_inq_len;
+		if (cdai->provsiz > cdai->bufsiz)
+			amt = cdai->bufsiz;
+		memcpy(cdai->buf, device->ext_inq, amt);
+		break;
 	default:
 		return;
 	}

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h	Thu Feb  5 00:11:05 2015	(r278227)
+++ head/sys/sys/param.h	Thu Feb  5 00:12:21 2015	(r278228)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1100057	/* Master, propagated to newvers */
+#define __FreeBSD_version 1100058	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502050012.t150CLaH051225>