From owner-svn-src-stable-10@FreeBSD.ORG Sun Nov 2 17:28:10 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 92F5936E; Sun, 2 Nov 2014 17:28:10 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 748A3CB3; Sun, 2 Nov 2014 17:28:10 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA2HSAeu028405; Sun, 2 Nov 2014 17:28:10 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA2HS9De028401; Sun, 2 Nov 2014 17:28:09 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201411021728.sA2HS9De028401@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Sun, 2 Nov 2014 17:28:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r273977 - in stable/10/sys/cam: ctl scsi X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Nov 2014 17:28:10 -0000 Author: mav Date: Sun Nov 2 17:28:08 2014 New Revision: 273977 URL: https://svnweb.freebsd.org/changeset/base/273977 Log: MFC r273073: 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. Modified: stable/10/sys/cam/ctl/ctl.c stable/10/sys/cam/ctl/ctl_cmd_table.c stable/10/sys/cam/ctl/ctl_private.h stable/10/sys/cam/scsi/scsi_all.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/ctl/ctl.c ============================================================================== --- stable/10/sys/cam/ctl/ctl.c Sun Nov 2 17:26:13 2014 (r273976) +++ stable/10/sys/cam/ctl/ctl.c Sun Nov 2 17:28:08 2014 (r273977) @@ -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. @@ -4155,14 +4218,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]; @@ -4177,6 +4237,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; @@ -4366,6 +4445,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: { @@ -4489,6 +4604,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. * @@ -4684,9 +4838,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. @@ -7270,6 +7425,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: stable/10/sys/cam/ctl/ctl_cmd_table.c ============================================================================== --- stable/10/sys/cam/ctl/ctl_cmd_table.c Sun Nov 2 17:26:13 2014 (r273976) +++ stable/10/sys/cam/ctl/ctl_cmd_table.c Sun Nov 2 17:28:08 2014 (r273977) @@ -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: stable/10/sys/cam/ctl/ctl_private.h ============================================================================== --- stable/10/sys/cam/ctl/ctl_private.h Sun Nov 2 17:26:13 2014 (r273976) +++ stable/10/sys/cam/ctl/ctl_private.h Sun Nov 2 17:28:08 2014 (r273977) @@ -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; @@ -482,6 +509,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: stable/10/sys/cam/scsi/scsi_all.h ============================================================================== --- stable/10/sys/cam/scsi/scsi_all.h Sun Nov 2 17:26:13 2014 (r273976) +++ stable/10/sys/cam/scsi/scsi_all.h Sun Nov 2 17:28:08 2014 (r273977) @@ -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. */