diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 2120 | 
1 files changed, 1661 insertions, 459 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c1cbec01345..1d7a5c34ee8 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@  /*******************************************************************   * This file is part of the Emulex Linux Device Driver for         *   * Fibre Channel Host Bus Adapters.                                * - * Copyright (C) 2004-2009 Emulex.  All rights reserved.           * + * Copyright (C) 2004-2014 Emulex.  All rights reserved.           *   * EMULEX and SLI are trademarks of Emulex.                        *   * www.emulex.com                                                  *   * Portions Copyright (C) 2004-2005 Christoph Hellwig              * @@ -23,6 +23,7 @@  #include <linux/delay.h>  #include <linux/pci.h>  #include <linux/interrupt.h> +#include <linux/module.h>  #include <linux/aer.h>  #include <linux/gfp.h>  #include <linux/kernel.h> @@ -52,9 +53,12 @@  #define LPFC_MIN_DEVLOSS_TMO 1  #define LPFC_MAX_DEVLOSS_TMO 255 -#define LPFC_MAX_LINK_SPEED 8 -#define LPFC_LINK_SPEED_BITMAP 0x00000117 -#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8" +/* + * Write key size should be multiple of 4. If write key is changed + * make sure that library write key is also changed. + */ +#define LPFC_REG_WRITE_KEY_SIZE	4 +#define LPFC_REG_WRITE_KEY	"EMLX"  /**   * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules @@ -347,10 +351,23 @@ lpfc_fwrev_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; -	char fwrev[32]; +	uint32_t if_type; +	uint8_t sli_family; +	char fwrev[FW_REV_STR_SIZE]; +	int len;  	lpfc_decode_firmware_rev(phba, fwrev, 1); -	return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev); +	if_type = phba->sli4_hba.pc_sli4_params.if_type; +	sli_family = phba->sli4_hba.pc_sli4_params.sli_family; + +	if (phba->sli_rev < LPFC_SLI_REV4) +		len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", +			       fwrev, phba->sli_rev); +	else +		len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n", +			       fwrev, phba->sli_rev, if_type, sli_family); + +	return len;  }  /** @@ -463,7 +480,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,  		if (phba->sli.sli_flag & LPFC_MENLO_MAINT)  			len += snprintf(buf + len, PAGE_SIZE-len,  					"   Menlo Maint Mode\n"); -		else if (phba->fc_topology == TOPOLOGY_LOOP) { +		else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {  			if (vport->fc_flag & FC_PUBLIC_LOOP)  				len += snprintf(buf + len, PAGE_SIZE-len,  						"   Public Loop\n"); @@ -484,6 +501,55 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,  }  /** + * lpfc_sli4_protocol_show - Return the fip mode of the HBA + * @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_sli4_protocol_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; + +	if (phba->sli_rev < LPFC_SLI_REV4) +		return snprintf(buf, PAGE_SIZE, "fc\n"); + +	if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) { +		if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE) +			return snprintf(buf, PAGE_SIZE, "fcoe\n"); +		if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) +			return snprintf(buf, PAGE_SIZE, "fc\n"); +	} +	return snprintf(buf, PAGE_SIZE, "unknown\n"); +} + +/** + * 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. @@ -627,10 +693,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)  	int status = 0;  	int cnt = 0;  	int i; +	int rc;  	init_completion(&online_compl); -	lpfc_workq_post_event(phba, &status, &online_compl, +	rc = lpfc_workq_post_event(phba, &status, &online_compl,  			      LPFC_EVT_OFFLINE_PREP); +	if (rc == 0) +		return -ENOMEM; +  	wait_for_completion(&online_compl);  	if (status != 0) @@ -643,7 +713,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)  	 */  	for (i = 0; i < psli->num_rings; i++) {  		pring = &psli->ring[i]; -		while (pring->txcmplq_cnt) { +		while (!list_empty(&pring->txcmplq)) {  			msleep(10);  			if (cnt++ > 500) {  /* 5 secs */  				lpfc_printf_log(phba, @@ -656,7 +726,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)  	}  	init_completion(&online_compl); -	lpfc_workq_post_event(phba, &status, &online_compl, type); +	rc = lpfc_workq_post_event(phba, &status, &online_compl, type); +	if (rc == 0) +		return -ENOMEM; +  	wait_for_completion(&online_compl);  	if (status != 0) @@ -675,29 +748,36 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)   *   * Notes:   * Assumes any error from lpfc_do_offline() will be negative. + * Do not make this function static.   *   * Returns:   * lpfc_do_offline() return code if not zero   * -EIO reset not configured or error posting the event   * zero for success   **/ -static int +int  lpfc_selective_reset(struct lpfc_hba *phba)  {  	struct completion online_compl;  	int status = 0; +	int rc;  	if (!phba->cfg_enable_hba_reset) -		return -EIO; +		return -EACCES; -	status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); +	if (!(phba->pport->fc_flag & FC_OFFLINE_MODE)) { +		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); -	if (status != 0) -		return status; +		if (status != 0) +			return status; +	}  	init_completion(&online_compl); -	lpfc_workq_post_event(phba, &status, &online_compl, +	rc = lpfc_workq_post_event(phba, &status, &online_compl,  			      LPFC_EVT_ONLINE); +	if (rc == 0) +		return -ENOMEM; +  	wait_for_completion(&online_compl);  	if (status != 0) @@ -734,11 +814,13 @@ lpfc_issue_reset(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 status = -EINVAL; +	if (!phba->cfg_enable_hba_reset) +		return -EACCES; +  	if (strncmp(buf, "selective", sizeof("selective") - 1) == 0) -		status = lpfc_selective_reset(phba); +		status = phba->lpfc_selective_reset(phba);  	if (status == 0)  		return strlen(buf); @@ -747,6 +829,172 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,  }  /** + * lpfc_sli4_pdev_status_reg_wait - Wait for pdev status register for readyness + * @phba: lpfc_hba pointer. + * + * Description: + * SLI4 interface type-2 device to wait on the sliport status register for + * the readyness after performing a firmware reset. + * + * Returns: + * zero for success, -EPERM when port does not have privilege to perform the + * reset, -EIO when port timeout from recovering from the reset. + * + * Note: + * As the caller will interpret the return code by value, be careful in making + * change or addition to return codes. + **/ +int +lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) +{ +	struct lpfc_register portstat_reg = {0}; +	int i; + +	msleep(100); +	lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, +		   &portstat_reg.word0); + +	/* verify if privileged for the request operation */ +	if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) && +	    !bf_get(lpfc_sliport_status_err, &portstat_reg)) +		return -EPERM; + +	/* wait for the SLI port firmware ready after firmware reset */ +	for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) { +		msleep(10); +		lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, +			   &portstat_reg.word0); +		if (!bf_get(lpfc_sliport_status_err, &portstat_reg)) +			continue; +		if (!bf_get(lpfc_sliport_status_rn, &portstat_reg)) +			continue; +		if (!bf_get(lpfc_sliport_status_rdy, &portstat_reg)) +			continue; +		break; +	} + +	if (i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT) +		return 0; +	else +		return -EIO; +} + +/** + * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc + * @phba: lpfc_hba pointer. + * + * Description: + * Request SLI4 interface type-2 device to perform a physical register set + * access. + * + * Returns: + * zero for success + **/ +static ssize_t +lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) +{ +	struct completion online_compl; +	struct pci_dev *pdev = phba->pcidev; +	uint32_t before_fc_flag; +	uint32_t sriov_nr_virtfn; +	uint32_t reg_val; +	int status = 0, rc = 0; +	int job_posted = 1, sriov_err; + +	if (!phba->cfg_enable_hba_reset) +		return -EACCES; + +	if ((phba->sli_rev < LPFC_SLI_REV4) || +	    (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != +	     LPFC_SLI_INTF_IF_TYPE_2)) +		return -EPERM; + +	/* Keep state if we need to restore back */ +	before_fc_flag = phba->pport->fc_flag; +	sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn; + +	/* Disable SR-IOV virtual functions if enabled */ +	if (phba->cfg_sriov_nr_virtfn) { +		pci_disable_sriov(pdev); +		phba->cfg_sriov_nr_virtfn = 0; +	} + +	if (opcode == LPFC_FW_DUMP) +		phba->hba_flag |= HBA_FW_DUMP_OP; + +	status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); + +	if (status != 0) { +		phba->hba_flag &= ~HBA_FW_DUMP_OP; +		return status; +	} + +	/* wait for the device to be quiesced before firmware reset */ +	msleep(100); + +	reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + +			LPFC_CTL_PDEV_CTL_OFFSET); + +	if (opcode == LPFC_FW_DUMP) +		reg_val |= LPFC_FW_DUMP_REQUEST; +	else if (opcode == LPFC_FW_RESET) +		reg_val |= LPFC_CTL_PDEV_CTL_FRST; +	else if (opcode == LPFC_DV_RESET) +		reg_val |= LPFC_CTL_PDEV_CTL_DRST; + +	writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + +	       LPFC_CTL_PDEV_CTL_OFFSET); +	/* flush */ +	readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET); + +	/* delay driver action following IF_TYPE_2 reset */ +	rc = lpfc_sli4_pdev_status_reg_wait(phba); + +	if (rc == -EPERM) { +		/* no privilege for reset */ +		lpfc_printf_log(phba, KERN_ERR, LOG_SLI, +				"3150 No privilege to perform the requested " +				"access: x%x\n", reg_val); +	} else if (rc == -EIO) { +		/* reset failed, there is nothing more we can do */ +		lpfc_printf_log(phba, KERN_ERR, LOG_SLI, +				"3153 Fail to perform the requested " +				"access: x%x\n", reg_val); +		return rc; +	} + +	/* keep the original port state */ +	if (before_fc_flag & FC_OFFLINE_MODE) +		goto out; + +	init_completion(&online_compl); +	job_posted = lpfc_workq_post_event(phba, &status, &online_compl, +					   LPFC_EVT_ONLINE); +	if (!job_posted) +		goto out; + +	wait_for_completion(&online_compl); + +out: +	/* in any case, restore the virtual functions enabled as before */ +	if (sriov_nr_virtfn) { +		sriov_err = +			lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); +		if (!sriov_err) +			phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn; +	} + +	/* return proper error code */ +	if (!rc) { +		if (!job_posted) +			rc = -ENOMEM; +		else if (status) +			rc = -EIO; +	} +	return rc; +} + +/**   * lpfc_nport_evt_cnt_show - Return the number of nport events   * @dev: class device that is converted into a Scsi_host.   * @attr: device attribute, not used. @@ -815,35 +1063,62 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,  	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;  	struct lpfc_hba   *phba = vport->phba;  	struct completion online_compl; -	int status=0; +	char *board_mode_str = NULL; +	int status = 0; +	int rc; + +	if (!phba->cfg_enable_hba_reset) { +		status = -EACCES; +		goto board_mode_out; +	} + +	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +			 "3050 lpfc_board_mode set to %s\n", buf); -	if (!phba->cfg_enable_hba_reset) -		return -EACCES;  	init_completion(&online_compl);  	if(strncmp(buf, "online", sizeof("online") - 1) == 0) { -		lpfc_workq_post_event(phba, &status, &online_compl, +		rc = lpfc_workq_post_event(phba, &status, &online_compl,  				      LPFC_EVT_ONLINE); +		if (rc == 0) { +			status = -ENOMEM; +			goto board_mode_out; +		}  		wait_for_completion(&online_compl);  	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)  		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);  	else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)  		if (phba->sli_rev == LPFC_SLI_REV4) -			return -EINVAL; +			status = -EINVAL;  		else  			status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);  	else if (strncmp(buf, "error", sizeof("error") - 1) == 0)  		if (phba->sli_rev == LPFC_SLI_REV4) -			return -EINVAL; +			status = -EINVAL;  		else  			status = lpfc_do_offline(phba, LPFC_EVT_KILL); +	else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) +		status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP); +	else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0) +		status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET); +	else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) +		status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET);  	else -		return -EINVAL; +		status = -EINVAL; +board_mode_out:  	if (!status)  		return strlen(buf); -	else -		return -EIO; +	else { +		board_mode_str = strchr(buf, '\n'); +		if (board_mode_str) +			*board_mode_str = '\0'; +		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +				 "3097 Failed \"%s\", status(%d), " +				 "fc_flag(x%x)\n", +				 buf, status, phba->pport->fc_flag); +		return status; +	}  }  /** @@ -1206,6 +1481,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,  	if (phba->sli_rev == LPFC_SLI_REV4)  		val = 0; +	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +		"3051 lpfc_poll changed from %d to %d\n", +		phba->cfg_poll, val); +  	spin_lock_irq(&phba->hbalock);  	old_val = phba->cfg_poll; @@ -1213,7 +1492,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,  	if (val & ENABLE_FCP_RING_POLLING) {  		if ((val & DISABLE_FCP_RING_INT) &&  		    !(old_val & DISABLE_FCP_RING_INT)) { -			creg_val = readl(phba->HCregaddr); +			if (lpfc_readl(phba->HCregaddr, &creg_val)) { +				spin_unlock_irq(&phba->hbalock); +				return -EINVAL; +			}  			creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);  			writel(creg_val, phba->HCregaddr);  			readl(phba->HCregaddr); /* flush */ @@ -1231,7 +1513,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,  		spin_unlock_irq(&phba->hbalock);  		del_timer(&phba->fcp_poll_timer);  		spin_lock_irq(&phba->hbalock); -		creg_val = readl(phba->HCregaddr); +		if (lpfc_readl(phba->HCregaddr, &creg_val)) { +			spin_unlock_irq(&phba->hbalock); +			return -EINVAL; +		}  		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);  		writel(creg_val, phba->HCregaddr);  		readl(phba->HCregaddr); /* flush */ @@ -1283,6 +1568,54 @@ lpfc_fips_rev_show(struct device *dev,  struct device_attribute *attr,  }  /** + * lpfc_dss_show - Return the current state of dss and the configured state + * @dev: class converted to a Scsi_host structure. + * @attr: device attribute, not used. + * @buf: on return contains the formatted text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_dss_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, "%s - %sOperational\n", +			(phba->cfg_enable_dss) ? "Enabled" : "Disabled", +			(phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ? +				"" : "Not "); +} + +/** + * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions + * @dev: class converted to a Scsi_host structure. + * @attr: device attribute, not used. + * @buf: on return contains the formatted support level. + * + * Description: + * Returns the maximum number of virtual functions a physical function can + * support, 0 will be returned if called on virtual function. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_sriov_hw_max_virtfn_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; +	uint16_t max_nr_virtfn; + +	max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba); +	return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); +} + +/**   * lpfc_param_show - Return a cfg attribute value in decimal   *   * Description: @@ -1339,7 +1672,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \  }  /** - * lpfc_param_init - Intializes a cfg attribute + * lpfc_param_init - Initializes a cfg attribute   *   * Description:   * Macro that given an attr e.g. hba_queue_depth expands @@ -1397,6 +1730,9 @@ static int \  lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \  { \  	if (val >= minval && val <= maxval) {\ +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ +			"3052 lpfc_" #attr " changed from %d to %d\n", \ +			phba->cfg_##attr, val); \  		phba->cfg_##attr = val;\  		return 0;\  	}\ @@ -1554,6 +1890,11 @@ static int \  lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \  { \  	if (val >= minval && val <= maxval) {\ +		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ +			"3053 lpfc_" #attr \ +			" changed from %d (x%x) to %d (x%x)\n", \ +			vport->cfg_##attr, vport->cfg_##attr, \ +			val, val); \  		vport->cfg_##attr = val;\  		return 0;\  	}\ @@ -1601,13 +1942,13 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \  #define LPFC_ATTR(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_param_init(name, defval, minval, maxval)  #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_param_show(name)\  lpfc_param_init(name, defval, minval, maxval)\ @@ -1615,7 +1956,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)  #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_param_show(name)\  lpfc_param_init(name, defval, minval, maxval)\ @@ -1626,7 +1967,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\  #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_param_hex_show(name)\  lpfc_param_init(name, defval, minval, maxval)\ @@ -1634,7 +1975,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)  #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_param_hex_show(name)\  lpfc_param_init(name, defval, minval, maxval)\ @@ -1645,13 +1986,13 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\  #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_vport_param_init(name, defval, minval, maxval)  #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_vport_param_show(name)\  lpfc_vport_param_init(name, defval, minval, maxval)\ @@ -1659,7 +2000,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)  #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_vport_param_show(name)\  lpfc_vport_param_init(name, defval, minval, maxval)\ @@ -1670,7 +2011,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\  #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_vport_param_hex_show(name)\  lpfc_vport_param_init(name, defval, minval, maxval)\ @@ -1678,7 +2019,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)  #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \  static uint lpfc_##name = defval;\ -module_param(lpfc_##name, uint, 0);\ +module_param(lpfc_##name, uint, S_IRUGO);\  MODULE_PARM_DESC(lpfc_##name, desc);\  lpfc_vport_param_hex_show(name)\  lpfc_vport_param_init(name, defval, minval, maxval)\ @@ -1722,10 +2063,57 @@ static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);  static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);  static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL);  static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); - +static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); +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. @@ -1814,9 +2202,10 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,  	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)  		return -EACCES; @@ -1830,29 +2219,19 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,  	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) @@ -1867,7 +2246,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,  				"0463 lpfc_soft_wwpn attribute set failed to "  				"reinit adapter - %d\n", stat1);  	init_completion(&online_compl); -	lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE); +	rc = lpfc_workq_post_event(phba, &stat2, &online_compl, +				   LPFC_EVT_ONLINE); +	if (rc == 0) +		return -ENOMEM; +  	wait_for_completion(&online_compl);  	if (stat2)  		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -1875,7 +2258,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,  				"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);  /** @@ -1912,39 +2295,25 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,  {  	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, @@ -1953,12 +2322,441 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,  	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_fof) +		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_fof) +		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_fof) +		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_fof) +		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_fof) +		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_fof) +		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, 0); +module_param(lpfc_poll, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"  		 " 0 - none,"  		 " 1 - poll with interrupts enabled" @@ -1968,19 +2766,35 @@ static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,  		   lpfc_poll_show, lpfc_poll_store);  int  lpfc_sli_mode = 0; -module_param(lpfc_sli_mode, int, 0); +module_param(lpfc_sli_mode, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"  		 " 0 - auto (SLI-3 if supported),"  		 " 2 - select SLI-2 even on SLI-3 capable HBAs,"  		 " 3 - select SLI-3");  int lpfc_enable_npiv = 1; -module_param(lpfc_enable_npiv, int, 0); +module_param(lpfc_enable_npiv, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");  lpfc_param_show(enable_npiv);  lpfc_param_init(enable_npiv, 1, 0, 1);  static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); +LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2, +	"FCF Fast failover=1 Priority failover=2"); + +int lpfc_enable_rrq = 2; +module_param(lpfc_enable_rrq, int, S_IRUGO); +MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); +lpfc_param_show(enable_rrq); +/* +# lpfc_enable_rrq: Track XRI/OXID reuse after IO failures +#	0x0 = disabled, XRI/OXID use not tracked. +#	0x1 = XRI/OXID reuse is timed with ratov, RRQ sent. +#	0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent. +*/ +lpfc_param_init(enable_rrq, 2, 0, 2); +static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL); +  /*  # lpfc_suppress_link_up:  Bring link up at initialization  #            0x0  = bring link up (issue MBX_INIT_LINK) @@ -2037,7 +2851,7 @@ static DEVICE_ATTR(txcmplq_hw, S_IRUGO,  			 lpfc_txcmplq_hw_show, NULL);  int lpfc_iocb_cnt = 2; -module_param(lpfc_iocb_cnt, int, 1); +module_param(lpfc_iocb_cnt, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_iocb_cnt,  	"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");  lpfc_param_show(iocb_cnt); @@ -2189,7 +3003,7 @@ static DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,  # disappear until the timer expires. Value range is [0,255]. Default  # value is 30.  */ -module_param(lpfc_devloss_tmo, int, 0); +module_param(lpfc_devloss_tmo, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_devloss_tmo,  		 "Seconds driver will hold I/O waiting "  		 "for a device to come back"); @@ -2247,14 +3061,17 @@ LPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffffffff,  # lpfc_enable_da_id: This turns on the DA_ID CT command that deregisters  # objects that have been registered with the nameserver after login.  */ -LPFC_VPORT_ATTR_R(enable_da_id, 0, 0, 1, +LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1,  		  "Deregister nameserver objects before LOGO");  /*  # lun_queue_depth:  This parameter is used to limit the number of outstanding -# commands per FCP LUN. Value range is [1,128]. Default value is 30. +# commands per FCP LUN. Value range is [1,512]. Default value is 30. +# If this parameter value is greater than 1/8th the maximum number of exchanges +# supported by the HBA port, then the lun queue depth will be reduced to +# 1/8th the maximum number of exchanges.  */ -LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 128, +LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512,  		  "Max number of FCP commands we can queue to a specific LUN");  /* @@ -2262,7 +3079,7 @@ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 128,  # commands per target port. Value range is [10,65535]. Default value is 65535.  */  LPFC_VPORT_ATTR_R(tgt_queue_depth, 65535, 10, 65535, -	"Max number of FCP commands we can queue to a specific target port"); +		  "Max number of FCP commands we can queue to a specific target port");  /*  # hba_queue_depth:  This parameter is used to limit the number of outstanding @@ -2299,7 +3116,7 @@ LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1,  # Default value of this parameter is 1.  */  static int lpfc_restrict_login = 1; -module_param(lpfc_restrict_login, int, 0); +module_param(lpfc_restrict_login, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_restrict_login,  		 "Restrict virtual ports login to remote initiators.");  lpfc_vport_param_show(restrict_login); @@ -2453,9 +3270,22 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,  	if (val >= 0 && val <= 6) {  		prev_val = phba->cfg_topology;  		phba->cfg_topology = val; +		if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G && +			val == 4) { +			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +				"3113 Loop mode not supported at speed %d\n", +				phba->cfg_link_speed); +			phba->cfg_topology = prev_val; +			return -EINVAL; +		}  		if (nolip)  			return strlen(buf); +		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +			"3054 lpfc_topology changed from %d to %d\n", +			prev_val, val); +		if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4) +			phba->fc_topology_changed = 1;  		err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));  		if (err) {  			phba->cfg_topology = prev_val; @@ -2470,7 +3300,7 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,  	return -EINVAL;  }  static int lpfc_topology = 0; -module_param(lpfc_topology, int, 0); +module_param(lpfc_topology, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");  lpfc_param_show(topology)  lpfc_param_init(topology, 0, 0, 6) @@ -2837,14 +3667,8 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {  /*  # lpfc_link_speed: Link speed selection for initializing the Fibre Channel  # connection. -#       0  = auto select (default) -#       1  = 1 Gigabaud -#       2  = 2 Gigabaud -#       4  = 4 Gigabaud -#       8  = 8 Gigabaud -# Value range is [0,8]. Default value is 0. +# Value range is [0,16]. Default value is 0.  */ -  /**   * lpfc_link_speed_set - Set the adapters link speed   * @phba: lpfc_hba pointer. @@ -2869,7 +3693,7 @@ lpfc_link_speed_store(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 val = 0; +	int val = LPFC_USER_LINK_SPEED_AUTO;  	int nolip = 0;  	const char *val_buf = buf;  	int err; @@ -2885,15 +3709,32 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,  	if (sscanf(val_buf, "%i", &val) != 1)  		return -EINVAL; -	if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || -		((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || -		((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || -		((val == LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || -		((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb))) +	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, +		"3055 lpfc_link_speed changed from %d to %d %s\n", +		phba->cfg_link_speed, val, nolip ? "(nolip)" : "(lip)"); + +	if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || +	    ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || +	    ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || +	    ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || +	    ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) || +	    ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"2879 lpfc_link_speed attribute cannot be set " +				"to %d. Speed is not supported by this port.\n", +				val);  		return -EINVAL; - -	if ((val >= 0 && val <= 8) -		&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) { +	} +	if (val == LPFC_USER_LINK_SPEED_16G && +		 phba->fc_topology == LPFC_TOPOLOGY_LOOP) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"3112 lpfc_link_speed attribute cannot be set " +				"to %d. Speed is not supported in loop mode.\n", +				val); +		return -EINVAL; +	} +	if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && +	    (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {  		prev_val = phba->cfg_link_speed;  		phba->cfg_link_speed = val;  		if (nolip) @@ -2906,16 +3747,14 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,  		} else  			return strlen(buf);  	} -  	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, -		"%d:0469 lpfc_link_speed attribute cannot be set to %d, " -		"allowed range is [0, 8]\n", -		phba->brd_no, val); +		"0469 lpfc_link_speed attribute cannot be set to %d, " +		"allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val);  	return -EINVAL;  }  static int lpfc_link_speed = 0; -module_param(lpfc_link_speed, int, 0); +module_param(lpfc_link_speed, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");  lpfc_param_show(link_speed) @@ -2938,8 +3777,15 @@ lpfc_param_show(link_speed)  static int  lpfc_link_speed_init(struct lpfc_hba *phba, int val)  { -	if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) -		&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) { +	if (val == LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +			"3111 lpfc_link_speed of %d cannot " +			"support loop mode, setting topology to default.\n", +			 val); +		phba->cfg_topology = 0; +	} +	if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && +	    (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {  		phba->cfg_link_speed = val;  		return 0;  	} @@ -2947,12 +3793,12 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)  			"0405 lpfc_link_speed attribute cannot "  			"be set to %d, allowed values are "  			"["LPFC_LINK_SPEED_STRING"]\n", val); -	phba->cfg_link_speed = 0; +	phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;  	return -EINVAL;  }  static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, -		lpfc_link_speed_show, lpfc_link_speed_store); +		   lpfc_link_speed_show, lpfc_link_speed_store);  /*  # lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER) @@ -2966,7 +3812,7 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,   *   * @dev: class device that is converted into a Scsi_host.   * @attr: device attribute, not used. - * @buf: containing the string "selective". + * @buf: containing enable or disable aer flag.   * @count: unused variable.   *   * Description: @@ -3043,14 +3889,14 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,  }  static int lpfc_aer_support = 1; -module_param(lpfc_aer_support, int, 1); +module_param(lpfc_aer_support, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");  lpfc_param_show(aer_support)  /**   * lpfc_aer_support_init - Set the initial adapters aer support flag   * @phba: lpfc_hba pointer. - * @val: link speed value. + * @val: enable aer or disable aer flag.   *   * Description:   * If val is in a valid range [0,1], then set the adapter's initial @@ -3089,7 +3935,7 @@ static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR,   * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device   * @dev: class device that is converted into a Scsi_host.   * @attr: device attribute, not used. - * @buf: containing the string "selective". + * @buf: containing flag 1 for aer cleanup state.   * @count: unused variable.   *   * Description: @@ -3132,6 +3978,456 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr,  static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL,  		   lpfc_aer_cleanup_state); +/** + * lpfc_sriov_nr_virtfn_store - Enable the adapter for sr-iov virtual functions + * + * @dev: class device that is converted into a Scsi_host. + * @attr: device attribute, not used. + * @buf: containing the string the number of vfs to be enabled. + * @count: unused variable. + * + * Description: + * When this api is called either through user sysfs, the driver shall + * try to enable or disable SR-IOV virtual functions according to the + * following: + * + * If zero virtual function has been enabled to the physical function, + * the driver shall invoke the pci enable virtual function api trying + * to enable the virtual functions. If the nr_vfn provided is greater + * than the maximum supported, the maximum virtual function number will + * be used for invoking the api; otherwise, the nr_vfn provided shall + * be used for invoking the api. If the api call returned success, the + * actual number of virtual functions enabled will be set to the driver + * cfg_sriov_nr_virtfn; otherwise, -EINVAL shall be returned and driver + * cfg_sriov_nr_virtfn remains zero. + * + * If none-zero virtual functions have already been enabled to the + * physical function, as reflected by the driver's cfg_sriov_nr_virtfn, + * -EINVAL will be returned and the driver does nothing; + * + * If the nr_vfn provided is zero and none-zero virtual functions have + * been enabled, as indicated by the driver's cfg_sriov_nr_virtfn, the + * disabling virtual function api shall be invoded to disable all the + * virtual functions and driver's cfg_sriov_nr_virtfn shall be set to + * zero. Otherwise, if zero virtual function has been enabled, do + * nothing. + * + * Returns: + * length of the buf on success if val is in range the intended mode + * is supported. + * -EINVAL if val out of range or intended mode is not supported. + **/ +static ssize_t +lpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr, +			 const char *buf, size_t count) +{ +	struct Scsi_Host *shost = class_to_shost(dev); +	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; +	struct lpfc_hba *phba = vport->phba; +	struct pci_dev *pdev = phba->pcidev; +	int val = 0, rc = -EINVAL; + +	/* Sanity check on user data */ +	if (!isdigit(buf[0])) +		return -EINVAL; +	if (sscanf(buf, "%i", &val) != 1) +		return -EINVAL; +	if (val < 0) +		return -EINVAL; + +	/* Request disabling virtual functions */ +	if (val == 0) { +		if (phba->cfg_sriov_nr_virtfn > 0) { +			pci_disable_sriov(pdev); +			phba->cfg_sriov_nr_virtfn = 0; +		} +		return strlen(buf); +	} + +	/* Request enabling virtual functions */ +	if (phba->cfg_sriov_nr_virtfn > 0) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"3018 There are %d virtual functions " +				"enabled on physical function.\n", +				phba->cfg_sriov_nr_virtfn); +		return -EEXIST; +	} + +	if (val <= LPFC_MAX_VFN_PER_PFN) +		phba->cfg_sriov_nr_virtfn = val; +	else { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"3019 Enabling %d virtual functions is not " +				"allowed.\n", val); +		return -EINVAL; +	} + +	rc = lpfc_sli_probe_sriov_nr_virtfn(phba, phba->cfg_sriov_nr_virtfn); +	if (rc) { +		phba->cfg_sriov_nr_virtfn = 0; +		rc = -EPERM; +	} else +		rc = strlen(buf); + +	return rc; +} + +static int lpfc_sriov_nr_virtfn = LPFC_DEF_VFN_PER_PFN; +module_param(lpfc_sriov_nr_virtfn, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(lpfc_sriov_nr_virtfn, "Enable PCIe device SR-IOV virtual fn"); +lpfc_param_show(sriov_nr_virtfn) + +/** + * lpfc_sriov_nr_virtfn_init - Set the initial sr-iov virtual function enable + * @phba: lpfc_hba pointer. + * @val: link speed value. + * + * Description: + * If val is in a valid range [0,255], then set the adapter's initial + * cfg_sriov_nr_virtfn field. If it's greater than the maximum, the maximum + * number shall be used instead. It will be up to the driver's probe_one + * routine to determine whether the device's SR-IOV is supported or not. + * + * Returns: + * zero if val saved. + * -EINVAL val out of range + **/ +static int +lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val) +{ +	if (val >= 0 && val <= LPFC_MAX_VFN_PER_PFN) { +		phba->cfg_sriov_nr_virtfn = val; +		return 0; +	} + +	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +			"3017 Enabling %d virtual functions is not " +			"allowed.\n", val); +	return -EINVAL; +} +static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR, +		   lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); + +/** + * lpfc_request_firmware_store - Request for Linux generic firmware upgrade + * + * @dev: class device that is converted into a Scsi_host. + * @attr: device attribute, not used. + * @buf: containing the string the number of vfs to be enabled. + * @count: unused variable. + * + * Description: + * + * Returns: + * length of the buf on success if val is in range the intended mode + * is supported. + * -EINVAL if val out of range or intended mode is not supported. + **/ +static ssize_t +lpfc_request_firmware_upgrade_store(struct device *dev, +				    struct device_attribute *attr, +				    const char *buf, size_t count) +{ +	struct Scsi_Host *shost = class_to_shost(dev); +	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; +	struct lpfc_hba *phba = vport->phba; +	int val = 0, rc = -EINVAL; + +	/* Sanity check on user data */ +	if (!isdigit(buf[0])) +		return -EINVAL; +	if (sscanf(buf, "%i", &val) != 1) +		return -EINVAL; +	if (val != 1) +		return -EINVAL; + +	rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE); +	if (rc) +		rc = -EPERM; +	else +		rc = strlen(buf); +	return rc; +} + +static int lpfc_req_fw_upgrade; +module_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade"); +lpfc_param_show(request_firmware_upgrade) + +/** + * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade + * @phba: lpfc_hba pointer. + * @val: 0 or 1. + * + * Description: + * Set the initial Linux generic firmware upgrade enable or disable flag. + * + * Returns: + * zero if val saved. + * -EINVAL val out of range + **/ +static int +lpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val) +{ +	if (val >= 0 && val <= 1) { +		phba->cfg_request_firmware_upgrade = val; +		return 0; +	} +	return -EINVAL; +} +static DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR, +		   lpfc_request_firmware_upgrade_show, +		   lpfc_request_firmware_upgrade_store); + +/** + * lpfc_fcp_imax_store + * + * @dev: class device that is converted into a Scsi_host. + * @attr: device attribute, not used. + * @buf: string with the number of fast-path FCP interrupts per second. + * @count: unused variable. + * + * Description: + * If val is in a valid range [636,651042], then set the adapter's + * maximum number of fast-path FCP interrupts per second. + * + * Returns: + * length of the buf on success if val is in range the intended mode + * is supported. + * -EINVAL if val out of range or intended mode is not supported. + **/ +static ssize_t +lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr, +			 const char *buf, size_t count) +{ +	struct Scsi_Host *shost = class_to_shost(dev); +	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; +	struct lpfc_hba *phba = vport->phba; +	int val = 0, i; + +	/* fcp_imax is only valid for SLI4 */ +	if (phba->sli_rev != LPFC_SLI_REV4) +		return -EINVAL; + +	/* Sanity check on user data */ +	if (!isdigit(buf[0])) +		return -EINVAL; +	if (sscanf(buf, "%i", &val) != 1) +		return -EINVAL; + +	/* +	 * Value range for the HBA is [5000,5000000] +	 * The value for each EQ depends on how many EQs are configured. +	 */ +	if (val < LPFC_MIN_IMAX || val > LPFC_MAX_IMAX) +		return -EINVAL; + +	phba->cfg_fcp_imax = (uint32_t)val; +	for (i = 0; i < phba->cfg_fcp_io_channel; i += LPFC_MAX_EQ_DELAY) +		lpfc_modify_fcp_eq_delay(phba, i); + +	return strlen(buf); +} + +/* +# lpfc_fcp_imax: The maximum number of fast-path FCP interrupts per second +# for the HBA. +# +# Value range is [5,000 to 5,000,000]. Default value is 50,000. +*/ +static int lpfc_fcp_imax = LPFC_DEF_IMAX; +module_param(lpfc_fcp_imax, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(lpfc_fcp_imax, +	    "Set the maximum number of FCP interrupts per second per HBA"); +lpfc_param_show(fcp_imax) + +/** + * lpfc_fcp_imax_init - Set the initial sr-iov virtual function enable + * @phba: lpfc_hba pointer. + * @val: link speed value. + * + * Description: + * If val is in a valid range [636,651042], then initialize the adapter's + * maximum number of fast-path FCP interrupts per second. + * + * Returns: + * zero if val saved. + * -EINVAL val out of range + **/ +static int +lpfc_fcp_imax_init(struct lpfc_hba *phba, int val) +{ +	if (phba->sli_rev != LPFC_SLI_REV4) { +		phba->cfg_fcp_imax = 0; +		return 0; +	} + +	if (val >= LPFC_MIN_IMAX && val <= LPFC_MAX_IMAX) { +		phba->cfg_fcp_imax = val; +		return 0; +	} + +	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +			"3016 fcp_imax: %d out of range, using default\n", val); +	phba->cfg_fcp_imax = LPFC_DEF_IMAX; + +	return 0; +} + +static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, +		   lpfc_fcp_imax_show, lpfc_fcp_imax_store); + +/** + * lpfc_state_show - Display current driver CPU affinity + * @dev: class converted to a Scsi_host structure. + * @attr: device attribute, not used. + * @buf: on return contains text describing the state of the link. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_fcp_cpu_map_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; +	struct lpfc_vector_map_info *cpup; +	int  len = 0; + +	if ((phba->sli_rev != LPFC_SLI_REV4) || +	    (phba->intr_type != MSIX)) +		return len; + +	switch (phba->cfg_fcp_cpu_map) { +	case 0: +		len += snprintf(buf + len, PAGE_SIZE-len, +				"fcp_cpu_map: No mapping (%d)\n", +				phba->cfg_fcp_cpu_map); +		return len; +	case 1: +		len += snprintf(buf + len, PAGE_SIZE-len, +				"fcp_cpu_map: HBA centric mapping (%d): " +				"%d online CPUs\n", +				phba->cfg_fcp_cpu_map, +				phba->sli4_hba.num_online_cpu); +		break; +	case 2: +		len += snprintf(buf + len, PAGE_SIZE-len, +				"fcp_cpu_map: Driver centric mapping (%d): " +				"%d online CPUs\n", +				phba->cfg_fcp_cpu_map, +				phba->sli4_hba.num_online_cpu); +		break; +	} + +	while (phba->sli4_hba.curr_disp_cpu < phba->sli4_hba.num_present_cpu) { +		cpup = &phba->sli4_hba.cpu_map[phba->sli4_hba.curr_disp_cpu]; + +		/* margin should fit in this and the truncated message */ +		if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) +			len += snprintf(buf + len, PAGE_SIZE-len, +					"CPU %02d io_chan %02d " +					"physid %d coreid %d\n", +					phba->sli4_hba.curr_disp_cpu, +					cpup->channel_id, cpup->phys_id, +					cpup->core_id); +		else +			len += snprintf(buf + len, PAGE_SIZE-len, +					"CPU %02d io_chan %02d " +					"physid %d coreid %d IRQ %d\n", +					phba->sli4_hba.curr_disp_cpu, +					cpup->channel_id, cpup->phys_id, +					cpup->core_id, cpup->irq); + +		phba->sli4_hba.curr_disp_cpu++; + +		/* display max number of CPUs keeping some margin */ +		if (phba->sli4_hba.curr_disp_cpu < +				phba->sli4_hba.num_present_cpu && +				(len >= (PAGE_SIZE - 64))) { +			len += snprintf(buf + len, PAGE_SIZE-len, "more...\n"); +			break; +		} +	} + +	if (phba->sli4_hba.curr_disp_cpu == phba->sli4_hba.num_present_cpu) +		phba->sli4_hba.curr_disp_cpu = 0; + +	return len; +} + +/** + * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors + * @dev: class device that is converted into a Scsi_host. + * @attr: device attribute, not used. + * @buf: one or more lpfc_polling_flags values. + * @count: not used. + * + * Returns: + * -EINVAL  - Not implemented yet. + **/ +static ssize_t +lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr, +		       const char *buf, size_t count) +{ +	int status = -EINVAL; +	return status; +} + +/* +# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors +# for the HBA. +# +# Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2). +#	0 - Do not affinitze IRQ vectors +#	1 - Affintize HBA vectors with respect to each HBA +#	    (start with CPU0 for each HBA) +#	2 - Affintize HBA vectors with respect to the entire driver +#	    (round robin thru all CPUs across all HBAs) +*/ +static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP; +module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(lpfc_fcp_cpu_map, +		 "Defines how to map CPUs to IRQ vectors per HBA"); + +/** + * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable + * @phba: lpfc_hba pointer. + * @val: link speed value. + * + * Description: + * If val is in a valid range [0-2], then affinitze the adapter's + * MSIX vectors. + * + * Returns: + * zero if val saved. + * -EINVAL val out of range + **/ +static int +lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val) +{ +	if (phba->sli_rev != LPFC_SLI_REV4) { +		phba->cfg_fcp_cpu_map = 0; +		return 0; +	} + +	if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) { +		phba->cfg_fcp_cpu_map = val; +		return 0; +	} + +	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +			"3326 fcp_cpu_map: %d out of range, using default\n", +			val); +	phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP; + +	return 0; +} + +static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR, +		   lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store); +  /*  # lpfc_fcp_class:  Determines FC class to use for the FCP protocol.  # Value range is [2,3]. Default value is 3. @@ -3147,6 +4443,14 @@ LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,  		   "Use ADISC on rediscovery to authenticate FCP devices");  /* +# lpfc_first_burst_size: First burst size to use on the NPorts +# that support first burst. +# Value range is [0,65536]. Default value is 0. +*/ +LPFC_VPORT_ATTR_RW(first_burst_size, 0, 0, 65536, +		   "First burst size for Targets that support first burst"); + +/*  # lpfc_max_scsicmpl_time: Use scsi command completion time to control I/O queue  # depth. Default value is 0. When the value of this parameter is zero the  # SCSI command completion time is not used for controlling I/O queue depth. When @@ -3155,7 +4459,7 @@ LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,  # The value is set in milliseconds.  */  static int lpfc_max_scsicmpl_time; -module_param(lpfc_max_scsicmpl_time, int, 0); +module_param(lpfc_max_scsicmpl_time, int, S_IRUGO);  MODULE_PARM_DESC(lpfc_max_scsicmpl_time,  	"Use command completion time to control queue depth");  lpfc_vport_param_show(max_scsicmpl_time); @@ -3195,6 +4499,29 @@ static DEVICE_ATTR(lpfc_max_scsicmpl_time, S_IRUGO | S_IWUSR,  LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");  /* +# lpfc_fcp_io_sched: Determine scheduling algrithmn for issuing FCP cmds +# range is [0,1]. Default value is 0. +# For [0], FCP commands are issued to Work Queues ina round robin fashion. +# For [1], FCP commands are issued to a Work Queue associated with the +#          current CPU. +# It would be set to 1 by the driver if it's able to set up cpu affinity +# for FCP I/Os through Work Queue associated with the current CPU. Otherwise, +# roundrobin scheduling of FCP I/Os through WQs will be used. +*/ +LPFC_ATTR_RW(fcp_io_sched, 0, 0, 1, "Determine scheduling algorithm for " +		"issuing commands [0] - Round Robin, [1] - Current CPU"); + +/* +# lpfc_fcp2_no_tgt_reset: Determine bus reset behavior +# range is [0,1]. Default value is 0. +# For [0], bus reset issues target reset to ALL devices +# For [1], bus reset issues target reset to non-FCP2 devices +*/ +LPFC_ATTR_RW(fcp2_no_tgt_reset, 0, 0, 1, "Determine bus reset behavior for " +	     "FCP2 devices [0] - issue tgt reset, [1] - no tgt reset"); + + +/*  # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing  # cr_delay (msec) or cr_count outstanding commands. cr_delay can take  # value [0,63]. cr_count can take value [1,255]. Default value of cr_delay @@ -3248,11 +4575,28 @@ LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "  		 "during discovery");  /* -# lpfc_max_luns: maximum allowed LUN. +# lpfc_max_luns: maximum allowed LUN ID. This is the highest LUN ID that +#    will be scanned by the SCSI midlayer when sequential scanning is +#    used; and is also the highest LUN ID allowed when the SCSI midlayer +#    parses REPORT_LUN responses. The lpfc driver has no LUN count or +#    LUN ID limit, but the SCSI midlayer requires this field for the uses +#    above. The lpfc driver limits the default value to 255 for two reasons. +#    As it bounds the sequential scan loop, scanning for thousands of luns +#    on a target can take minutes of wall clock time.  Additionally, +#    there are FC targets, such as JBODs, that only recognize 8-bits of +#    LUN ID. When they receive a value greater than 8 bits, they chop off +#    the high order bits. In other words, they see LUN IDs 0, 256, 512, +#    and so on all as LUN ID 0. This causes the linux kernel, which sees +#    valid responses at each of the LUN IDs, to believe there are multiple +#    devices present, when in fact, there is only 1. +#    A customer that is aware of their target behaviors, and the results as +#    indicated above, is welcome to increase the lpfc_max_luns value. +#    As mentioned, this value is not used by the lpfc driver, only the +#    SCSI midlayer.  # Value range is [0,65535]. Default value is 255.  # NOTE: The SCSI layer might probe all allowed LUN on some old targets.  */ -LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN"); +LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");  /*  # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring. @@ -3262,6 +4606,12 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,  	     "Milliseconds driver will wait between polling FCP ring");  /* +# lpfc_task_mgmt_tmo: Maximum time to wait for task management commands +# to complete in seconds. Value range is [5,180], default value is 60. +*/ +LPFC_ATTR_RW(task_mgmt_tmo, 60, 5, 180, +	     "Maximum time to wait for task management commands to complete"); +/*  # lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that  #		support this feature  #       0  = MSI disabled @@ -3273,28 +4623,13 @@ LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "  	    "MSI-X (2), if possible");  /* -# lpfc_fcp_imax: Set the maximum number of fast-path FCP interrupts per second +# lpfc_fcp_io_channel: Set the number of FCP EQ/CQ/WQ IO channels  # -# Value range is [636,651042]. Default value is 10000. +# Value range is [1,7]. Default value is 4.  */ -LPFC_ATTR_R(fcp_imax, LPFC_FP_DEF_IMAX, LPFC_MIM_IMAX, LPFC_DMULT_CONST, -	    "Set the maximum number of fast-path FCP interrupts per second"); - -/* -# lpfc_fcp_wq_count: Set the number of fast-path FCP work queues -# -# Value range is [1,31]. Default value is 4. -*/ -LPFC_ATTR_R(fcp_wq_count, LPFC_FP_WQN_DEF, LPFC_FP_WQN_MIN, LPFC_FP_WQN_MAX, -	    "Set the number of fast-path FCP work queues, if possible"); - -/* -# lpfc_fcp_eq_count: Set the number of fast-path FCP event queues -# -# Value range is [1,7]. Default value is 1. -*/ -LPFC_ATTR_R(fcp_eq_count, LPFC_FP_EQN_DEF, LPFC_FP_EQN_MIN, LPFC_FP_EQN_MAX, -	    "Set the number of fast-path FCP event queues, if possible"); +LPFC_ATTR_R(fcp_io_channel, LPFC_FCP_IO_CHAN_DEF, LPFC_FCP_IO_CHAN_MIN, +	    LPFC_FCP_IO_CHAN_MAX, +	    "Set the number of FCP I/O channels");  /*  # lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware. @@ -3305,12 +4640,27 @@ LPFC_ATTR_R(fcp_eq_count, LPFC_FP_EQN_DEF, LPFC_FP_EQN_MIN, LPFC_FP_EQN_MAX,  LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver.");  /* -# lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer.. +# lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer..  #       0  = HBA Heartbeat disabled  #       1  = HBA Heartbeat enabled (default)  # Value range is [0,1]. Default value is 1.  */ -LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat."); +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_RW(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature.");  /*  # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) @@ -3321,44 +4671,88 @@ LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");  LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");  /* +# lpfc_fcp_look_ahead: Look ahead for completions in FCP start routine +#       0  = disabled (default) +#       1  = enabled +# Value range is [0,1]. Default value is 0. +# +# This feature in under investigation and may be supported in the future. +*/ +unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF; + +/*  # lpfc_prot_mask: i  #	- Bit mask of host protection capabilities used to register with the  #	  SCSI mid-layer  # 	- Only meaningful if BG is turned on (lpfc_enable_bg=1).  #	- Allows you to ultimately specify which profiles to use  #	- Default will result in registering capabilities for all profiles. +#	- SHOST_DIF_TYPE1_PROTECTION	1 +#		HBA supports T10 DIF Type 1: HBA to Target Type 1 Protection +#	- SHOST_DIX_TYPE0_PROTECTION	8 +#		HBA supports DIX Type 0: Host to HBA protection only +#	- SHOST_DIX_TYPE1_PROTECTION	16 +#		HBA supports DIX Type 1: Host to HBA  Type 1 protection  #  */ -unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; +unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION | +			      SHOST_DIX_TYPE0_PROTECTION | +			      SHOST_DIX_TYPE1_PROTECTION; -module_param(lpfc_prot_mask, uint, 0); +module_param(lpfc_prot_mask, uint, S_IRUGO);  MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");  /*  # lpfc_prot_guard: i  #	- Bit mask of protection guard types to register with the SCSI mid-layer -# 	- Guard types are currently either 1) IP checksum 2) T10-DIF CRC +#	- Guard types are currently either 1) T10-DIF CRC 2) IP checksum  #	- Allows you to ultimately specify which profiles to use  #	- Default will result in registering capabilities for all guard types  #  */  unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP; -module_param(lpfc_prot_guard, byte, 0); +module_param(lpfc_prot_guard, byte, S_IRUGO);  MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); +/* + * Delay initial NPort discovery when Clean Address bit is cleared in + * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed. + * This parameter can have value 0 or 1. + * When this parameter is set to 0, no delay is added to the initial + * discovery. + * When this parameter is set to non-zero value, initial Nport discovery is + * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC + * accept and FCID/Fabric name/Fabric portname is changed. + * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion + * when Clean Address bit is cleared in FLOGI/FDISC + * accept and FCID/Fabric name/Fabric portname is changed. + * Default value is 0. + */ +int lpfc_delay_discovery; +module_param(lpfc_delay_discovery, int, S_IRUGO); +MODULE_PARM_DESC(lpfc_delay_discovery, +	"Delay NPort discovery when Clean Address bit is cleared. " +	"Allowed values: 0,1.");  /*   * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count - * This value can be set to values between 64 and 256. The default value is + * This value can be set to values between 64 and 4096. The default value is   * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer   * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE). + * Because of the additional overhead involved in setting up T10-DIF, + * this parameter will be limited to 128 if BlockGuard is enabled under SLI4 + * and will be limited to 512 if BlockGuard is enabled under SLI3.   */  LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,  	    LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); -LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_PROT_SG_SEG_CNT, -		LPFC_DEFAULT_PROT_SG_SEG_CNT, LPFC_MAX_PROT_SG_SEG_CNT, -		"Max Protection Scatter Gather Segment Count"); +/* + * This parameter will be depricated, the driver cannot limit the + * protection data s/g list. + */ +LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, +	    LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, +	    "Max Protection Scatter Gather Segment Count");  struct device_attribute *lpfc_hba_attrs[] = {  	&dev_attr_bg_info, @@ -3389,10 +4783,13 @@ struct device_attribute *lpfc_hba_attrs[] = {  	&dev_attr_lpfc_devloss_tmo,  	&dev_attr_lpfc_fcp_class,  	&dev_attr_lpfc_use_adisc, +	&dev_attr_lpfc_first_burst_size,  	&dev_attr_lpfc_ack0,  	&dev_attr_lpfc_topology,  	&dev_attr_lpfc_scan_down,  	&dev_attr_lpfc_link_speed, +	&dev_attr_lpfc_fcp_io_sched, +	&dev_attr_lpfc_fcp2_no_tgt_reset,  	&dev_attr_lpfc_cr_delay,  	&dev_attr_lpfc_cr_count,  	&dev_attr_lpfc_multi_ring_support, @@ -3401,6 +4798,8 @@ struct device_attribute *lpfc_hba_attrs[] = {  	&dev_attr_lpfc_fdmi_on,  	&dev_attr_lpfc_max_luns,  	&dev_attr_lpfc_enable_npiv, +	&dev_attr_lpfc_fcf_failover_policy, +	&dev_attr_lpfc_enable_rrq,  	&dev_attr_nport_evt_cnt,  	&dev_attr_board_mode,  	&dev_attr_max_vpi, @@ -3413,22 +4812,32 @@ struct device_attribute *lpfc_hba_attrs[] = {  	&dev_attr_issue_reset,  	&dev_attr_lpfc_poll,  	&dev_attr_lpfc_poll_tmo, +	&dev_attr_lpfc_task_mgmt_tmo,  	&dev_attr_lpfc_use_msi,  	&dev_attr_lpfc_fcp_imax, -	&dev_attr_lpfc_fcp_wq_count, -	&dev_attr_lpfc_fcp_eq_count, +	&dev_attr_lpfc_fcp_cpu_map, +	&dev_attr_lpfc_fcp_io_channel,  	&dev_attr_lpfc_enable_bg,  	&dev_attr_lpfc_soft_wwnn,  	&dev_attr_lpfc_soft_wwpn,  	&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,  	&dev_attr_lpfc_prot_sg_seg_cnt,  	&dev_attr_lpfc_aer_support,  	&dev_attr_lpfc_aer_state_cleanup, +	&dev_attr_lpfc_sriov_nr_virtfn, +	&dev_attr_lpfc_req_fw_upgrade,  	&dev_attr_lpfc_suppress_link_up,  	&dev_attr_lpfc_iocb_cnt,  	&dev_attr_iocb_hw, @@ -3436,6 +4845,10 @@ struct device_attribute *lpfc_hba_attrs[] = {  	&dev_attr_txcmplq_hw,  	&dev_attr_lpfc_fips_level,  	&dev_attr_lpfc_fips_rev, +	&dev_attr_lpfc_dss, +	&dev_attr_lpfc_sriov_hw_max_virtfn, +	&dev_attr_protocol, +	&dev_attr_lpfc_xlane_supported,  	NULL,  }; @@ -3454,6 +4867,7 @@ struct device_attribute *lpfc_vport_attrs[] = {  	&dev_attr_lpfc_restrict_login,  	&dev_attr_lpfc_fcp_class,  	&dev_attr_lpfc_use_adisc, +	&dev_attr_lpfc_first_burst_size,  	&dev_attr_lpfc_fdmi_on,  	&dev_attr_lpfc_max_luns,  	&dev_attr_nport_evt_cnt, @@ -3503,18 +4917,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,  	if ((off + count) > FF_REG_AREA_SIZE)  		return -ERANGE; -	if (count == 0) return 0; +	if (count <= LPFC_REG_WRITE_KEY_SIZE) +		return 0;  	if (off % 4 || count % 4 || (unsigned long)buf % 4)  		return -EINVAL; -	if (!(vport->fc_flag & FC_OFFLINE_MODE)) { +	/* This is to protect HBA registers from accidental writes. */ +	if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE)) +		return -EINVAL; + +	if (!(vport->fc_flag & FC_OFFLINE_MODE))  		return -EPERM; -	}  	spin_lock_irq(&phba->hbalock); -	for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) -		writel(*((uint32_t *)(buf + buf_off)), +	for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE; +			buf_off += sizeof(uint32_t)) +		writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),  		       phba->ctrl_regs_memmap_p + off + buf_off);  	spin_unlock_irq(&phba->hbalock); @@ -3589,23 +5008,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {  };  /** - * sysfs_mbox_idle - frees the sysfs mailbox - * @phba: lpfc_hba pointer - **/ -static void -sysfs_mbox_idle(struct lpfc_hba *phba) -{ -	phba->sysfs_mbox.state = SMBOX_IDLE; -	phba->sysfs_mbox.offset = 0; - -	if (phba->sysfs_mbox.mbox) { -		mempool_free(phba->sysfs_mbox.mbox, -			     phba->mbox_mem_pool); -		phba->sysfs_mbox.mbox = NULL; -	} -} - -/**   * sysfs_mbox_write - Write method for writing information via mbox   * @filp: open sysfs file   * @kobj: kernel kobject that contains the kernel class device. @@ -3615,71 +5017,18 @@ sysfs_mbox_idle(struct lpfc_hba *phba)   * @count: bytes to transfer.   *   * Description: - * Accessed via /sys/class/scsi_host/hostxxx/mbox. - * Uses the sysfs mbox to send buf contents to the adapter. + * Deprecated function. All mailbox access from user space is performed via the + * bsg interface.   *   * Returns: - * -ERANGE off and count combo out of range - * -EINVAL off, count or buff address invalid - * zero if count is zero - * -EPERM adapter is offline - * -ENOMEM failed to allocate memory for the mail box - * -EAGAIN offset, state or mbox is NULL - * count number of bytes transferred + * -EPERM operation not permitted   **/  static ssize_t  sysfs_mbox_write(struct file *filp, struct kobject *kobj,  		 struct bin_attribute *bin_attr,  		 char *buf, loff_t off, size_t count)  { -	struct device *dev = container_of(kobj, struct device, kobj); -	struct Scsi_Host  *shost = class_to_shost(dev); -	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; -	struct lpfc_hba   *phba = vport->phba; -	struct lpfcMboxq  *mbox = NULL; - -	if ((count + off) > MAILBOX_CMD_SIZE) -		return -ERANGE; - -	if (off % 4 ||  count % 4 || (unsigned long)buf % 4) -		return -EINVAL; - -	if (count == 0) -		return 0; - -	if (off == 0) { -		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); -		if (!mbox) -			return -ENOMEM; -		memset(mbox, 0, sizeof (LPFC_MBOXQ_t)); -	} - -	spin_lock_irq(&phba->hbalock); - -	if (off == 0) { -		if (phba->sysfs_mbox.mbox) -			mempool_free(mbox, phba->mbox_mem_pool); -		else -			phba->sysfs_mbox.mbox = mbox; -		phba->sysfs_mbox.state = SMBOX_WRITING; -	} else { -		if (phba->sysfs_mbox.state  != SMBOX_WRITING || -		    phba->sysfs_mbox.offset != off           || -		    phba->sysfs_mbox.mbox   == NULL) { -			sysfs_mbox_idle(phba); -			spin_unlock_irq(&phba->hbalock); -			return -EAGAIN; -		} -	} - -	memcpy((uint8_t *) &phba->sysfs_mbox.mbox->u.mb + off, -	       buf, count); - -	phba->sysfs_mbox.offset = off + count; - -	spin_unlock_irq(&phba->hbalock); - -	return count; +	return -EPERM;  }  /** @@ -3692,200 +5041,18 @@ sysfs_mbox_write(struct file *filp, struct kobject *kobj,   * @count: bytes to transfer.   *   * Description: - * Accessed via /sys/class/scsi_host/hostxxx/mbox. - * Uses the sysfs mbox to receive data from to the adapter. + * Deprecated function. All mailbox access from user space is performed via the + * bsg interface.   *   * Returns: - * -ERANGE off greater than mailbox command size - * -EINVAL off, count or buff address invalid - * zero if off and count are zero - * -EACCES adapter over temp - * -EPERM garbage can value to catch a multitude of errors - * -EAGAIN management IO not permitted, state or off error - * -ETIME mailbox timeout - * -ENODEV mailbox error - * count number of bytes transferred + * -EPERM operation not permitted   **/  static ssize_t  sysfs_mbox_read(struct file *filp, struct kobject *kobj,  		struct bin_attribute *bin_attr,  		char *buf, loff_t off, size_t count)  { -	struct device *dev = container_of(kobj, struct device, kobj); -	struct Scsi_Host  *shost = class_to_shost(dev); -	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; -	struct lpfc_hba   *phba = vport->phba; -	int rc; -	MAILBOX_t *pmb; - -	if (off > MAILBOX_CMD_SIZE) -		return -ERANGE; - -	if ((count + off) > MAILBOX_CMD_SIZE) -		count = MAILBOX_CMD_SIZE - off; - -	if (off % 4 ||  count % 4 || (unsigned long)buf % 4) -		return -EINVAL; - -	if (off && count == 0) -		return 0; - -	spin_lock_irq(&phba->hbalock); - -	if (phba->over_temp_state == HBA_OVER_TEMP) { -		sysfs_mbox_idle(phba); -		spin_unlock_irq(&phba->hbalock); -		return  -EACCES; -	} - -	if (off == 0 && -	    phba->sysfs_mbox.state  == SMBOX_WRITING && -	    phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) { -		pmb = &phba->sysfs_mbox.mbox->u.mb; -		switch (pmb->mbxCommand) { -			/* Offline only */ -		case MBX_INIT_LINK: -		case MBX_DOWN_LINK: -		case MBX_CONFIG_LINK: -		case MBX_CONFIG_RING: -		case MBX_RESET_RING: -		case MBX_UNREG_LOGIN: -		case MBX_CLEAR_LA: -		case MBX_DUMP_CONTEXT: -		case MBX_RUN_DIAGS: -		case MBX_RESTART: -		case MBX_SET_MASK: -		case MBX_SET_DEBUG: -			if (!(vport->fc_flag & FC_OFFLINE_MODE)) { -				printk(KERN_WARNING "mbox_read:Command 0x%x " -				       "is illegal in on-line state\n", -				       pmb->mbxCommand); -				sysfs_mbox_idle(phba); -				spin_unlock_irq(&phba->hbalock); -				return -EPERM; -			} -		case MBX_WRITE_NV: -		case MBX_WRITE_VPARMS: -		case MBX_LOAD_SM: -		case MBX_READ_NV: -		case MBX_READ_CONFIG: -		case MBX_READ_RCONFIG: -		case MBX_READ_STATUS: -		case MBX_READ_XRI: -		case MBX_READ_REV: -		case MBX_READ_LNK_STAT: -		case MBX_DUMP_MEMORY: -		case MBX_DOWN_LOAD: -		case MBX_UPDATE_CFG: -		case MBX_KILL_BOARD: -		case MBX_LOAD_AREA: -		case MBX_LOAD_EXP_ROM: -		case MBX_BEACON: -		case MBX_DEL_LD_ENTRY: -		case MBX_SET_VARIABLE: -		case MBX_WRITE_WWN: -		case MBX_PORT_CAPABILITIES: -		case MBX_PORT_IOV_CONTROL: -			break; -		case MBX_SECURITY_MGMT: -		case MBX_AUTH_PORT: -			if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { -				printk(KERN_WARNING "mbox_read:Command 0x%x " -				       "is not permitted\n", pmb->mbxCommand); -				sysfs_mbox_idle(phba); -				spin_unlock_irq(&phba->hbalock); -				return -EPERM; -			} -			break; -		case MBX_READ_SPARM64: -		case MBX_READ_LA: -		case MBX_READ_LA64: -		case MBX_REG_LOGIN: -		case MBX_REG_LOGIN64: -		case MBX_CONFIG_PORT: -		case MBX_RUN_BIU_DIAG: -			printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n", -			       pmb->mbxCommand); -			sysfs_mbox_idle(phba); -			spin_unlock_irq(&phba->hbalock); -			return -EPERM; -		default: -			printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n", -			       pmb->mbxCommand); -			sysfs_mbox_idle(phba); -			spin_unlock_irq(&phba->hbalock); -			return -EPERM; -		} - -		/* If HBA encountered an error attention, allow only DUMP -		 * or RESTART mailbox commands until the HBA is restarted. -		 */ -		if (phba->pport->stopped && -		    pmb->mbxCommand != MBX_DUMP_MEMORY && -		    pmb->mbxCommand != MBX_RESTART && -		    pmb->mbxCommand != MBX_WRITE_VPARMS && -		    pmb->mbxCommand != MBX_WRITE_WWN) -			lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, -					"1259 mbox: Issued mailbox cmd " -					"0x%x while in stopped state.\n", -					pmb->mbxCommand); - -		phba->sysfs_mbox.mbox->vport = vport; - -		/* Don't allow mailbox commands to be sent when blocked -		 * or when in the middle of discovery -		 */ -		if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { -			sysfs_mbox_idle(phba); -			spin_unlock_irq(&phba->hbalock); -			return  -EAGAIN; -		} - -		if ((vport->fc_flag & FC_OFFLINE_MODE) || -		    (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) { - -			spin_unlock_irq(&phba->hbalock); -			rc = lpfc_sli_issue_mbox (phba, -						  phba->sysfs_mbox.mbox, -						  MBX_POLL); -			spin_lock_irq(&phba->hbalock); - -		} else { -			spin_unlock_irq(&phba->hbalock); -			rc = lpfc_sli_issue_mbox_wait (phba, -						       phba->sysfs_mbox.mbox, -				lpfc_mbox_tmo_val(phba, pmb->mbxCommand) * HZ); -			spin_lock_irq(&phba->hbalock); -		} - -		if (rc != MBX_SUCCESS) { -			if (rc == MBX_TIMEOUT) { -				phba->sysfs_mbox.mbox = NULL; -			} -			sysfs_mbox_idle(phba); -			spin_unlock_irq(&phba->hbalock); -			return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV; -		} -		phba->sysfs_mbox.state = SMBOX_READING; -	} -	else if (phba->sysfs_mbox.offset != off || -		 phba->sysfs_mbox.state  != SMBOX_READING) { -		printk(KERN_WARNING  "mbox_read: Bad State\n"); -		sysfs_mbox_idle(phba); -		spin_unlock_irq(&phba->hbalock); -		return -EAGAIN; -	} - -	memcpy(buf, (uint8_t *) &pmb + off, count); - -	phba->sysfs_mbox.offset = off + count; - -	if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE) -		sysfs_mbox_idle(phba); - -	spin_unlock_irq(&phba->hbalock); - -	return count; +	return -EPERM;  }  static struct bin_attribute sysfs_mbox_attr = { @@ -3893,7 +5060,7 @@ static struct bin_attribute sysfs_mbox_attr = {  		.name = "mbox",  		.mode = S_IRUSR | S_IWUSR,  	}, -	.size = MAILBOX_CMD_SIZE, +	.size = MAILBOX_SYSFS_MAX,  	.read = sysfs_mbox_read,  	.write = sysfs_mbox_write,  }; @@ -3989,7 +5156,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)  	if (vport->port_type == LPFC_NPIV_PORT) {  		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;  	} else if (lpfc_is_link_up(phba)) { -		if (phba->fc_topology == TOPOLOGY_LOOP) { +		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {  			if (vport->fc_flag & FC_PUBLIC_LOOP)  				fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;  			else @@ -4029,8 +5196,13 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)  		case LPFC_LINK_UP:  		case LPFC_CLEAR_LA:  		case LPFC_HBA_READY: -			/* Links up, beyond this port_type reports state */ -			fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; +			/* Links up, reports port state accordingly */ +			if (vport->port_state < LPFC_VPORT_READY) +				fc_host_port_state(shost) = +							FC_PORTSTATE_BYPASSED; +			else +				fc_host_port_state(shost) = +							FC_PORTSTATE_ONLINE;  			break;  		case LPFC_HBA_ERROR:  			fc_host_port_state(shost) = FC_PORTSTATE_ERROR; @@ -4058,23 +5230,26 @@ lpfc_get_host_speed(struct Scsi_Host *shost)  	if (lpfc_is_link_up(phba)) {  		switch(phba->fc_linkspeed) { -			case LA_1GHZ_LINK: -				fc_host_speed(shost) = FC_PORTSPEED_1GBIT; +		case LPFC_LINK_SPEED_1GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_1GBIT; +			break; +		case LPFC_LINK_SPEED_2GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_2GBIT;  			break; -			case LA_2GHZ_LINK: -				fc_host_speed(shost) = FC_PORTSPEED_2GBIT; +		case LPFC_LINK_SPEED_4GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_4GBIT;  			break; -			case LA_4GHZ_LINK: -				fc_host_speed(shost) = FC_PORTSPEED_4GBIT; +		case LPFC_LINK_SPEED_8GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_8GBIT;  			break; -			case LA_8GHZ_LINK: -				fc_host_speed(shost) = FC_PORTSPEED_8GBIT; +		case LPFC_LINK_SPEED_10GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_10GBIT;  			break; -			case LA_10GHZ_LINK: -				fc_host_speed(shost) = FC_PORTSPEED_10GBIT; +		case LPFC_LINK_SPEED_16GHZ: +			fc_host_speed(shost) = FC_PORTSPEED_16GBIT;  			break; -			default: -				fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; +		default: +			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;  			break;  		}  	} else @@ -4096,9 +5271,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)  	spin_lock_irq(shost->host_lock); -	if ((vport->fc_flag & FC_FABRIC) || -	    ((phba->fc_topology == TOPOLOGY_LOOP) && -	     (vport->fc_flag & FC_PUBLIC_LOOP))) +	if ((vport->port_state > LPFC_FLOGI) && +	    ((vport->fc_flag & FC_FABRIC) || +	     ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && +	      (vport->fc_flag & FC_PUBLIC_LOOP))))  		node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);  	else  		/* fabric is local port if there is no F/FL_Port */ @@ -4171,9 +5347,17 @@ lpfc_get_stats(struct Scsi_Host *shost)  	memset(hs, 0, sizeof (struct fc_host_statistics));  	hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt; -	hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256); +	/* +	 * The MBX_READ_STATUS returns tx_k_bytes which has to +	 * converted to words +	 */ +	hs->tx_words = (uint64_t) +			((uint64_t)pmb->un.varRdStatus.xmitByteCnt +			* (uint64_t)256);  	hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt; -	hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256); +	hs->rx_words = (uint64_t) +			((uint64_t)pmb->un.varRdStatus.rcvByteCnt +			 * (uint64_t)256);  	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));  	pmb->mbxCommand = MBX_READ_LNK_STAT; @@ -4208,11 +5392,11 @@ lpfc_get_stats(struct Scsi_Host *shost)  	hs->invalid_crc_count -= lso->invalid_crc_count;  	hs->error_frames -= lso->error_frames; -	if (phba->hba_flag & HBA_FCOE_SUPPORT) { +	if (phba->hba_flag & HBA_FCOE_MODE) {  		hs->lip_count = -1;  		hs->nos_count = (phba->link_events >> 1);  		hs->nos_count -= lso->link_events; -	} else if (phba->fc_topology == TOPOLOGY_LOOP) { +	} else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {  		hs->lip_count = (phba->fc_eventTag >> 1);  		hs->lip_count -= lso->link_events;  		hs->nos_count = -1; @@ -4303,7 +5487,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)  	lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;  	lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;  	lso->error_frames = pmb->un.varRdLnk.crcCnt; -	if (phba->hba_flag & HBA_FCOE_SUPPORT) +	if (phba->hba_flag & HBA_FCOE_MODE)  		lso->link_events = (phba->link_events >> 1);  	else  		lso->link_events = (phba->fc_eventTag >> 1); @@ -4444,7 +5628,7 @@ static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)   * Description:   * This function is called by the transport after the @fc_vport's symbolic name   * has been changed. This function re-registers the symbolic name with the - * switch to propogate the change into the fabric if the vport is active. + * switch to propagate the change into the fabric if the vport is active.   **/  static void  lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport) @@ -4461,7 +5645,7 @@ lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport)   *   * This function is called by the lpfc_get_cfgparam() routine to set the   * module lpfc_log_verbose into the @phba cfg_log_verbose for use with - * log messsage according to the module's lpfc_log_verbose parameter setting + * log message according to the module's lpfc_log_verbose parameter setting   * before hba port or vport created.   **/  static void @@ -4605,6 +5789,8 @@ struct fc_function_template lpfc_vport_transport_functions = {  void  lpfc_get_cfgparam(struct lpfc_hba *phba)  { +	lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched); +	lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);  	lpfc_cr_delay_init(phba, lpfc_cr_delay);  	lpfc_cr_count_init(phba, lpfc_cr_count);  	lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); @@ -4614,18 +5800,30 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)  	lpfc_topology_init(phba, lpfc_topology);  	lpfc_link_speed_init(phba, lpfc_link_speed);  	lpfc_poll_tmo_init(phba, lpfc_poll_tmo); +	lpfc_task_mgmt_tmo_init(phba, lpfc_task_mgmt_tmo);  	lpfc_enable_npiv_init(phba, lpfc_enable_npiv); +	lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy); +	lpfc_enable_rrq_init(phba, lpfc_enable_rrq);  	lpfc_use_msi_init(phba, lpfc_use_msi);  	lpfc_fcp_imax_init(phba, lpfc_fcp_imax); -	lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); -	lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count); +	lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map); +	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); @@ -4633,8 +5831,11 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)  	lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);  	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);  	lpfc_aer_support_init(phba, lpfc_aer_support); +	lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); +	lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);  	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);  	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); +	phba->cfg_enable_dss = 1;  	return;  } @@ -4654,6 +5855,7 @@ lpfc_get_vport_cfgparam(struct lpfc_vport *vport)  	lpfc_restrict_login_init(vport, lpfc_restrict_login);  	lpfc_fcp_class_init(vport, lpfc_fcp_class);  	lpfc_use_adisc_init(vport, lpfc_use_adisc); +	lpfc_first_burst_size_init(vport, lpfc_first_burst_size);  	lpfc_max_scsicmpl_time_init(vport, lpfc_max_scsicmpl_time);  	lpfc_fdmi_on_init(vport, lpfc_fdmi_on);  	lpfc_discovery_threads_init(vport, lpfc_discovery_threads);  | 
