lpfc 8.3.45: Incorporated support of a low-latency io path
Subsystems (2)
PATCH 2/8 lpfc 8.3.45: Incorporated support of a low-latency io path
Incorporated support of a low-latency io path
Signed-off-by James Smart <[email protected]>
---
lpfc.h | 17 + lpfc_attr.c | 600 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- lpfc_crtn.h | 22 ++ lpfc_debugfs.c | 98 +++++++++ lpfc_hw.h | 1 lpfc_hw4.h | 6 lpfc_init.c | 241 ++++++++++++++++++++++ lpfc_mem.c | 25 ++ lpfc_scsi.c | 406 +++++++++++++++++++++++++++++++++++++- lpfc_scsi.h | 18 + lpfc_sli.c | 241 +++++++++++++++++++++- lpfc_sli.h | 2 lpfc_sli4.h | 20 + 13 files changed, 1622 insertions(+), 75 deletions(-)
drivers/scsi/lpfc/lpfc_attr.c +551 -49
@@ -529,6 +529,27 @@ lpfc_sli4_protocol_show(struct device *d }/** +* lpfc_oas_supported_show - Return whether or not Optimized Access Storage +* (OAS) is supported. +* @dev: class unused variable. +* @attr: device attribute, not used. +* @buf: on return contains the module description text. +* +* Returns: size of formatted string. +**/ +static ssize_t +lpfc_oas_supported_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; +struct lpfc_hba *phba = vport->phba; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , + phba->sli4_hba.pc_sli4_params.oas_supported); +} + +/** * lpfc_link_state_store - Transition the link_state on an HBA port * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used.
@@ -2041,9 +2062,53 @@ static DEVICE_ATTR(lpfc_dss, S_IRUGO, lp static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, lpfc_sriov_hw_max_virtfn_show, NULL); static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); +static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show, + NULL);static char *lpfc_soft_wwn_key ="C99G71SL8032A" ; +#define WWN_SZ 8 +/** +* lpfc_wwn_set - Convert string to the 8 byte WWN value. +* @buf: WWN string. +* @cnt: Length of string. +* @wwn: Array to receive converted wwn value. +* +* Returns: +* -EINVAL if the buffer does not contain a valid wwn +* 0 success +**/ +static size_t +lpfc_wwn_set (const char *buf,size_t cnt,char wwn[]) +{ +unsigned int i, j; + +/* Count may include a LF at end of string */ +if (buf[cnt-1 ] =='\n' ) + cnt--; +if ((cnt <16 ) || (cnt >18 ) || ((cnt ==17 ) && (*buf++ !='x' )) || + ((cnt ==18 ) && ((*buf++ !='0' ) || (*buf++ !='x' )))) +return -EINVAL ; + +memset (wwn,0 ,WWN_SZ ); + +/* Validate and store the new name */ +for (i =0 , j =0 ; i <16 ; i++) { +if ((*buf >='a' ) && (*buf <='f' )) + j = ((j <<4 ) | ((*buf++ -'a' ) +10 )); +else if ((*buf >='A' ) && (*buf <='F' )) + j = ((j <<4 ) | ((*buf++ -'A' ) +10 )); +else if ((*buf >='0' ) && (*buf <='9' )) + j = ((j <<4 ) | (*buf++ -'0' )); +else +return -EINVAL ; +if (i %2 ) { + wwn[i/2 ] = j &0xff ; + j =0 ; + } + } +return 0 ; +}/** * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid * @dev: class device that is converted into a Scsi_host.
@@ -2132,9 +2197,9 @@ lpfc_soft_wwpn_store(struct device *dev,struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;struct lpfc_hba *phba = vport->phba;struct completion online_compl; -int stat1=0 , stat2=0 ; -unsigned int i, j, cnt=count; -u8 wwpn[8 ]; +int stat1 =0 , stat2 =0 ; +unsigned int cnt = count; +u8 wwpn[WWN_SZ ];int rc;if (!phba->cfg_enable_hba_reset)
@@ -2149,29 +2214,19 @@ lpfc_soft_wwpn_store(struct device *dev,if (buf[cnt-1 ] =='\n' ) cnt--; -if (!phba->soft_wwn_enable || (cnt <16 ) || (cnt >18 ) || - ((cnt ==17 ) && (*buf++ !='x' )) || - ((cnt ==18 ) && ((*buf++ !='0' ) || (*buf++ !='x' )))) +if (!phba->soft_wwn_enable)return -EINVAL ; +/* lock setting wwpn, wwnn down */ phba->soft_wwn_enable =0 ; -memset (wwpn,0 ,sizeof (wwpn)); - -/* Validate and store the new name */ -for (i=0 , j=0 ; i <16 ; i++) { -int value; - - value =hex_to_bin (*buf++); -if (value >=0 ) - j = (j <<4 ) | value; -else -return -EINVAL ; -if (i %2 ) { - wwpn[i/2 ] = j &0xff ; - j =0 ; - } + rc =lpfc_wwn_set (buf, cnt, wwpn); +if (!rc) { +/* not able to set wwpn, unlock it */ + phba->soft_wwn_enable =1 ; +return rc; } + phba->cfg_soft_wwpn =wwn_to_u64 (wwpn);fc_host_port_name (shost) = phba->cfg_soft_wwpn;if (phba->cfg_soft_wwnn)
@@ -2198,7 +2253,7 @@ lpfc_soft_wwpn_store(struct device *dev, "reinit adapter - %d\n", stat2);return (stat1 || stat2) ? -EIO : count; } -static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ +static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR, lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);/**
@@ -2235,39 +2290,25 @@ lpfc_soft_wwnn_store(struct device *dev, {struct Scsi_Host *shost =class_to_shost (dev);struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; -unsigned int i, j, cnt=count; -u8 wwnn[8 ]; +unsigned int cnt = count; +u8 wwnn[WWN_SZ ]; +int rc;/* count may include a LF at end of string */ if (buf[cnt-1 ] =='\n' ) cnt--; -if (!phba->soft_wwn_enable || (cnt <16 ) || (cnt >18 ) || - ((cnt ==17 ) && (*buf++ !='x' )) || - ((cnt ==18 ) && ((*buf++ !='0' ) || (*buf++ !='x' )))) +if (!phba->soft_wwn_enable)return -EINVAL ; -/* -* Allow wwnn to be set many times, as long as the enable is set. -* However, once the wwpn is set, everything locks. -*/ - -memset (wwnn,0 ,sizeof (wwnn)); - -/* Validate and store the new name */ -for (i=0 , j=0 ; i <16 ; i++) { -int value; - - value =hex_to_bin (*buf++); -if (value >=0 ) - j = (j <<4 ) | value; -else -return -EINVAL ; -if (i %2 ) { - wwnn[i/2 ] = j &0xff ; - j =0 ; - } + rc =lpfc_wwn_set (buf, cnt, wwnn); +if (!rc) { +/* Allow wwnn to be set many times, as long as the enable +* is set. However, once the wwpn is set, everything locks. +*/ +return rc; } + phba->cfg_soft_wwnn =wwn_to_u64 (wwnn); dev_printk(KERN_NOTICE, &phba->pcidev->dev,
@@ -2276,9 +2317,438 @@ lpfc_soft_wwnn_store(struct device *dev,return count; } -static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ +static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR, lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); +/** +* lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for +* Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* Returns: +* value of count +**/ +static ssize_t +lpfc_oas_tgt_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"0x%llx\n" , +wwn_to_u64 (phba->cfg_oas_tgt_wwpn)); +} + +/** +* lpfc_oas_tgt_store - Store wwpn of target whose luns maybe enabled for +* Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* @count: Size of the data buffer. +* +* Returns: +* -EINVAL count is invalid, invalid wwpn byte invalid +* -EPERM oas is not supported by hba +* value of count on success +**/ +static ssize_t +lpfc_oas_tgt_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; +unsigned int cnt = count; +uint8_t wwpn[WWN_SZ ]; +int rc; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +/* count may include a LF at end of string */ +if (buf[cnt-1 ] =='\n' ) + cnt--; + + rc =lpfc_wwn_set (buf, cnt, wwpn); +if (rc) +return rc; + +memcpy (phba->cfg_oas_tgt_wwpn, wwpn, (8 *sizeof (uint8_t ))); +memcpy (phba->sli4_hba.oas_next_tgt_wwpn, wwpn, (8 *sizeof (uint8_t ))); +if (wwn_to_u64 (wwpn) ==0 ) + phba->cfg_oas_flags |=OAS_FIND_ANY_TARGET ; +else + phba->cfg_oas_flags &= ~OAS_FIND_ANY_TARGET ; + phba->cfg_oas_flags &= ~OAS_LUN_VALID ; + phba->sli4_hba.oas_next_lun =FIND_FIRST_OAS_LUN ; +return count; +} +static DEVICE_ATTR(lpfc_xlane_tgt, S_IRUGO | S_IWUSR, + lpfc_oas_tgt_show, lpfc_oas_tgt_store); + +/** +* lpfc_oas_vpt_show - Return wwpn of vport whose targets maybe enabled +* for Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* Returns: +* value of count on success +**/ +static ssize_t +lpfc_oas_vpt_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"0x%llx\n" , +wwn_to_u64 (phba->cfg_oas_vpt_wwpn)); +} + +/** +* lpfc_oas_vpt_store - Store wwpn of vport whose targets maybe enabled +* for Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* @count: Size of the data buffer. +* +* Returns: +* -EINVAL count is invalid, invalid wwpn byte invalid +* -EPERM oas is not supported by hba +* value of count on success +**/ +static ssize_t +lpfc_oas_vpt_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; +unsigned int cnt = count; +uint8_t wwpn[WWN_SZ ]; +int rc; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +/* count may include a LF at end of string */ +if (buf[cnt-1 ] =='\n' ) + cnt--; + + rc =lpfc_wwn_set (buf, cnt, wwpn); +if (rc) +return rc; + +memcpy (phba->cfg_oas_vpt_wwpn, wwpn, (8 *sizeof (uint8_t ))); +memcpy (phba->sli4_hba.oas_next_vpt_wwpn, wwpn, (8 *sizeof (uint8_t ))); +if (wwn_to_u64 (wwpn) ==0 ) + phba->cfg_oas_flags |=OAS_FIND_ANY_VPORT ; +else + phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT ; + phba->cfg_oas_flags &= ~OAS_LUN_VALID ; + phba->sli4_hba.oas_next_lun =FIND_FIRST_OAS_LUN ; +return count; +} +static DEVICE_ATTR(lpfc_xlane_vpt, S_IRUGO | S_IWUSR, + lpfc_oas_vpt_show, lpfc_oas_vpt_store); + +/** +* lpfc_oas_lun_state_show - Return the current state (enabled or disabled) +* of whether luns will be enabled or disabled +* for Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* Returns: +* size of formatted string. +**/ +static ssize_t +lpfc_oas_lun_state_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , phba->cfg_oas_lun_state); +} + +/** +* lpfc_oas_lun_state_store - Store the state (enabled or disabled) +* of whether luns will be enabled or disabled +* for Optimized Access Storage (OAS) operations. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* @count: Size of the data buffer. +* +* Returns: +* -EINVAL count is invalid, invalid wwpn byte invalid +* -EPERM oas is not supported by hba +* value of count on success +**/ +static ssize_t +lpfc_oas_lun_state_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; +int val =0 ; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +if (!isdigit (buf[0 ])) +return -EINVAL ; + +if (sscanf (buf,"%i" , &val) !=1 ) +return -EINVAL ; + +if ((val !=0 ) && (val !=1 )) +return -EINVAL ; + + phba->cfg_oas_lun_state = val; + +return strlen (buf); +} +static DEVICE_ATTR(lpfc_xlane_lun_state, S_IRUGO | S_IWUSR, + lpfc_oas_lun_state_show, lpfc_oas_lun_state_store); + +/** +* lpfc_oas_lun_status_show - Return the status of the Optimized Access +* Storage (OAS) lun returned by the +* lpfc_oas_lun_show function. +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* Returns: +* size of formatted string. +**/ +static ssize_t +lpfc_oas_lun_status_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +if (!(phba->cfg_oas_flags &OAS_LUN_VALID )) +return -EFAULT ; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , phba->cfg_oas_lun_status); +} +static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO, + lpfc_oas_lun_status_show, NULL); + + +/** +* lpfc_oas_lun_state_set - enable or disable a lun for Optimized Access Storage +* (OAS) operations. +* @phba: lpfc_hba pointer. +* @ndlp: pointer to fcp target node. +* @lun: the fc lun for setting oas state. +* @oas_state: the oas state to be set to the lun. +* +* Returns: +* SUCCESS : 0 +* -EPERM OAS is not enabled or not supported by this port. +* +*/ +static size_t +lpfc_oas_lun_state_set (struct lpfc_hba *phba,uint8_t vpt_wwpn[], +uint8_t tgt_wwpn[],uint64_t lun,uint32_t oas_state) +{ + +int rc =0 ; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +if (oas_state) { +if (!lpfc_enable_oas_lun (phba, (struct lpfc_name *)vpt_wwpn, + (struct lpfc_name *)tgt_wwpn, lun)) + rc = -ENOMEM ; + }else { +lpfc_disable_oas_lun (phba, (struct lpfc_name *)vpt_wwpn, + (struct lpfc_name *)tgt_wwpn, lun); + } +return rc; + +} + +/** +* lpfc_oas_lun_get_next - get the next lun that has been enabled for Optimized +* Access Storage (OAS) operations. +* @phba: lpfc_hba pointer. +* @vpt_wwpn: wwpn of the vport associated with the returned lun +* @tgt_wwpn: wwpn of the target associated with the returned lun +* @lun_status: status of the lun returned lun +* +* Returns the first or next lun enabled for OAS operations for the vport/target +* specified. If a lun is found, its vport wwpn, target wwpn and status is +* returned. If the lun is not found, NOT_OAS_ENABLED_LUN is returned. +* +* Return: +* lun that is OAS enabled for the vport/target +* NOT_OAS_ENABLED_LUN when no oas enabled lun found. +*/ +static uint64_t +lpfc_oas_lun_get_next (struct lpfc_hba *phba,uint8_t vpt_wwpn[], +uint8_t tgt_wwpn[],uint32_t *lun_status) +{ +uint64_t found_lun; + +if (unlikely (!phba) || !vpt_wwpn || !tgt_wwpn) +return NOT_OAS_ENABLED_LUN ; +if (lpfc_find_next_oas_lun (phba, (struct lpfc_name *) + phba->sli4_hba.oas_next_vpt_wwpn, + (struct lpfc_name *) + phba->sli4_hba.oas_next_tgt_wwpn, + &phba->sli4_hba.oas_next_lun, + (struct lpfc_name *)vpt_wwpn, + (struct lpfc_name *)tgt_wwpn, + &found_lun, lun_status)) +return found_lun; +else +return NOT_OAS_ENABLED_LUN ; +} + +/** +* lpfc_oas_lun_state_change - enable/disable a lun for OAS operations +* @phba: lpfc_hba pointer. +* @vpt_wwpn: vport wwpn by reference. +* @tgt_wwpn: target wwpn by reference. +* @lun: the fc lun for setting oas state. +* @oas_state: the oas state to be set to the oas_lun. +* +* This routine enables (OAS_LUN_ENABLE) or disables (OAS_LUN_DISABLE) +* a lun for OAS operations. +* +* Return: +* SUCCESS: 0 +* -ENOMEM: failed to enable an lun for OAS operations +* -EPERM: OAS is not enabled +*/ +static ssize_t +lpfc_oas_lun_state_change (struct lpfc_hba *phba,uint8_t vpt_wwpn[], +uint8_t tgt_wwpn[],uint64_t lun, +uint32_t oas_state) +{ + +int rc; + + rc =lpfc_oas_lun_state_set (phba, vpt_wwpn, tgt_wwpn, lun, + oas_state); +return rc; +} + +/** +* lpfc_oas_lun_show - Return oas enabled luns from a chosen target +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* This routine returns a lun enabled for OAS each time the function +* is called. +* +* Returns: +* SUCCESS: size of formatted string. +* -EFAULT: target or vport wwpn was not set properly. +* -EPERM: oas is not enabled. +**/ +static ssize_t +lpfc_oas_lun_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +uint64_t oas_lun; +int len =0 ; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +if (wwn_to_u64 (phba->cfg_oas_vpt_wwpn) ==0 ) +if (!(phba->cfg_oas_flags &OAS_FIND_ANY_VPORT )) +return -EFAULT ; + +if (wwn_to_u64 (phba->cfg_oas_tgt_wwpn) ==0 ) +if (!(phba->cfg_oas_flags &OAS_FIND_ANY_TARGET )) +return -EFAULT ; + + oas_lun =lpfc_oas_lun_get_next (phba, phba->cfg_oas_vpt_wwpn, + phba->cfg_oas_tgt_wwpn, + &phba->cfg_oas_lun_status); +if (oas_lun !=NOT_OAS_ENABLED_LUN ) + phba->cfg_oas_flags |=OAS_LUN_VALID ; + + len +=snprintf (buf + len,PAGE_SIZE -len,"0x%llx" , oas_lun); + +return len; +} + +/** +* lpfc_oas_lun_store - Sets the OAS state for lun +* @dev: class device that is converted into a Scsi_host. +* @attr: device attribute, not used. +* @buf: buffer for passing information. +* +* This function sets the OAS state for lun. Before this function is called, +* the vport wwpn, target wwpn, and oas state need to be set. +* +* Returns: +* SUCCESS: size of formatted string. +* -EFAULT: target or vport wwpn was not set properly. +* -EPERM: oas is not enabled. +* size of formatted string. +**/ +static ssize_t +lpfc_oas_lun_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; +uint64_t scsi_lun; +ssize_t rc; + +if (!phba->cfg_EnableXLane) +return -EPERM ; + +if (wwn_to_u64 (phba->cfg_oas_vpt_wwpn) ==0 ) +return -EFAULT ; + +if (wwn_to_u64 (phba->cfg_oas_tgt_wwpn) ==0 ) +return -EFAULT ; + +if (!isdigit (buf[0 ])) +return -EINVAL ; + +if (sscanf (buf,"0x%llx" , &scsi_lun) !=1 ) +return -EINVAL ; + +lpfc_printf_log (phba,KERN_INFO ,LOG_INIT , +"3372 Try to set vport 0x%llx target 0x%llx lun:%lld " +"with oas set to %d\n" , +wwn_to_u64 (phba->cfg_oas_vpt_wwpn), +wwn_to_u64 (phba->cfg_oas_tgt_wwpn), scsi_lun, + phba->cfg_oas_lun_state); + + rc =lpfc_oas_lun_state_change (phba, phba->cfg_oas_vpt_wwpn, + phba->cfg_oas_tgt_wwpn, scsi_lun, + phba->cfg_oas_lun_state); + +if (rc) +return rc; + +return count; +} +static DEVICE_ATTR(lpfc_xlane_lun, S_IRUGO | S_IWUSR, + lpfc_oas_lun_show, lpfc_oas_lun_store);static int lpfc_poll =0 ;module_param (lpfc_poll, int,S_IRUGO );
@@ -4157,6 +4627,21 @@ LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "LPFC_ATTR_R (enable_hba_heartbeat,0 ,0 ,1 ,"Enable HBA Heartbeat." );/* +# lpfc_EnableXLane: Enable Express Lane Feature +# 0x0 Express Lane Feature disabled +# 0x1 Express Lane Feature enabled +# Value range is [0,1]. Default value is 0. +*/ +LPFC_ATTR_R (EnableXLane,0 ,0 ,1 ,"Enable Express Lane Feature." ); + +/* +# lpfc_XLanePriority: Define CS_CTL priority for Express Lane Feature +# 0x0 - 0x7f = CS_CTL field in FC header (high 7 bits) +# Value range is [0x0,0x7f]. Default value is 0 +*/ +LPFC_ATTR_R (XLanePriority,0 ,0x0 ,0x7f ,"CS_CTL for Express Lane Feature." ); + +/* # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) # 0 = BlockGuard disabled (default) # 1 = BlockGuard enabled
@@ -4317,6 +4802,13 @@ struct device_attribute *lpfc_hba_attrs[ &dev_attr_lpfc_soft_wwn_enable, &dev_attr_lpfc_enable_hba_reset, &dev_attr_lpfc_enable_hba_heartbeat, + &dev_attr_lpfc_EnableXLane, + &dev_attr_lpfc_XLanePriority, + &dev_attr_lpfc_xlane_lun, + &dev_attr_lpfc_xlane_tgt, + &dev_attr_lpfc_xlane_vpt, + &dev_attr_lpfc_xlane_lun_state, + &dev_attr_lpfc_xlane_lun_status, &dev_attr_lpfc_sg_seg_cnt, &dev_attr_lpfc_max_scsicmpl_time, &dev_attr_lpfc_stat_data_ctrl,
@@ -4335,6 +4827,7 @@ struct device_attribute *lpfc_hba_attrs[ &dev_attr_lpfc_dss, &dev_attr_lpfc_sriov_hw_max_virtfn, &dev_attr_protocol, + &dev_attr_lpfc_xlane_supported, NULL, };
@@ -5296,11 +5789,20 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)lpfc_fcp_io_channel_init (phba, lpfc_fcp_io_channel);lpfc_enable_hba_reset_init (phba, lpfc_enable_hba_reset);lpfc_enable_hba_heartbeat_init (phba, lpfc_enable_hba_heartbeat); +lpfc_EnableXLane_init (phba, lpfc_EnableXLane); +if (phba->sli_rev !=LPFC_SLI_REV4 ) + phba->cfg_EnableXLane =0 ; +lpfc_XLanePriority_init (phba, lpfc_XLanePriority); +memset (phba->cfg_oas_tgt_wwpn,0 , (8 *sizeof (uint8_t ))); +memset (phba->cfg_oas_vpt_wwpn,0 , (8 *sizeof (uint8_t ))); + phba->cfg_oas_lun_state =0 ; + phba->cfg_oas_lun_status =0 ; + phba->cfg_oas_flags =0 ;lpfc_enable_bg_init (phba, lpfc_enable_bg);if (phba->sli_rev ==LPFC_SLI_REV4 ) phba->cfg_poll =0 ;else - phba->cfg_poll = lpfc_poll; + phba->cfg_poll = lpfc_poll; phba->cfg_soft_wwnn =0L ; phba->cfg_soft_wwpn =0L ;lpfc_sg_seg_cnt_init (phba, lpfc_sg_seg_cnt);
drivers/scsi/lpfc/lpfc_crtn.h +22 -0
@@ -187,6 +187,11 @@ void lpfc_offline_prep(struct lpfc_hba *void lpfc_offline (struct lpfc_hba *);void lpfc_reset_hba (struct lpfc_hba *); +int lpfc_fof_queue_create (struct lpfc_hba *); +int lpfc_fof_queue_setup (struct lpfc_hba *); +int lpfc_fof_queue_destroy (struct lpfc_hba *); +irqreturn_t lpfc_sli4_fof_intr_handler (int ,void *); +int lpfc_sli_setup (struct lpfc_hba *);int lpfc_sli_queue_setup (struct lpfc_hba *);
@@ -472,3 +477,20 @@ void lpfc_free_sgl_list(struct lpfc_hbauint32_t lpfc_sli_port_speed_get (struct lpfc_hba *);int lpfc_sli4_request_firmware_update (struct lpfc_hba *,uint8_t );void lpfc_sli4_offline_eratt (struct lpfc_hba *); + +struct lpfc_device_data *lpfc_create_device_data (struct lpfc_hba *, +struct lpfc_name *, +struct lpfc_name *, +uint64_t ,bool ); +void lpfc_delete_device_data (struct lpfc_hba *,struct lpfc_device_data *); +struct lpfc_device_data *__lpfc_get_device_data (struct lpfc_hba *, +struct list_head *list, +struct lpfc_name *, +struct lpfc_name *,uint64_t ); +bool lpfc_enable_oas_lun (struct lpfc_hba *,struct lpfc_name *, +struct lpfc_name *,uint64_t ); +bool lpfc_disable_oas_lun (struct lpfc_hba *,struct lpfc_name *, +struct lpfc_name *,uint64_t ); +bool lpfc_find_next_oas_lun (struct lpfc_hba *,struct lpfc_name *, +struct lpfc_name *,uint64_t *,struct lpfc_name *, +struct lpfc_name *,uint64_t *,uint32_t *);
drivers/scsi/lpfc/lpfc_debugfs.c +98 -0
104 lines not on this page · raw message
drivers/scsi/lpfc/lpfc.h +17 -0
@@ -722,6 +722,20 @@ struct lpfc_hba {uint32_t cfg_hba_queue_depth;uint32_t cfg_enable_hba_reset;uint32_t cfg_enable_hba_heartbeat; +uint32_t cfg_fof; +uint32_t cfg_EnableXLane; +uint8_t cfg_oas_tgt_wwpn[8 ]; +uint8_t cfg_oas_vpt_wwpn[8 ]; +uint32_t cfg_oas_lun_state; +#define OAS_LUN_ENABLE 1 +#define OAS_LUN_DISABLE 0 +uint32_t cfg_oas_lun_status; +#define OAS_LUN_STATUS_EXISTS 0x01 +uint32_t cfg_oas_flags; +#define OAS_FIND_ANY_VPORT 0x01 +#define OAS_FIND_ANY_TARGET 0x02 +#define OAS_LUN_VALID 0x04 +uint32_t cfg_XLanePriority;uint32_t cfg_enable_bg;uint32_t cfg_hostmem_hgp;uint32_t cfg_log_verbose;
@@ -973,6 +987,9 @@ struct lpfc_hba {atomic_t sdev_cnt;uint8_t fips_spec_rev;uint8_t fips_level; +spinlock_t devicelock;/* lock for luns list */ +mempool_t *device_data_mem_pool; +struct list_head luns; }; static inline struct Scsi_Host *
drivers/scsi/lpfc/lpfc_hw4.h +6 -0
@@ -2616,6 +2616,9 @@ struct lpfc_sli4_parameters {#define cfg_phwq_SHIFT 15#define cfg_phwq_MASK 0x00000001#define cfg_phwq_WORD word12 +#define cfg_oas_SHIFT 25 +#define cfg_oas_MASK 0x00000001 +#define cfg_oas_WORD word12#define cfg_loopbk_scope_SHIFT 28#define cfg_loopbk_scope_MASK 0x0000000f#define cfg_loopbk_scope_WORD word12
@@ -3322,6 +3325,9 @@ struct wqe_common {#define wqe_ebde_cnt_SHIFT 0#define wqe_ebde_cnt_MASK 0x0000000f#define wqe_ebde_cnt_WORD word10 +#define wqe_oas_SHIFT 6 +#define wqe_oas_MASK 0x00000001 +#define wqe_oas_WORD word10#define wqe_lenloc_SHIFT 7#define wqe_lenloc_MASK 0x00000003#define wqe_lenloc_WORD word10
drivers/scsi/lpfc/lpfc_hw.h +1 -0
@@ -45,6 +45,7 @@#define LPFC_EXTRA_RING 1/* ring 1 for other protocols */ #define LPFC_ELS_RING 2/* ring 2 for ELS commands */ #define LPFC_FCP_NEXT_RING 3 +#define LPFC_FCP_OAS_RING 3#define SLI2_IOCB_CMD_R0_ENTRIES 172/* SLI-2 FCP command ring entries */ #define SLI2_IOCB_RSP_R0_ENTRIES 134/* SLI-2 FCP response ring entries */
drivers/scsi/lpfc/lpfc_init.c +235 -6
369 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_mem.c +25 -0
@@ -42,6 +42,7 @@#define LPFC_MBUF_POOL_SIZE 64/* max elements in MBUF safety pool */ #define LPFC_MEM_POOL_SIZE 64/* max elem in non-DMA safety pool */ +#define LPFC_DEVICE_DATA_POOL_SIZE 64/* max elements in device data pool */ int lpfc_mem_alloc_active_rrq_pool_s4 (struct lpfc_hba *phba) {
@@ -164,6 +165,16 @@ lpfc_mem_alloc(struct lpfc_hba *phba, in phba->lpfc_drb_pool =NULL ; } +if (phba->cfg_EnableXLane) { + phba->device_data_mem_pool =mempool_create_kmalloc_pool ( +LPFC_DEVICE_DATA_POOL_SIZE , +sizeof (struct lpfc_device_data )); +if (!phba->device_data_mem_pool) + goto fail_free_hrb_pool; + }else { + phba->device_data_mem_pool =NULL ; + } +return 0 ; fail_free_hrb_pool:pci_pool_destroy (phba->lpfc_hrb_pool);
@@ -206,6 +217,7 @@ lpfc_mem_free(struct lpfc_hba *phba) {int i;struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; +struct lpfc_device_data *device_data;/* Free HBQ pools */ lpfc_sli_hbqbuf_free_all (phba);
@@ -249,6 +261,19 @@ lpfc_mem_free(struct lpfc_hba *phba)pci_pool_destroy (phba->lpfc_scsi_dma_buf_pool); phba->lpfc_scsi_dma_buf_pool =NULL ; +/* Free Device Data memory pool */ +if (phba->device_data_mem_pool) { +/* Ensure all objects have been returned to the pool */ +while (!list_empty (&phba->luns)) { + device_data =list_first_entry (&phba->luns, + struct lpfc_device_data, + listentry); +list_del (&device_data->listentry); +mempool_free (device_data, phba->device_data_mem_pool); + } +mempool_destroy (phba->device_data_mem_pool); + } + phba->device_data_mem_pool =NULL ;return ; }
drivers/scsi/lpfc/lpfc_scsi.c +398 -8
501 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_scsi.h +18 -0
@@ -41,6 +41,20 @@ struct lpfc_rport_data {struct lpfc_nodelist *pnode;/* Pointer to the node structure. */ }; +struct lpfc_device_id { +struct lpfc_name vport_wwpn; +struct lpfc_name target_wwpn; +uint64_t lun; +}; + +struct lpfc_device_data { +struct list_head listentry; +struct lpfc_rport_data *rport_data; +struct lpfc_device_id device_id; +bool oas_enabled; +bool available; +}; +struct fcp_rsp {uint32_t rspRsvd1;/* FC Word 0, byte 0:3 */ uint32_t rspRsvd2;/* FC Word 1, byte 0:3 */
@@ -166,3 +180,7 @@ struct lpfc_scsi_buf {#define LPFC_SCSI_DMA_EXT_SIZE 264#define LPFC_BPL_SIZE 1024#define MDAC_DIRECT_CMD 0x22 + +#define FIND_FIRST_OAS_LUN 0 +#define NO_MORE_OAS_LUN -1 +#define NOT_OAS_ENABLED_LUN NO_MORE_OAS_LUN
drivers/scsi/lpfc/lpfc_sli4.h +19 -1
@@ -39,6 +39,10 @@#define LPFC_FCP_IO_CHAN_MIN 1#define LPFC_FCP_IO_CHAN_MAX 16 +/* Number of channels used for Flash Optimized Fabric (FOF) operations */ + +#define LPFC_FOF_IO_CHAN_NUM 1 +/* * Provide the default FCF Record attributes used by the driver * when nonFIP mode is configured and there is no other default
@@ -399,6 +403,7 @@ struct lpfc_pc_sli4_params {uint32_t if_page_sz;uint32_t rq_db_window;uint32_t loopbk_scope; +uint32_t oas_supported;uint32_t eq_pages_max;uint32_t eqe_size;uint32_t cq_pages_max;
@@ -439,6 +444,8 @@ struct lpfc_sli4_lnk_info {uint8_t lnk_no; }; +#define LPFC_SLI4_HANDLER_CNT (LPFC_FCP_IO_CHAN_MAX+ \ + LPFC_FOF_IO_CHAN_NUM)#define LPFC_SLI4_HANDLER_NAME_SZ 16/* Used for IRQ vector to CPU mapping */
@@ -507,7 +514,7 @@ struct lpfc_sli4_hba {struct lpfc_register sli_intf;struct lpfc_pc_sli4_params pc_sli4_params;struct msix_entry *msix_entries; -uint8_t handler_name[LPFC_FCP_IO_CHAN_MAX ][LPFC_SLI4_HANDLER_NAME_SZ ]; +uint8_t handler_name[LPFC_SLI4_HANDLER_CNT ][LPFC_SLI4_HANDLER_NAME_SZ ];struct lpfc_fcp_eq_hdl *fcp_eq_hdl;/* FCP per-WQ handle */ /* Pointers to the constructed SLI4 queues */
@@ -527,6 +534,17 @@ struct lpfc_sli4_hba {uint32_t ulp0_mode;/* ULP0 protocol mode */ uint32_t ulp1_mode;/* ULP1 protocol mode */ +struct lpfc_queue *fof_eq;/* Flash Optimized Fabric Event queue */ + +/* Optimized Access Storage specific queues/structures */ + +struct lpfc_queue *oas_cq;/* OAS completion queue */ +struct lpfc_queue *oas_wq;/* OAS Work queue */ +struct lpfc_sli_ring *oas_ring; +uint64_t oas_next_lun; +uint8_t oas_next_tgt_wwpn[8 ]; +uint8_t oas_next_vpt_wwpn[8 ]; +/* Setup information for various queue parameters */ int eq_esize;int eq_ecount;
drivers/scsi/lpfc/lpfc_sli.c +230 -11
301 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_sli.h +2 -0
@@ -78,6 +78,8 @@ struct lpfc_iocbq {#define LPFC_FIP_ELS_ID_MASK 0xc000/* ELS_ID range 0-3, non-shifted mask */ #define LPFC_FIP_ELS_ID_SHIFT 14 +#define LPFC_IO_OAS 0x10000/* OAS FCP IO */ +uint32_t drvrTimeout;/* driver timeout in seconds */ uint32_t fcp_wqidx;/* index to FCP work queue */ struct lpfc_vport *vport;/* virtual port pointer */