Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Oct 2014 10:14:14 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r273073 - in head/sys/cam: ctl scsi
Message-ID:  <201410141014.s9EAEElh040693@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Oct 14 10:14:14 2014
New Revision: 273073
URL: https://svnweb.freebsd.org/changeset/base/273073

Log:
  Some groundwork for later Informational Exceptions support.
  
  This includes support for:
   - Read-Write Error Recovery mode page;
   - Informational Exceptions Control mode page;
   - Logical Block Provisioning mode page;
   - LOG SENSE command.
  
  No real Informational Exceptions features yet. This is only a placeholder.
  
  Sponsored by:	iXsystems, Inc.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_cmd_table.c
  head/sys/cam/ctl/ctl_private.h
  head/sys/cam/scsi/scsi_all.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Tue Oct 14 08:30:02 2014	(r273072)
+++ head/sys/cam/ctl/ctl.c	Tue Oct 14 10:14:14 2014	(r273073)
@@ -178,6 +178,34 @@ static struct copan_debugconf_subpage de
 	{0xff,0xff},			/* ctl_time_io_secs */
 };
 
+static struct scsi_da_rw_recovery_page rw_er_page_default = {
+	/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
+	/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
+	/*byte3*/SMS_RWER_AWRE|SMS_RWER_ARRE,
+	/*read_retry_count*/0,
+	/*correction_span*/0,
+	/*head_offset_count*/0,
+	/*data_strobe_offset_cnt*/0,
+	/*byte8*/0,
+	/*write_retry_count*/0,
+	/*reserved2*/0,
+	/*recovery_time_limit*/{0, 0},
+};
+
+static struct scsi_da_rw_recovery_page rw_er_page_changeable = {
+	/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
+	/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
+	/*byte3*/0,
+	/*read_retry_count*/0,
+	/*correction_span*/0,
+	/*head_offset_count*/0,
+	/*data_strobe_offset_cnt*/0,
+	/*byte8*/0,
+	/*write_retry_count*/0,
+	/*reserved2*/0,
+	/*recovery_time_limit*/{0, 0},
+};
+
 static struct scsi_format_page format_page_default = {
 	/*page_code*/SMS_FORMAT_DEVICE_PAGE,
 	/*page_length*/sizeof(struct scsi_format_page) - 2,
@@ -300,6 +328,41 @@ static struct scsi_control_page control_
 	/*extended_selftest_completion_time*/{0, 0}
 };
 
+static struct scsi_info_exceptions_page ie_page_default = {
+	/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
+	/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
+	/*info_flags*/SIEP_FLAGS_DEXCPT,
+	/*mrie*/0,
+	/*interval_timer*/{0, 0, 0, 0},
+	/*report_count*/{0, 0, 0, 0}
+};
+
+static struct scsi_info_exceptions_page ie_page_changeable = {
+	/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
+	/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
+	/*info_flags*/0,
+	/*mrie*/0,
+	/*interval_timer*/{0, 0, 0, 0},
+	/*report_count*/{0, 0, 0, 0}
+};
+
+static struct scsi_logical_block_provisioning_page lbp_page_default = {
+	/*page_code*/SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF,
+	/*subpage_code*/0x02,
+	/*page_length*/{0, sizeof(struct scsi_logical_block_provisioning_page) - 4},
+	/*flags*/0,
+	/*reserved*/{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	/*descr*/{}
+};
+
+static struct scsi_logical_block_provisioning_page lbp_page_changeable = {
+	/*page_code*/SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF,
+	/*subpage_code*/0x02,
+	/*page_length*/{0, sizeof(struct scsi_logical_block_provisioning_page) - 4},
+	/*flags*/0,
+	/*reserved*/{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	/*descr*/{}
+};
 
 /*
  * XXX KDM move these into the softc.
@@ -4153,14 +4216,11 @@ ctl_init_page_index(struct ctl_lun *lun)
 {
 	int i;
 	struct ctl_page_index *page_index;
-	struct ctl_softc *softc;
 	const char *value;
 
 	memcpy(&lun->mode_pages.index, page_index_template,
 	       sizeof(page_index_template));
 
-	softc = lun->ctl_softc;
-
 	for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
 
 		page_index = &lun->mode_pages.index[i];
@@ -4175,6 +4235,25 @@ ctl_init_page_index(struct ctl_lun *lun)
 			continue;
 
 		switch (page_index->page_code & SMPH_PC_MASK) {
+		case SMS_RW_ERROR_RECOVERY_PAGE: {
+			if (page_index->subpage != SMS_SUBPAGE_PAGE_0)
+				panic("subpage is incorrect!");
+			memcpy(&lun->mode_pages.rw_er_page[CTL_PAGE_CURRENT],
+			       &rw_er_page_default,
+			       sizeof(rw_er_page_default));
+			memcpy(&lun->mode_pages.rw_er_page[CTL_PAGE_CHANGEABLE],
+			       &rw_er_page_changeable,
+			       sizeof(rw_er_page_changeable));
+			memcpy(&lun->mode_pages.rw_er_page[CTL_PAGE_DEFAULT],
+			       &rw_er_page_default,
+			       sizeof(rw_er_page_default));
+			memcpy(&lun->mode_pages.rw_er_page[CTL_PAGE_SAVED],
+			       &rw_er_page_default,
+			       sizeof(rw_er_page_default));
+			page_index->page_data =
+				(uint8_t *)lun->mode_pages.rw_er_page;
+			break;
+		}
 		case SMS_FORMAT_DEVICE_PAGE: {
 			struct scsi_format_page *format_page;
 
@@ -4364,6 +4443,42 @@ ctl_init_page_index(struct ctl_lun *lun)
 			break;
 
 		}
+		case SMS_INFO_EXCEPTIONS_PAGE: {
+			switch (page_index->subpage) {
+			case SMS_SUBPAGE_PAGE_0:
+				memcpy(&lun->mode_pages.ie_page[CTL_PAGE_CURRENT],
+				       &ie_page_default,
+				       sizeof(ie_page_default));
+				memcpy(&lun->mode_pages.ie_page[
+				       CTL_PAGE_CHANGEABLE], &ie_page_changeable,
+				       sizeof(ie_page_changeable));
+				memcpy(&lun->mode_pages.ie_page[CTL_PAGE_DEFAULT],
+				       &ie_page_default,
+				       sizeof(ie_page_default));
+				memcpy(&lun->mode_pages.ie_page[CTL_PAGE_SAVED],
+				       &ie_page_default,
+				       sizeof(ie_page_default));
+				page_index->page_data =
+					(uint8_t *)lun->mode_pages.ie_page;
+				break;
+			case 0x02:
+				memcpy(&lun->mode_pages.lbp_page[CTL_PAGE_CURRENT],
+				       &lbp_page_default,
+				       sizeof(lbp_page_default));
+				memcpy(&lun->mode_pages.lbp_page[
+				       CTL_PAGE_CHANGEABLE], &lbp_page_changeable,
+				       sizeof(lbp_page_changeable));
+				memcpy(&lun->mode_pages.lbp_page[CTL_PAGE_DEFAULT],
+				       &lbp_page_default,
+				       sizeof(lbp_page_default));
+				memcpy(&lun->mode_pages.lbp_page[CTL_PAGE_SAVED],
+				       &lbp_page_default,
+				       sizeof(lbp_page_default));
+				page_index->page_data =
+					(uint8_t *)lun->mode_pages.lbp_page;
+			}
+			break;
+		}
 		case SMS_VENDOR_SPECIFIC_PAGE:{
 			switch (page_index->subpage) {
 			case PWR_SUBPAGE_CODE: {
@@ -4487,6 +4602,45 @@ ctl_init_page_index(struct ctl_lun *lun)
 	return (CTL_RETVAL_COMPLETE);
 }
 
+static int
+ctl_init_log_page_index(struct ctl_lun *lun)
+{
+	struct ctl_page_index *page_index;
+	int i, j, prev;
+
+	memcpy(&lun->log_pages.index, log_page_index_template,
+	       sizeof(log_page_index_template));
+
+	prev = -1;
+	for (i = 0, j = 0; i < CTL_NUM_LOG_PAGES; i++) {
+
+		page_index = &lun->log_pages.index[i];
+		/*
+		 * If this is a disk-only mode page, there's no point in
+		 * setting it up.  For some pages, we have to have some
+		 * basic information about the disk in order to calculate the
+		 * mode page data.
+		 */
+		if ((lun->be_lun->lun_type != T_DIRECT)
+		 && (page_index->page_flags & CTL_PAGE_FLAG_DISK_ONLY))
+			continue;
+
+		if (page_index->page_code != prev) {
+			lun->log_pages.pages_page[j] = page_index->page_code;
+			prev = page_index->page_code;
+			j++;
+		}
+		lun->log_pages.subpages_page[i*2] = page_index->page_code;
+		lun->log_pages.subpages_page[i*2+1] = page_index->subpage;
+	}
+	lun->log_pages.index[0].page_data = &lun->log_pages.pages_page[0];
+	lun->log_pages.index[0].page_len = j;
+	lun->log_pages.index[1].page_data = &lun->log_pages.subpages_page[0];
+	lun->log_pages.index[1].page_len = i * 2;
+
+	return (CTL_RETVAL_COMPLETE);
+}
+
 /*
  * LUN allocation.
  *
@@ -4682,9 +4836,10 @@ ctl_alloc_lun(struct ctl_softc *ctl_soft
 	ctl_tpc_lun_init(lun);
 
 	/*
-	 * Initialize the mode page index.
+	 * Initialize the mode and log page index.
 	 */
 	ctl_init_page_index(lun);
+	ctl_init_log_page_index(lun);
 
 	/*
 	 * Set the poweron UA for all initiators on this LUN only.
@@ -7266,6 +7421,91 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
 }
 
 int
+ctl_log_sense(struct ctl_scsiio *ctsio)
+{
+	struct ctl_lun *lun;
+	int i, pc, page_code, subpage;
+	int alloc_len, total_len;
+	struct ctl_page_index *page_index;
+	struct scsi_log_sense *cdb;
+	struct scsi_log_header *header;
+
+	CTL_DEBUG_PRINT(("ctl_log_sense\n"));
+
+	lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+	cdb = (struct scsi_log_sense *)ctsio->cdb;
+	pc = (cdb->page & SLS_PAGE_CTRL_MASK) >> 6;
+	page_code = cdb->page & SLS_PAGE_CODE;
+	subpage = cdb->subpage;
+	alloc_len = scsi_2btoul(cdb->length);
+
+	page_index = NULL;
+	for (i = 0; i < CTL_NUM_LOG_PAGES; i++) {
+		page_index = &lun->log_pages.index[i];
+
+		/* Look for the right page code */
+		if ((page_index->page_code & SL_PAGE_CODE) != page_code)
+			continue;
+
+		/* Look for the right subpage or the subpage wildcard*/
+		if (page_index->subpage != subpage)
+			continue;
+
+		break;
+	}
+	if (i >= CTL_NUM_LOG_PAGES) {
+		ctl_set_invalid_field(ctsio,
+				      /*sks_valid*/ 1,
+				      /*command*/ 1,
+				      /*field*/ 2,
+				      /*bit_valid*/ 0,
+				      /*bit*/ 0);
+		ctl_done((union ctl_io *)ctsio);
+		return (CTL_RETVAL_COMPLETE);
+	}
+
+	total_len = sizeof(struct scsi_log_header) + page_index->page_len;
+
+	ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
+	ctsio->kern_sg_entries = 0;
+	ctsio->kern_data_resid = 0;
+	ctsio->kern_rel_offset = 0;
+	if (total_len < alloc_len) {
+		ctsio->residual = alloc_len - total_len;
+		ctsio->kern_data_len = total_len;
+		ctsio->kern_total_len = total_len;
+	} else {
+		ctsio->residual = 0;
+		ctsio->kern_data_len = alloc_len;
+		ctsio->kern_total_len = alloc_len;
+	}
+
+	header = (struct scsi_log_header *)ctsio->kern_data_ptr;
+	header->page = page_index->page_code;
+	if (page_index->subpage) {
+		header->page |= SL_SPF;
+		header->subpage = page_index->subpage;
+	}
+	scsi_ulto2b(page_index->page_len, header->datalen);
+
+	/*
+	 * Call the handler, if it exists, to update the
+	 * page to the latest values.
+	 */
+	if (page_index->sense_handler != NULL)
+		page_index->sense_handler(ctsio, page_index, pc);
+
+	memcpy(header + 1, page_index->page_data, page_index->page_len);
+
+	ctsio->scsi_status = SCSI_STATUS_OK;
+	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+	ctsio->be_move_done = ctl_config_move_done;
+	ctl_datamove((union ctl_io *)ctsio);
+
+	return (CTL_RETVAL_COMPLETE);
+}
+
+int
 ctl_read_capacity(struct ctl_scsiio *ctsio)
 {
 	struct scsi_read_capacity *cdb;

Modified: head/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- head/sys/cam/ctl/ctl_cmd_table.c	Tue Oct 14 08:30:02 2014	(r273072)
+++ head/sys/cam/ctl/ctl_cmd_table.c	Tue Oct 14 10:14:14 2014	(r273073)
@@ -850,7 +850,10 @@ const struct ctl_cmd_entry ctl_cmd_table
 {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
 
 /* 4D LOG SENSE */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+{ctl_log_sense, CTL_SERIDX_LOG_SNS, CTL_CMD_FLAG_OK_ON_SLUN |
+				    CTL_FLAG_DATA_IN |
+				    CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
+ CTL_LUN_PAT_NONE, 10, {0, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0x07} },
 
 /* 4E STOP PLAY/SCAN */
 {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},

Modified: head/sys/cam/ctl/ctl_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Tue Oct 14 08:30:02 2014	(r273072)
+++ head/sys/cam/ctl/ctl_private.h	Tue Oct 14 10:14:14 2014	(r273073)
@@ -302,6 +302,8 @@ struct ctl_page_index {
 #define	CTL_PAGE_SAVED		0x03
 
 static const struct ctl_page_index page_index_template[] = {
+	{SMS_RW_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_rw_recovery_page), NULL,
+	 CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL},
 	{SMS_FORMAT_DEVICE_PAGE, 0, sizeof(struct scsi_format_page), NULL,
 	 CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL},
 	{SMS_RIGID_DISK_PAGE, 0, sizeof(struct scsi_rigid_disk_page), NULL,
@@ -310,6 +312,11 @@ static const struct ctl_page_index page_
 	 CTL_PAGE_FLAG_DISK_ONLY, NULL, ctl_caching_sp_handler},
 	{SMS_CONTROL_MODE_PAGE, 0, sizeof(struct scsi_control_page), NULL,
 	 CTL_PAGE_FLAG_NONE, NULL, ctl_control_page_handler},
+	{SMS_INFO_EXCEPTIONS_PAGE, 0, sizeof(struct scsi_info_exceptions_page), NULL,
+	 CTL_PAGE_FLAG_NONE, NULL, NULL},
+	{SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF, 0x02,
+	 sizeof(struct scsi_logical_block_provisioning_page), NULL,
+	 CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL},
    	{SMS_VENDOR_SPECIFIC_PAGE | SMPH_SPF, PWR_SUBPAGE_CODE,
 	 sizeof(struct copan_power_subpage), NULL, CTL_PAGE_FLAG_NONE,
 	 ctl_power_sp_sense_handler, ctl_power_sp_handler},
@@ -325,16 +332,35 @@ static const struct ctl_page_index page_
 			   sizeof(page_index_template[0])
 
 struct ctl_mode_pages {
+	struct scsi_da_rw_recovery_page	rw_er_page[4];
 	struct scsi_format_page		format_page[4];
 	struct scsi_rigid_disk_page	rigid_disk_page[4];
 	struct scsi_caching_page	caching_page[4];
 	struct scsi_control_page	control_page[4];
+	struct scsi_info_exceptions_page ie_page[4];
+	struct scsi_logical_block_provisioning_page lbp_page[4];
 	struct copan_power_subpage	power_subpage[4];
 	struct copan_aps_subpage	aps_subpage[4];
 	struct copan_debugconf_subpage	debugconf_subpage[4];
 	struct ctl_page_index		index[CTL_NUM_MODE_PAGES];
 };
 
+static const struct ctl_page_index log_page_index_template[] = {
+	{SLS_SUPPORTED_PAGES_PAGE, 0, 0, NULL,
+	 CTL_PAGE_FLAG_NONE, NULL, NULL},
+	{SLS_SUPPORTED_PAGES_PAGE, SLS_SUPPORTED_SUBPAGES_SUBPAGE, 0, NULL,
+	 CTL_PAGE_FLAG_NONE, NULL, NULL},
+};
+
+#define	CTL_NUM_LOG_PAGES sizeof(log_page_index_template)/   \
+			  sizeof(log_page_index_template[0])
+
+struct ctl_log_pages {
+	uint8_t				pages_page[CTL_NUM_LOG_PAGES];
+	uint8_t				subpages_page[CTL_NUM_LOG_PAGES * 2];
+	struct ctl_page_index		index[CTL_NUM_LOG_PAGES];
+};
+
 struct ctl_lun_delay_info {
 	ctl_delay_type		datamove_type;
 	uint32_t		datamove_delay;
@@ -391,6 +417,7 @@ struct ctl_lun {
 #endif
 	ctl_ua_type			pending_ua[CTL_MAX_INITIATORS];
 	struct ctl_mode_pages		mode_pages;
+	struct ctl_log_pages		log_pages;
 	struct ctl_lun_io_stats		stats;
 	uint32_t			res_idx;
 	unsigned int			PRGeneration;
@@ -484,6 +511,7 @@ int ctl_write_same(struct ctl_scsiio *ct
 int ctl_unmap(struct ctl_scsiio *ctsio);
 int ctl_mode_select(struct ctl_scsiio *ctsio);
 int ctl_mode_sense(struct ctl_scsiio *ctsio);
+int ctl_log_sense(struct ctl_scsiio *ctsio);
 int ctl_read_capacity(struct ctl_scsiio *ctsio);
 int ctl_read_capacity_16(struct ctl_scsiio *ctsio);
 int ctl_read_defect(struct ctl_scsiio *ctsio);

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h	Tue Oct 14 08:30:02 2014	(r273072)
+++ head/sys/cam/scsi/scsi_all.h	Tue Oct 14 10:14:14 2014	(r273073)
@@ -551,7 +551,7 @@ struct scsi_log_sense
 #define	SLS_PPC				0x02
 	u_int8_t page;
 #define	SLS_PAGE_CODE 			0x3F
-#define	SLS_ALL_PAGES_PAGE		0x00
+#define	SLS_SUPPORTED_PAGES_PAGE	0x00
 #define	SLS_OVERRUN_PAGE		0x01
 #define	SLS_ERROR_WRITE_PAGE		0x02
 #define	SLS_ERROR_READ_PAGE		0x03
@@ -566,7 +566,9 @@ struct scsi_log_sense
 #define	SLS_PAGE_CTRL_CUMULATIVE	0x40
 #define	SLS_PAGE_CTRL_THRESH_DEFAULT	0x80
 #define	SLS_PAGE_CTRL_CUMUL_DEFAULT	0xC0
-	u_int8_t reserved[2];
+	u_int8_t subpage;
+#define	SLS_SUPPORTED_SUBPAGES_SUBPAGE	0xff
+	u_int8_t reserved;
 	u_int8_t paramptr[2];
 	u_int8_t length[2];
 	u_int8_t control;
@@ -592,7 +594,10 @@ struct scsi_log_select
 struct scsi_log_header
 {
 	u_int8_t page;
-	u_int8_t reserved;
+#define	SL_PAGE_CODE			0x3F
+#define	SL_SPF				0x40
+#define	SL_DS				0x80
+	u_int8_t subpage;
 	u_int8_t datalen[2];
 };
 
@@ -767,6 +772,23 @@ struct scsi_info_exceptions_page {
 	u_int8_t report_count[4];
 };
 
+struct scsi_logical_block_provisioning_page_descr {
+	uint8_t flags;
+	uint8_t resource;
+	uint8_t reserved[2];
+	uint8_t count[4];
+};
+
+struct scsi_logical_block_provisioning_page {
+	uint8_t page_code;
+	uint8_t subpage_code;
+	uint8_t page_length[2];
+	uint8_t flags;
+#define	SLBPP_SITUA		0x01
+	uint8_t reserved[11];
+	struct scsi_logical_block_provisioning_page_descr descr[0];
+};
+
 /*
  * SCSI protocol identifier values, current as of SPC4r36l.
  */



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