lpfc: Implement support for wire-only DIF devices
Subsystems (2)
PATCH 15/21 lpfc: Implement support for wire-only DIF devices
Implement support for wire-only DIF devices
This patch adds the ability to support auto-enablement of wire-only DIF (DIF is generated on TX to target, stripped on RX; OS unaware DIF in use) for a select set of devices. Currently, there is only 1 device vendor
supported: 3PARdata. When the feature is enabled, Inquiry commands are trapped, the vendor matched, and DIF enablement checked. In 3Par's case, there's a vendor specific check to see if the LUN supports DIF. If supported, DIF will be enabled on a per-lun basis. The driver will trap READS/WRITEs from the OS, check for LUN DIF enablement, and if set, turns on write-only DIF.
--- drivers/scsi/lpfc/lpfc.h | 41 ++++ drivers/scsi/lpfc/lpfc_attr.c | 65 ++++++- drivers/scsi/lpfc/lpfc_crtn.h | 3 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 3 + drivers/scsi/lpfc/lpfc_init.c | 24 ++- drivers/scsi/lpfc/lpfc_mbox.c | 4 +- drivers/scsi/lpfc/lpfc_scsi.c | 410 ++++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_scsi.h | 7 +- drivers/scsi/lpfc/lpfc_sli.c | 36 ++-- 9 files changed, 532 insertions(+), 61 deletions(-)
drivers/scsi/lpfc/lpfc.h +41 -0
@@ -295,6 +295,42 @@ enum hba_state {LPFC_HBA_ERROR =-1 }; +/* Structure used to identify all devices controlled +* by the External DIF logic. +*/ +struct lpfc_external_dif_support { +struct list_head listentry; +struct lpfc_name portName; +uint64_t lun; +uint16_t sid; +uint8_t dif_info; +uint8_t reserved1; +}; + +/* Struct used to identify External DIF vendor specific info */ +struct lpfc_vendor_dif { +uint8_t length; +uint8_t version; +uint8_t dif_info; +#define LPFC_FDIF_ATO 0x01 +#define LPFC_FDIF_REFCHK 0x02 +#define LPFC_FDIF_APPCHK 0x04 +#define LPFC_FDIF_GRDCHK 0x08 +#define LPFC_FDIF_SPTMASK 0x70 +#define LPFC_FDIF_PROTECT 0x80 +uint8_t reserved1; +}; + +/* Defines used to identify a External DIF device */ +#define LPFC_INQ_VID_OFFSET 8 +#define LPFC_INQ_VDIF_OFFSET 168 +#define LPFC_INQ_FDIF_SZ (LPFC_INQ_VDIF_OFFSET + 4) +#define LPFC_INQ_FDIF_VENDOR "3PARdata"/* Vendor Identification */ +#define LPFC_INQ_FDIF_VERSION 1 +#define LPFC_INQ_FDIF_SIZE 2 +#define LPFC_FDIF_CDB_PROTECT 0x20/* Set RD/WR PROTECT = 001 */ + +struct lpfc_vport {struct lpfc_hba *phba;struct list_head listentry;
@@ -441,6 +477,10 @@ struct lpfc_vport {unsigned long rcv_buffer_time_stamp;uint32_t vport_flag;#define STATIC_VPORT 1 + +/* Used to discover External DIF devices */ +struct list_head external_dif_list; +spinlock_t external_dif_lock;/* lock for external_dif_list */ };struct hbq_s {
@@ -739,6 +779,7 @@ struct lpfc_hba {#define OAS_LUN_VALID 0x04uint32_t cfg_XLanePriority;uint32_t cfg_enable_bg; +uint32_t cfg_external_dif;uint32_t cfg_hostmem_hgp;uint32_t cfg_log_verbose;uint32_t cfg_aer_support;
drivers/scsi/lpfc/lpfc_attr.c +59 -6
112 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_crtn.h +2 -1
@@ -366,7 +366,8 @@ extern int lpfc_delay_discovery;int lpfc_vport_symbolic_node_name (struct lpfc_vport *,char *,size_t );int lpfc_vport_symbolic_port_name (struct lpfc_vport *,char *,size_t );void lpfc_terminate_rport_io (struct fc_rport *); -void lpfc_dev_loss_tmo_callbk (struct fc_rport *rport); +void lpfc_dev_loss_tmo_callbk (struct fc_rport *); +void lpfc_external_dif_cleanup (struct lpfc_vport *,struct lpfc_name *);struct lpfc_vport *lpfc_create_port (struct lpfc_hba *,int ,struct device *);int lpfc_vport_disable (struct fc_vport *fc_vport,bool disable);
drivers/scsi/lpfc/lpfc_hbadisc.c +3 -0
@@ -143,6 +143,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)return ; } +/* Cleanup all External DIF devices that match this rports WWPN */ +lpfc_external_dif_cleanup (vport, &ndlp->nlp_portname); +if (ndlp->nlp_state ==NLP_STE_MAPPED_NODE )return ;
drivers/scsi/lpfc/lpfc_init.c +19 -5
@@ -154,8 +154,6 @@ lpfc_config_port_prep(struct lpfc_hba *phba) sizeof(phba->wwpn)); } - phba->sli3_options =0x0 ; -/* Setup and issue mailbox READ REV command */ lpfc_read_rev (phba, pmb); rc =lpfc_sli_issue_mbox (phba, pmb,MBX_POLL );
@@ -2523,6 +2521,7 @@ lpfc_cleanup(struct lpfc_vport *vport) {struct lpfc_hba *phba = vport->phba;struct lpfc_nodelist *ndlp, *next_ndlp; +struct lpfc_external_dif_support *dp, *next_dp;int i =0 ;if (phba->link_state >LPFC_LINK_DOWN )
@@ -2600,6 +2599,15 @@ lpfc_cleanup(struct lpfc_vport *vport)msleep (10 ); }lpfc_cleanup_vports_rrqs (vport,NULL ); + +/* Cleanup any discovered External DIF devices for this vport */ +list_for_each_entry_safe (dp, next_dp, &vport->external_dif_list, + listentry) { +spin_lock_irq (&vport->external_dif_lock); +list_del (&dp->listentry); +spin_unlock_irq (&vport->external_dif_lock); +kfree (dp); + } }/**
@@ -3348,6 +3356,10 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)if (error) goto out_put_shost; +/* Initialize objects used to discover External DIF devices */ +INIT_LIST_HEAD (&vport->external_dif_list); +spin_lock_init (&vport->external_dif_lock); +spin_lock_irq (&phba->hbalock);list_add_tail (&vport->listentry, &phba->port_list);spin_unlock_irq (&phba->hbalock);
@@ -4991,7 +5003,7 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;/* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */ -if (phba->cfg_enable_bg) { +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) {/* * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, * the FCP rsp, and a BDE for each. Sice we have no control
@@ -5184,7 +5196,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)* used to create the sg_dma_buf_pool must be dynamically calculated. */ -if (phba->cfg_enable_bg) { +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) {/* * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, * the FCP rsp, and a SGE for each. Sice we have no control
@@ -6285,7 +6297,9 @@ lpfc_post_init_setup(struct lpfc_hba *phba)*/ shost =pci_get_drvdata (phba->pcidev); shost->can_queue = phba->cfg_hba_queue_depth -10 ; -if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) + +/* Setup T10-DIF interface with SCSI Layer API */ +if (phba->cfg_enable_bg)lpfc_setup_bg (phba, shost);lpfc_host_attrib_init (shost);
drivers/scsi/lpfc/lpfc_mbox.c +2 -2
@@ -1280,7 +1280,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)/* If HBA supports SLI=3 ask for it */ if (phba->sli_rev ==LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) { -if (phba->cfg_enable_bg) +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) mb->un.varCfgPort.cbg =1 ;/* configure BlockGuard */ if (phba->cfg_enable_dss) mb->un.varCfgPort.cdss =1 ;/* Configure Security */
@@ -2071,7 +2071,7 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq)bf_set (lpfc_mbx_rq_ftr_rq_perfh, &mboxq->u.mqe.un.req_ftrs,1 );/* Enable DIF (block guard) only if configured to do so. */ -if (phba->cfg_enable_bg) +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED )bf_set (lpfc_mbx_rq_ftr_rq_dif, &mboxq->u.mqe.un.req_ftrs,1 );/* Enable NPIV only if configured to do so. */
drivers/scsi/lpfc/lpfc_scsi.c +378 -32
611 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_scsi.h +6 -1
@@ -134,7 +134,12 @@ struct lpfc_scsi_buf {uint32_t timeout; -uint16_t exch_busy;/* SLI4 hba reported XB on complete WCQE */ +uint16_t flags; +#define LPFC_SBUF_XBUSY 0x1/* SLI4 hba reported XB on WCQE cmpl */ +/* External DIF device IO conversions */ +#define LPFC_SBUF_NORMAL_DIF 0x2/* normal mode to insert/strip */ +#define LPFC_SBUF_PASS_DIF 0x4/* insert/strip mode to passthru */ +uint16_t status;/* From IOCB Word 7- ulpStatus */ uint32_t result;/* From IOCB Word 4. */
drivers/scsi/lpfc/lpfc_sli.c +22 -14
@@ -4526,7 +4526,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |LPFC_SLI3_HBQ_ENABLED |LPFC_SLI3_CRP_ENABLED | -LPFC_SLI3_BG_ENABLED |LPFC_SLI3_DSS_ENABLED );if (rc !=MBX_SUCCESS ) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -4592,13 +4591,20 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get; phba->port_gp = phba->mbox->us.s3_pgp.port; -if (phba->cfg_enable_bg) { -if (pmb->u.mb.un.varCfgPort.gbg) - phba->sli3_options |=LPFC_SLI3_BG_ENABLED ; -else +/* +* If the port cannot support the host's requested features +* then turn off the global config parameters to disable the +* feature in the driver. This is not a fatal error. +*/ +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) { +if (pmb->u.mb.un.varCfgPort.gbg ==0 ) { + phba->cfg_enable_bg =0 ; + phba->cfg_external_dif =0 ; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED ;lpfc_printf_log (phba,KERN_ERR ,LOG_INIT ,"0443 Adapter did not grant " "BlockGuard\n" ); + } } }else { phba->hbq_get =NULL ;
@@ -4689,7 +4695,6 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) }else { phba->iocb_cmd_size =SLI2_IOCB_CMD_SIZE ; phba->iocb_rsp_size =SLI2_IOCB_RSP_SIZE ; - phba->sli3_options =0 ; } lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
@@ -6407,12 +6412,13 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)* then turn off the global config parameters to disable the * feature in the driver. This is not a fatal error. */ - phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED ; -if (phba->cfg_enable_bg) { -if (bf_get (lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)) - phba->sli3_options |=LPFC_SLI3_BG_ENABLED ; -else +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) { +if (!(bf_get (lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))) { + phba->cfg_enable_bg =0 ; + phba->cfg_external_dif =0 ; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED ; ftr_rsp++; + } } if (phba->max_vpi && phba->cfg_enable_npiv &&
@@ -6425,8 +6431,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)"x%x x%x x%x\n" , mqe->un.req_ftrs.word2, mqe->un.req_ftrs.word3, phba->cfg_enable_bg, phba->cfg_enable_npiv, phba->max_vpi); -if (!(bf_get (lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))) - phba->cfg_enable_bg =0 ; +if (!(bf_get (lpfc_mbx_rq_ftr_rsp_npiv, &mqe->un.req_ftrs))) phba->cfg_enable_npiv =0 ; }
@@ -10326,7 +10331,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) { lpfc_cmd = container_of(cmdiocbq, struct lpfc_scsi_buf, cur_iocbq); - lpfc_cmd->exch_busy = rspiocbq->iocb_flag &LPFC_EXCHANGE_BUSY ; +if (rspiocbq->iocb_flag &LPFC_EXCHANGE_BUSY ) + lpfc_cmd->flags |=LPFC_SBUF_XBUSY ; +else + lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY ; } pdone_q = cmdiocbq->context_un.wait_queue;
Signature · 1 line
1.7.11.7
Quoted 25 lines · James Smart
Implement support for wire-only DIF devices
This patch adds the ability to support auto-enablement of wire-only DIF (DIF is generated on TX to target, stripped on RX; OS unaware DIF in use) for a select set of devices. Currently, there is only 1 device vendor
supported: 3PARdata. When the feature is enabled, Inquiry commands are trapped, the vendor matched, and DIF enablement checked. In 3Par's case, there's a vendor specific check to see if the LUN supports DIF. If supported, DIF will be enabled on a per-lun basis. The driver will trap READS/WRITEs from the OS, check for LUN DIF enablement, and if set, turns on write-only DIF.Signed-off-by Dick Kennedy <[email protected]>Signed-off-by James Smart <[email protected]>--- drivers/scsi/lpfc/lpfc.h | 41 ++++ drivers/scsi/lpfc/lpfc_attr.c | 65 ++++++- drivers/scsi/lpfc/lpfc_crtn.h | 3 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 3 + drivers/scsi/lpfc/lpfc_init.c | 24 ++- drivers/scsi/lpfc/lpfc_mbox.c | 4 +- drivers/scsi/lpfc/lpfc_scsi.c | 410 ++++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_scsi.h | 7 +- drivers/scsi/lpfc/lpfc_sli.c | 36 ++-- 9 files changed, 532 insertions(+), 61 deletions(-)
<snip>
Quoted 56 lines
drivers/scsi/lpfc/lpfc_attr.c +31
-5@@ -135,16 +135,29 @@ lpfc_bg_info_show(struct device *dev, struct device_attribute *attr,struct Scsi_Host *shost =class_to_shost (dev);struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;struct lpfc_hba *phba = vport->phba; +int len =0 ; -if (phba->cfg_enable_bg) +if (phba->cfg_enable_bg) {if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) -return snprintf (buf,PAGE_SIZE ,"BlockGuard Enabled\n" ); + len +=snprintf (buf,PAGE_SIZE , +"BlockGuard Enabled\n" );else -return snprintf (buf,PAGE_SIZE , + len +=snprintf (buf,PAGE_SIZE ,"BlockGuard Not Supported\n" ); -else -return snprintf (buf,PAGE_SIZE , + }else { + len +=snprintf (buf,PAGE_SIZE ,"BlockGuard Disabled\n" ); + } + +if (phba->cfg_external_dif) { +if (phba->sli3_options &LPFC_SLI3_BG_ENABLED ) + len +=snprintf (buf + len,PAGE_SIZE , +"External DIF Enabled\n" ); +else + len +=snprintf (buf + len,PAGE_SIZE , +"External DIF Not Supported\n" ); + } +return len; } static ssize_t@@ -4681,6 +4694,30 @@ LPFC_ATTR_R(EnableXLane, 0, 0, 1, "Enable Express Lane Feature.");*/ LPFC_ATTR_RW (XLanePriority,0 ,0x0 ,0x7f ,"CS_CTL for Express Lane Feature." ); + +/* +* For T10 DIF / protection data support, the driver supports 4 modes +* of operation. +* +* Mode 1: (lpfc_enable_bg=1 lpfc_external_dif=1) +* All normal T10 DIF devices are supported. +* External DIF devices are supported. +* +* Mode 2: (lpfc_enable_bg=0 lpfc_external_dif=1) +* If you don't want to have the extra overhead of the upper SCSI Layer +* supporting T10-DIF, but you still want to support External DIF devices. +* Normal T10 DIF devices are NOT supported.
drivers/scsi/lpfc/lpfc_attr.c LPFC_ATTR_R(EnableXLane, 0, 0, 1, "Enable Express Lane Feature."); · line 4719
Quoted 10 lines
drivers/scsi/lpfc/lpfc_attr.c +10
-0+* External DIF devices are supported. +* +* Mode 3: (lpfc_enable_bg=1 lpfc_external_dif=0) +* All normal T10 DIF devices are supported. +* External DIF devices are NOT supported. +* +* Mode 4: (lpfc_enable_bg=0 lpfc_external_dif=1) +* No normal T10-DIF and no external DIF devices supported, +* This would be the driver default values for these module parameters. +*/
Not lpfc_external_dif=0?
Quoted 9 lines
drivers/scsi/lpfc/lpfc_attr.c +2
-0/* # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) # 0 = BlockGuard disabled (default) @@ -4690,6 +4727,15 @@ LPFC_ATTR_RW(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature.");LPFC_ATTR_R (enable_bg,0 ,0 ,1 ,"Enable BlockGuard Support" );/* +# lpfc_external_dif: Enable External DIF support on select devices +# 0 = External DIF disabled (default)
drivers/scsi/lpfc/lpfc_attr.c LPFC_ATTR_RW(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature."); · line 4741
Quoted 10 lines
drivers/scsi/lpfc/lpfc_attr.c +7
-0+# 1 = External DIF enabled +# Value range is [0,1]. Default value is 0. +*/ +LPFC_ATTR_R (external_dif,0 ,0 ,1 , +"External T10-DIF Support, on select devices" ); + +/* # lpfc_fcp_look_ahead: Look ahead for completions in FCP start routine # 0 = disabled (default) # 1 = enabled
Sebastian
Quoted 11 lines · James Smart
Implement support for wire-only DIF devices
This patch adds the ability to support auto-enablement of wire-only DIF (DIF is generated on TX to target, stripped on RX; OS unaware DIF in use) for a select set of devices. Currently, there is only 1 device vendor
supported: 3PARdata. When the feature is enabled, Inquiry commands are trapped, the vendor matched, and DIF enablement checked. In 3Par's case, there's a vendor specific check to see if the LUN supports DIF. If supported, DIF will be enabled on a per-lun basis. The driver will trap READS/WRITEs from the OS, check for LUN DIF enablement, and if set, turns on write-only DIF.
NAK. We do support proper DIF, and anyone who wants it should enable the real thing.
And even if we would want to support a hack like this we'd do it genericly an not in a driver.
Quoted 11 lines
Quoted 11 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
"Christoph" == Christoph Hellwig <[email protected]> writes:
This patch adds the ability to support auto-enablement of wire-only DIF (DIF is generated on TX to target, stripped on RX; OS unaware DIF in use) for a select set of devices. Currently, there is only 1 device vendor supported: 3PARdata. When the feature is enabled, Inquiry commands are trapped, the vendor matched, and DIF enablement checked. In 3Par's case, there's a vendor specific check to see if the LUN supports DIF. If supported, DIF will be enabled on a per-lun basis. The driver will trap READS/WRITEs from the OS, check for LUN DIF enablement, and if set, turns on write-only DIF.
Christoph> NAK. We do support proper DIF, and anyone who wants it should Christoph> enable the real thing.
Christoph> And even if we would want to support a hack like this we'd do Christoph> it genericly an not in a driver.
Agree completely.
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering
fyi - in the v3 of the lpfc 10.5.0.0 patches I just posted, I pulled the patch. We will see what to do with it. We may come back with a set of generic midlayer patches.
-- james s
Quoted 23 lines · Christoph Hellwig
Quoted 11 lines · James Smart
Implement support for wire-only DIF devices
This patch adds the ability to support auto-enablement of wire-only DIF (DIF is generated on TX to target, stripped on RX; OS unaware DIF in use) for a select set of devices. Currently, there is only 1 device vendor
supported: 3PARdata. When the feature is enabled, Inquiry commands are trapped, the vendor matched, and DIF enablement checked. In 3Par's case, there's a vendor specific check to see if the LUN supports DIF. If supported, DIF will be enabled on a per-lun basis. The driver will trap READS/WRITEs from the OS, check for LUN DIF enablement, and if set, turns on write-only DIF.NAK. We do support proper DIF, and anyone who wants it should enable the real thing.
And even if we would want to support a hack like this we'd do it genericly an not in a driver.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"James" == James Smart <[email protected]> writes:
James> fyi - in the v3 of the lpfc 10.5.0.0 patches I just posted, I James> pulled the patch. We will see what to do with it. We may come James> back with a set of generic midlayer patches.
We already have a DIF blacklist. We could have an explicit whitelist as well. But it begs the question: Why on earth are 3Par not following the spec? And why don't they just fix their firmware to report the right thing?
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering