#define LPFC_MAX_INFO_TMP_LEN 100 #define LPFC_INFO_MORE_STR "\nCould be more info...\n" /* *Writekeysizeshouldbemultipleof4.Ifwritekeyischanged *makesurethatlibrarywritekeyisalsochanged.
*/ #define LPFC_REG_WRITE_KEY_SIZE 4 #define LPFC_REG_WRITE_KEY "EMLX"
constchar *const trunk_errmsg[] = { /* map errcode */ "", /* There is no such error code at index 0*/ "link negotiated speed does not match existing" " trunk - link was \"low\" speed", "link negotiated speed does not match" " existing trunk - link was \"middle\" speed", "link negotiated speed does not match existing" " trunk - link was \"high\" speed", "Attached to non-trunking port - F_Port", "Attached to non-trunking port - N_Port", "FLOGI response timeout", "non-FLOGI frame received", "Invalid FLOGI response", "Trunking initialization protocol", "Trunk peer device mismatch",
};
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n"); return len;
} if (phba->nvmet_support) { if (!phba->targetport) {
len = scnprintf(buf, PAGE_SIZE, "NVME Target: x%llx is not allocated\n",
wwn_to_u64(vport->fc_portname.u.wwn)); return len;
} /* Port state is only one of two values for now. */ if (phba->targetport->port_id)
statep = "REGISTERED"; else
statep = "INIT";
scnprintf(tmp, sizeof(tmp), "NVME Target Enabled State %s\n",
statep); if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) goto buffer_done;
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
nrport = NULL;
spin_lock(&ndlp->lock);
rport = lpfc_ndlp_get_nrport(ndlp); if (rport)
nrport = rport->remoteport;
spin_unlock(&ndlp->lock); if (!nrport) continue;
/* Port state is only one of two values for now. */ switch (nrport->port_state) { case FC_OBJSTATE_ONLINE:
statep = "ONLINE"; break; case FC_OBJSTATE_UNKNOWN:
statep = "UNKNOWN "; break; default:
statep = "UNSUPPORTED"; break;
}
/* Tab in to show lport ownership. */ if (strlcat(buf, "NVME RPORT ", PAGE_SIZE) >= PAGE_SIZE) goto unlock_buf_done; if (phba->brd_no >= 10) { if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) goto unlock_buf_done;
}
switch (phba->link_state) { case LPFC_LINK_UNKNOWN: case LPFC_WARM_START: case LPFC_INIT_START: case LPFC_INIT_MBX_CMDS: case LPFC_LINK_DOWN: case LPFC_HBA_ERROR: if (test_bit(LINK_DISABLED, &phba->hba_flag))
len += scnprintf(buf + len, PAGE_SIZE-len, "Link Down - User disabled\n"); else
len += scnprintf(buf + len, PAGE_SIZE-len, "Link Down\n"); break; case LPFC_LINK_UP: case LPFC_CLEAR_LA: case LPFC_HBA_READY:
len += scnprintf(buf + len, PAGE_SIZE-len, "Link Up - ");
switch (vport->port_state) { case LPFC_LOCAL_CFG_LINK:
len += scnprintf(buf + len, PAGE_SIZE-len, "Configuring Link\n"); break; case LPFC_FDISC: case LPFC_FLOGI: case LPFC_FABRIC_CFG_LINK: case LPFC_NS_REG: case LPFC_NS_QRY: case LPFC_BUILD_DISC_LIST: case LPFC_DISC_AUTH:
len += scnprintf(buf + len, PAGE_SIZE - len, "Discovery\n"); break; case LPFC_VPORT_READY:
len += scnprintf(buf + len, PAGE_SIZE - len, "Ready\n"); break;
case LPFC_VPORT_FAILED:
len += scnprintf(buf + len, PAGE_SIZE - len, "Failed\n"); break;
case LPFC_VPORT_UNKNOWN:
len += scnprintf(buf + len, PAGE_SIZE - len, "Unknown\n"); break;
} if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { if (test_bit(FC_PUBLIC_LOOP, &vport->fc_flag))
len += scnprintf(buf + len, PAGE_SIZE-len, " Public Loop\n"); else
len += scnprintf(buf + len, PAGE_SIZE-len, " Private Loop\n");
} else { if (test_bit(FC_FABRIC, &vport->fc_flag)) { if (phba->sli_rev == LPFC_SLI_REV4 &&
vport->port_type == LPFC_PHYSICAL_PORT &&
phba->sli4_hba.fawwpn_flag &
LPFC_FAWWPN_FABRIC)
len += scnprintf(buf + len,
PAGE_SIZE - len, " Fabric FA-PWWN\n"); else
len += scnprintf(buf + len,
PAGE_SIZE - len, " Fabric\n");
} else {
len += scnprintf(buf + len, PAGE_SIZE-len, " Point-2-Point\n");
}
}
}
if ((phba->sli_rev == LPFC_SLI_REV4) &&
((bf_get(lpfc_sli_intf_if_type,
&phba->sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_6))) { struct lpfc_trunk_link link = phba->trunk_link;
if (bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba))
len += scnprintf(buf + len, PAGE_SIZE - len, "Trunk port 0: Link %s %s\n",
(link.link0.state == LPFC_LINK_UP) ? "Up" : "Down. ",
trunk_errmsg[link.link0.fault]);
if (bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba))
len += scnprintf(buf + len, PAGE_SIZE - len, "Trunk port 1: Link %s %s\n",
(link.link1.state == LPFC_LINK_UP) ? "Up" : "Down. ",
trunk_errmsg[link.link1.fault]);
if (bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba))
len += scnprintf(buf + len, PAGE_SIZE - len, "Trunk port 2: Link %s %s\n",
(link.link2.state == LPFC_LINK_UP) ? "Up" : "Down. ",
trunk_errmsg[link.link2.fault]);
if (bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba))
len += scnprintf(buf + len, PAGE_SIZE - len, "Trunk port 3: Link %s %s\n",
(link.link3.state == LPFC_LINK_UP) ? "Up" : "Down. ",
trunk_errmsg[link.link3.fault]);
/* Wait a little for things to settle down, but not *longenoughfordevlosstimeouttoexpire.
*/ if (phba->sli_rev != LPFC_SLI_REV4) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->sli3_ring[i]; if (!lpfc_emptyq_wait(phba, &pring->txcmplq,
&phba->hbalock)) goto out;
}
} else {
list_for_each_entry(qp, &phba->sli4_hba.lpfc_wq_list, wq_list) {
pring = qp->pring; if (!pring) continue; if (!lpfc_emptyq_wait(phba, &pring->txcmplq,
&pring->ring_lock)) goto out;
}
}
out:
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_QUEUE_FREE_WAIT;
spin_unlock_irq(&phba->hbalock);
res = lpfc_check_pci_resettable(phba); if (res) return res;
/* Walk the list of devices on the pci_dev's bus */
list_for_each_entry(ptr, &pdev->bus->devices, bus_list) { /* Check port is offline */
shost = pci_get_drvdata(ptr); if (shost) {
phba_other =
((struct lpfc_vport *)shost->hostdata)->phba; if (!test_bit(FC_OFFLINE_MODE,
&phba_other->pport->fc_flag)) {
lpfc_printf_log(phba_other, KERN_INFO, LOG_INIT, "8349 WWPN = 0x%02x%02x%02x%02x" "%02x%02x%02x%02x is not " "offline!\n",
phba_other->wwpn[0],
phba_other->wwpn[1],
phba_other->wwpn[2],
phba_other->wwpn[3],
phba_other->wwpn[4],
phba_other->wwpn[5],
phba_other->wwpn[6],
phba_other->wwpn[7]); return -EBUSY;
}
}
}
/* Issue PCI bus reset */
res = pci_reset_bus(pdev); if (res) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "8350 PCI reset bus failed: %d\n", res);
}
return res;
}
/** *lpfc_selective_reset-Offlinethenonlinestheport *@phba:lpfc_hbapointer. * *Description: *Iftheportisconfiguredtoallowaresetthenthehbaisbrought *offlinethenonline. * *Notes: *Assumesanyerrorfromlpfc_do_offline()willbenegative. *Donotmakethisfunctionstatic. * *Returns: *lpfc_do_offline()returncodeifnotzero *-EIOresetnotconfiguredorerrorpostingtheevent *zeroforsuccess
**/ int
lpfc_selective_reset(struct lpfc_hba *phba)
{ struct completion online_compl; int status = 0; int rc;
if (!phba->cfg_enable_hba_reset) return -EACCES;
if (!test_bit(FC_OFFLINE_MODE, &phba->pport->fc_flag)) {
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
msleep(100); if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0)) return -EIO;
/* 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;
/* There is no point to wait if the port is in an unrecoverable *state.
*/ if (lpfc_sli4_unrecoverable_port(&portstat_reg)) return -EIO;
/* wait for the SLI port firmware ready after firmware reset */ for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10); if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0)) continue; 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) return0; else return -EIO;
}
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);
} elseif (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); if (phba->fw_dump_cmpl)
phba->fw_dump_cmpl = NULL; return rc;
}
/* keep the original port state */ if (test_bit(FC_OFFLINE_MODE, &before_fc_flag)) { if (phba->fw_dump_cmpl)
phba->fw_dump_cmpl = NULL; goto out;
}
/* Firmware dump will trigger an HA_ERATT event, and *lpfc_handle_eratt_s4routinealreadyhandlesbringingtheportback *online.
*/ if (opcode == LPFC_FW_DUMP) {
wait_for_completion(phba->fw_dump_cmpl);
} else {
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) { /* If fw_dump was performed, first disable to clean up */ if (opcode == LPFC_FW_DUMP) {
pci_disable_sriov(pdev);
phba->cfg_sriov_nr_virtfn = 0;
}
sriov_err =
lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); if (!sriov_err)
phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn;
}
/* Normally, extents are not used */ if (!phba->sli4_hba.extents_in_use) { if (mrpi)
*mrpi = max_cfg_param->max_rpi; if (mxri)
*mxri = max_cfg_param->max_xri; if (mvpi) {
max_vpi = max_cfg_param->max_vpi;
/* Limit the max we support */ if (max_vpi > LPFC_MAX_VPI)
max_vpi = LPFC_MAX_VPI;
*mvpi = max_vpi;
}
} else { /* Extents in use */ if (mrpi) { if (lpfc_sli4_get_avail_extnt_rsrc(phba,
LPFC_RSC_TYPE_FCOE_RPI,
&rsrc_ext_cnt,
&rsrc_ext_size)) {
rc = 0; goto free_pmboxq;
}
*mrpi = rsrc_ext_cnt * rsrc_ext_size;
}
if (mxri) { if (lpfc_sli4_get_avail_extnt_rsrc(phba,
LPFC_RSC_TYPE_FCOE_XRI,
&rsrc_ext_cnt,
&rsrc_ext_size)) {
rc = 0; goto free_pmboxq;
}
*mxri = rsrc_ext_cnt * rsrc_ext_size;
}
if (mvpi) { if (lpfc_sli4_get_avail_extnt_rsrc(phba,
LPFC_RSC_TYPE_FCOE_VPI,
&rsrc_ext_cnt,
&rsrc_ext_size)) {
rc = 0; goto free_pmboxq;
}
max_vpi = rsrc_ext_cnt * rsrc_ext_size;
/* Limit the max we support */ if (max_vpi > LPFC_MAX_VPI)
max_vpi = LPFC_MAX_VPI;
*mvpi = max_vpi;
}
}
} else { if (mrpi)
*mrpi = pmb->un.varRdConfig.max_rpi; if (arpi)
*arpi = pmb->un.varRdConfig.avail_rpi; if (mxri)
*mxri = pmb->un.varRdConfig.max_xri; if (axri)
*axri = pmb->un.varRdConfig.avail_xri; if (mvpi)
*mvpi = pmb->un.varRdConfig.max_vpi; if (avpi) { /* avail_vpi is only valid if link is up and ready */ if (phba->link_state == LPFC_HBA_READY)
*avpi = pmb->un.varRdConfig.avail_vpi; else
*avpi = pmb->un.varRdConfig.max_vpi;
}
}
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, "0404 lpfc_devloss_tmo attribute cannot be set to " "%d, allowed range is [%d, %d]\n",
val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); return -EINVAL;
}
/*
# 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, 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.
*/
LPFC_VPORT_ATTR_R(lun_queue_depth, 64, 1, 512,
"Max number of FCP commands we can queue to a specific LUN");
/*
# tgt_queue_depth: This parameter is used to limit the number of outstanding
# commands per target port. Value range is [10,65535]. Default value is 65535.
*/
static uint lpfc_tgt_queue_depth = LPFC_MAX_TGT_QDEPTH;
module_param(lpfc_tgt_queue_depth, uint, 0444);
MODULE_PARM_DESC(lpfc_tgt_queue_depth, "Set max Target queue depth");
lpfc_vport_param_show(tgt_queue_depth);
lpfc_vport_param_init(tgt_queue_depth, LPFC_MAX_TGT_QDEPTH,
LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH);
/**
* lpfc_tgt_queue_depth_set: Sets an attribute value.
* @vport: lpfc vport structure pointer.
* @val: integer attribute value.
*
* Description: Sets the parameter to the new value.
*
* Returns:
* zero on success
* -EINVAL if val is invalid
*/
static int
lpfc_tgt_queue_depth_set(struct lpfc_vport *vport, uint val)
{
struct lpfc_nodelist *ndlp;
unsigned long iflags;
if (!lpfc_rangecheck(val, LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH))
return -EINVAL;
/*
# hba_queue_depth: This parameter is used to limit the number of outstanding
# commands per lpfc HBA. Value range is [32,8192]. If this parameter
# value is greater than the maximum number of exchanges supported by the HBA,
# then maximum number of exchanges supported by the HBA is used to determine
# the hba_queue_depth.
*/
LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
"Max number of FCP commands we can queue to a lpfc HBA");
/*
# peer_port_login: This parameter allows/prevents logins
# between peer ports hosted on the same physical port.
# When this parameter is set 0 peer ports of same physical port
# are not allowed to login to each other.
# When this parameter is set 1 peer ports of same physical port
# are allowed to login to each other.
# Default value of this parameter is 0.
*/
LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1,
"Allow peer ports on the same physical port to login to each "
"other.");
/*
# restrict_login: This parameter allows/prevents logins
# between Virtual Ports and remote initiators.
# When this parameter is not set (0) Virtual Ports will accept PLOGIs from
# other initiators and will attempt to PLOGI all remote ports.
# When this parameter is set (1) Virtual Ports will reject PLOGIs from
# remote ports and will not attempt to PLOGI to other initiators.
# This parameter does not restrict to the physical port.
# This parameter does not restrict logins to Fabric resident remote ports.
# Default value of this parameter is 1.
*/
static int lpfc_restrict_login = 1;
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);
/**
* lpfc_restrict_login_init - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
* Description:
* If val is not in a valid range then log a kernel error message and set
* the vport restrict login to one.
* If the port type is physical clear the restrict login flag and return.
* Else set the restrict login flag to val.
*
* Returns:
* zero if val is in range
* -EINVAL val out of range
**/
static int
lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
{
if (val < 0 || val > 1) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"0422 lpfc_restrict_login attribute cannot "
"be set to %d, allowed range is [0, 1]\n",
val);
vport->cfg_restrict_login = 1;
return -EINVAL;
}
if (vport->port_type == LPFC_PHYSICAL_PORT) {
vport->cfg_restrict_login = 0;
return 0;
}
vport->cfg_restrict_login = val;
return 0;
}
/**
* lpfc_restrict_login_set - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
* Description:
* If val is not in a valid range then log a kernel error message and set
* the vport restrict login to one.
* If the port type is physical and the val is not zero log a kernel
* error message, clear the restrict login flag and return zero.
* Else set the restrict login flag to val.
*
* Returns:
* zero if val is in range
* -EINVAL val out of range
**/
static int
lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
{
if (val < 0 || val > 1) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"0425 lpfc_restrict_login attribute cannot "
"be set to %d, allowed range is [0, 1]\n",
val);
vport->cfg_restrict_login = 1;
return -EINVAL;
}
if (vport->port_type == LPFC_PHYSICAL_PORT && val != 0) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"0468 lpfc_restrict_login must be 0 for "
"Physical ports.\n");
vport->cfg_restrict_login = 0;
return 0;
}
vport->cfg_restrict_login = val;
return 0;
}
lpfc_vport_param_store(restrict_login);
static DEVICE_ATTR_RW(lpfc_restrict_login);
/*
# Some disk devices have a "select ID" or "select Target" capability.
# From a protocol standpoint "select ID" usually means select the
# Fibre channel "ALPA". In the FC-AL Profile there is an "informative
# annex" which contains a table that maps a "select ID" (a number
# between 0 and 7F) to an ALPA. By default, for compatibility with
# older drivers, the lpfc driver scans this table from low ALPA to high
# ALPA.
#
# Turning on the scan-down variable (on = 1, off = 0) will
# cause the lpfc driver to use an inverted table, effectively
# scanning ALPAs from high to low. Value range is [0,1]. Default value is 1.
#
# (Note: This "select ID" functionality is a LOOP ONLY characteristic
# and will not work across a fabric. Also this parameter will take
# effect only in the case when ALPA map is not available.)
*/
LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
"Start scanning for devices from highest ALPA to lowest");
/*
# lpfc_topology: link topology for init link
# 0x0 = attempt loop mode then point-to-point
# 0x01 = internal loopback mode
# 0x02 = attempt point-to-point mode only
# 0x04 = attempt loop mode only
# 0x06 = attempt point-to-point mode then loop
# Set point-to-point mode if you want to run as an N_Port.
# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
# Default value is 0.
*/
LPFC_ATTR(topology, 0, 0, 6,
"Select Fibre Channel topology");
/**
* lpfc_topology_store - Set the adapters topology field
* @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.
*
* Description:
* If val is in a valid range then set the adapter's topology field and
* issue a lip; if the lip fails reset the topology to the old value.
*
* If the value is not in range log a kernel error message and return an error.
*
* Returns:
* zero if val is in range and lip okay
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
static ssize_t
lpfc_topology_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;
int nolip = 0;
const char *val_buf = buf;
int err;
uint32_t prev_val;
u8 sli_family, if_type;
/**
* lpfc_static_vport_show: Read callback function for
* lpfc_static_vport sysfs file.
* @dev: Pointer to class device object.
* @attr: device attribute structure.
* @buf: Data buffer.
*
* This function is the read call back function for
* lpfc_static_vport sysfs file. The lpfc_static_vport
* sysfs file report the mageability of the vport.
**/
static ssize_t
lpfc_static_vport_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;
if (vport->vport_flag & STATIC_VPORT)
sprintf(buf, "1\n");
else
sprintf(buf, "0\n");
return strlen(buf);
}
/*
* Sysfs attribute to control the statistical data collection.
*/
static DEVICE_ATTR_RO(lpfc_static_vport);
/*
# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
# connection.
# Value range is [0,16]. Default value is 0.
*/
/**
* lpfc_link_speed_store - Set the adapters link speed
* @dev: Pointer to class device.
* @attr: Unused.
* @buf: Data buffer.
* @count: Size of the data buffer.
*
* Description:
* If val is in a valid range then set the adapter's link speed field and
* issue a lip; if the lip fails reset the link speed to the old value.
*
* Notes:
* If the value is not in range log a kernel error message and return an error.
*
* Returns:
* zero if val is in range and lip okay.
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
static ssize_t
lpfc_link_speed_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 = LPFC_USER_LINK_SPEED_AUTO;
int nolip = 0;
const char *val_buf = buf;
int err;
uint32_t prev_val, if_type;
if (!isdigit(val_buf[0]))
return -EINVAL;
if (sscanf(val_buf, "%i", &val) != 1)
return -EINVAL;
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)) ||
((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) ||
((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) {
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 >= 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;
}
switch (val) {
case LPFC_USER_LINK_SPEED_AUTO:
case LPFC_USER_LINK_SPEED_1G:
case LPFC_USER_LINK_SPEED_2G:
case LPFC_USER_LINK_SPEED_4G:
case LPFC_USER_LINK_SPEED_8G:
case LPFC_USER_LINK_SPEED_16G:
case LPFC_USER_LINK_SPEED_32G:
case LPFC_USER_LINK_SPEED_64G:
prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val;
if (nolip)
return strlen(buf);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0469 lpfc_link_speed attribute cannot be set to %d, "
"allowed values are [%s]\n",
val, LPFC_LINK_SPEED_STRING);
return -EINVAL;
}
static int lpfc_link_speed = 0;
module_param(lpfc_link_speed, int, S_IRUGO);
MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
lpfc_param_show(link_speed)
/**
* lpfc_link_speed_init - Set the adapters link speed
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
* Description:
* If val is in a valid range then set the adapter's link speed field.
*
* Notes:
* If the value is not in range log a kernel error message, clear the link
* speed and return an error.
*
* Returns:
* zero if val saved.
* -EINVAL val out of range
**/
static int
lpfc_link_speed_init(struct lpfc_hba *phba, int 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;
}
switch (val) {
case LPFC_USER_LINK_SPEED_AUTO:
case LPFC_USER_LINK_SPEED_1G:
case LPFC_USER_LINK_SPEED_2G:
case LPFC_USER_LINK_SPEED_4G:
case LPFC_USER_LINK_SPEED_8G:
case LPFC_USER_LINK_SPEED_16G:
case LPFC_USER_LINK_SPEED_32G:
case LPFC_USER_LINK_SPEED_64G:
phba->cfg_link_speed = val;
return 0;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0405 lpfc_link_speed attribute cannot "
"be set to %d, allowed values are "
"["LPFC_LINK_SPEED_STRING"]\n", val);
phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
return -EINVAL;
}
}
static DEVICE_ATTR_RW(lpfc_link_speed);
/*
# lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER)
# 1 = aer supported and enabled (default)
# PCIe error reporting is always enabled by the PCI core, so this always
# shows 1.
#
# N.B. Parts of LPFC_ATTR open-coded since some of the underlying
# infrastructure (phba->cfg_aer_support) is gone.
*/
static uint lpfc_aer_support = 1;
module_param(lpfc_aer_support, uint, S_IRUGO);
MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");
static ssize_t
lpfc_aer_support_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", lpfc_aer_support);
}
/**
* lpfc_aer_support_store - Set the adapter for aer support
*
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing enable or disable aer flag.
* @count: unused variable.
*
* Description:
* PCIe error reporting is enabled by the PCI core, so drivers don't need
* to do anything. Retain this interface for backwards compatibility,
* but do nothing.
*
* Returns:
* length of the buf on success
* -EINVAL if val out of range
**/
static ssize_t
lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int val = 0;
if (!isdigit(buf[0]))
return -EINVAL;
if (sscanf(buf, "%i", &val) != 1)
return -EINVAL;
dev_info_once(dev, "PCIe error reporting automatically enabled by the PCI core; sysfs write ignored\n");
return strlen(buf);
}
static DEVICE_ATTR_RW(lpfc_aer_support);
/**
* 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 flag 1 for aer cleanup state.
* @count: unused variable.
*
* Description:
* If the @buf contains 1, invokes the kernel AER helper routine
* pci_aer_clear_nonfatal_status() to clean up the uncorrectable
* error status register.
*
* Notes:
*
* Returns:
* -EINVAL if the buf does not contain 1
* -EPERM if the OS cannot clear AER error status, i.e., when platform
* firmware owns the AER Capability
**/
static ssize_t
lpfc_aer_cleanup_state(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, rc = -1;
if (!isdigit(buf[0]))
return -EINVAL;
if (sscanf(buf, "%i", &val) != 1)
return -EINVAL;
if (val != 1)
return -EINVAL;
rc = pci_aer_clear_nonfatal_status(phba->pcidev);
if (rc == 0)
return strlen(buf);
else
return -EPERM;
}
/**
* 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;
/**
* lpfc_request_firmware_upgrade_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;
/* Sanity check on user data */
if (!isdigit(buf[0]))
return -EINVAL;
if (sscanf(buf, "%i", &val) != 1)
return -EINVAL;
if (val != 1)
return -EINVAL;
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_force_rscn_store
*
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: unused string
* @count: unused variable.
*
* Description:
* Force the switch to send a RSCN to all other NPorts in our zone
* If we are direct connect pt2pt, build the RSCN command ourself
* and send to the other NPort. Not supported for private loop.
*
* Returns:
* 0 - on success
* -EIO - if command is not sent
**/
static ssize_t
lpfc_force_rscn_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;
int i;
i = lpfc_issue_els_rscn(vport, 0);
if (i)
return -EIO;
return strlen(buf);
}
/*
* lpfc_force_rscn: Force an RSCN to be sent to all remote NPorts
* connected to the HBA.
*
* Value range is any ascii value
*/
static int lpfc_force_rscn;
module_param(lpfc_force_rscn, int, 0644);
MODULE_PARM_DESC(lpfc_force_rscn,
"Force an RSCN to be sent to all remote NPorts");
lpfc_param_show(force_rscn)
/**
* lpfc_force_rscn_init - Force an RSCN to be sent to all remote NPorts
* @phba: lpfc_hba pointer.
* @val: unused value.
*
* Returns:
* zero if val saved.
**/
static int
lpfc_force_rscn_init(struct lpfc_hba *phba, int val)
{
return 0;
}
static DEVICE_ATTR_RW(lpfc_force_rscn);
/**
* 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;
struct lpfc_eq_intr_info *eqi;
uint32_t usdelay;
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.
* Allow value == 0
*/
if (val && (val < LPFC_MIN_IMAX || val > LPFC_MAX_IMAX))
return -EINVAL;
for (i = 0; i < phba->cfg_irq_chann; i += LPFC_MAX_EQ_DELAY_EQID_CNT)
lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT,
usdelay);
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) ||
(val == 0)) {
phba->cfg_fcp_imax = val;
return 0;
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3016 lpfc_fcp_imax: %d out of range, using default\n",
val);
phba->cfg_fcp_imax = LPFC_DEF_IMAX;
return 0;
}
static DEVICE_ATTR_RW(lpfc_fcp_imax);
/**
* lpfc_cq_max_proc_limit_store
*
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: string with the cq max processing limit of cqes
* @count: unused variable.
*
* Description:
* If val is in a valid range, then set value on each cq
*
* Returns:
* The length of the buf: if successful
* -ERANGE: if val is not in the valid range
* -EINVAL: if bad value format or intended mode is not supported.
**/
static ssize_t
lpfc_cq_max_proc_limit_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 lpfc_queue *eq, *cq;
unsigned long val;
int i;
/* cq_max_proc_limit 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 (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < LPFC_CQ_MIN_PROC_LIMIT || val > LPFC_CQ_MAX_PROC_LIMIT)
return -ERANGE;
phba->cfg_cq_max_proc_limit = (uint32_t)val;
/* set the values on the cq's */
for (i = 0; i < phba->cfg_irq_chann; i++) {
/* Get the EQ corresponding to the IRQ vector */
eq = phba->sli4_hba.hba_eq_hdl[i].eq;
if (!eq)
continue;
/*
* lpfc_cq_max_proc_limit: The maximum number CQE entries processed in an
* itteration of CQ processing.
*/
static int lpfc_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT;
module_param(lpfc_cq_max_proc_limit, int, 0644);
MODULE_PARM_DESC(lpfc_cq_max_proc_limit,
"Set the maximum number CQEs processed in an iteration of "
"CQ processing");
lpfc_param_show(cq_max_proc_limit)
/*
* lpfc_cq_poll_threshold: Set the threshold of CQE completions in a
* single handler call which should request a polled completion rather
* than re-enabling interrupts.
*/
LPFC_ATTR_RW(cq_poll_threshold, LPFC_CQ_DEF_THRESHOLD_TO_POLL,
LPFC_CQ_MIN_THRESHOLD_TO_POLL,
LPFC_CQ_MAX_THRESHOLD_TO_POLL,
"CQE Processing Threshold to enable Polling");
/**
* lpfc_cq_max_proc_limit_init - Set the initial cq max_proc_limit
* @phba: lpfc_hba pointer.
* @val: entry limit
*
* Description:
* If val is in a valid range, then initialize the adapter's maximum
* value.
*
* Returns:
* Always returns 0 for success, even if value not always set to
* requested value. If value out of range or not supported, will fall
* back to default.
**/
static int
lpfc_cq_max_proc_limit_init(struct lpfc_hba *phba, int val)
{
phba->cfg_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT;
if (phba->sli_rev != LPFC_SLI_REV4)
return 0;
if (val >= LPFC_CQ_MIN_PROC_LIMIT && val <= LPFC_CQ_MAX_PROC_LIMIT) {
phba->cfg_cq_max_proc_limit = val;
return 0;
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0371 lpfc_cq_max_proc_limit: %d out of range, using "
"default\n",
phba->cfg_cq_max_proc_limit);
return 0;
}
static DEVICE_ATTR_RW(lpfc_cq_max_proc_limit);
/**
* lpfc_fcp_cpu_map_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 += scnprintf(buf + len, PAGE_SIZE-len,
"fcp_cpu_map: No mapping (%d)\n",
phba->cfg_fcp_cpu_map);
return len;
case 1:
len += scnprintf(buf + len, PAGE_SIZE-len,
"fcp_cpu_map: HBA centric mapping (%d): "
"%d of %d CPUs online from %d possible CPUs\n",
phba->cfg_fcp_cpu_map, num_online_cpus(),
num_present_cpus(),
phba->sli4_hba.num_possible_cpu);
break;
}
while (phba->sli4_hba.curr_disp_cpu <
phba->sli4_hba.num_possible_cpu) {
cpup = &phba->sli4_hba.cpu_map[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_possible_cpu &&
(len >= (PAGE_SIZE - 64))) {
len += scnprintf(buf + len,
PAGE_SIZE - len, "more...\n");
break;
}
}
if (phba->sli4_hba.curr_disp_cpu == phba->sli4_hba.num_possible_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)
{
return -EINVAL;
}
/*
# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
# for the HBA.
#
# Value range is [0 to 1]. Default value is LPFC_HBA_CPU_MAP (1).
# 0 - Do not affinitze IRQ vectors
# 1 - Affintize HBA vectors with respect to each HBA
# (start with CPU0 for each HBA)
# This also defines how Hardware Queues are mapped to specific CPUs.
*/
static int lpfc_fcp_cpu_map = LPFC_HBA_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 lpfc_fcp_cpu_map: %d out of range, using "
"default\n", val);
phba->cfg_fcp_cpu_map = LPFC_HBA_CPU_MAP;
return 0;
}
static DEVICE_ATTR_RW(lpfc_fcp_cpu_map);
/*
# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
# Value range is [2,3]. Default value is 3.
*/
LPFC_VPORT_ATTR_R(fcp_class, 3, 2, 3,
"Select Fibre Channel class of service for FCP sequences");
/*
# lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range
# is [0,1]. Default value is 1.
*/
LPFC_VPORT_ATTR_RW(use_adisc, 1, 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_nvmet_fb_size: NVME Target mode supported first burst size.
* When the driver is configured as an NVME target, this value is
* communicated to the NVME initiator in the PRLI response. It is
* used only when the lpfc_nvme_enable_fb and lpfc_nvmet_support
* parameters are set and the target is sending the PRLI RSP.
* Parameter supported on physical port only - no NPIV support.
* Value range is [0,65536]. Default value is 0.
*/
LPFC_ATTR_RW(nvmet_fb_size, 0, 0, 65536,
"NVME Target mode first burst size in 512B increments.");
/*
* lpfc_nvme_enable_fb: Enable NVME first burst on I and T functions.
* For the Initiator (I), enabling this parameter means that an NVMET
* PRLI response with FBA enabled and an FB_SIZE set to a nonzero value will be
* processed by the initiator for subsequent NVME FCP IO.
* Currently, this feature is not supported on the NVME target
* Value range is [0,1]. Default value is 0 (disabled).
*/
LPFC_ATTR_RW(nvme_enable_fb, 0, 0, 1,
"Enable First Burst feature for NVME Initiator.");
/*
# 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
# the parameter is set to a non-zero value, the I/O queue depth is controlled
# to limit the I/O completion time to the parameter value.
# The value is set in milliseconds.
*/
LPFC_VPORT_ATTR(max_scsicmpl_time, 0, 0, 60000,
"Use command completion time to control queue depth");
lpfc_vport_param_show(max_scsicmpl_time);
static int
lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
unsigned long iflags;
if (val == vport->cfg_max_scsicmpl_time)
return 0;
if ((val < 0) || (val > 60000))
return -EINVAL;
vport->cfg_max_scsicmpl_time = val;
/*
# lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value
# range is [0,1]. Default value is 0.
*/
LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
/*
# lpfc_xri_rebalancing: enable or disable XRI rebalancing feature
# range is [0,1]. Default value is 1.
*/
LPFC_ATTR_R(xri_rebalancing, 1, 0, 1, "Enable/Disable XRI rebalancing");
/*
* lpfc_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 based on upper layer
* hardware queue index.
* For [1], FCP commands are issued to a Work Queue associated with the
* current CPU.
*
* LPFC_FCP_SCHED_BY_HDWQ == 0
* LPFC_FCP_SCHED_BY_CPU == 1
*
* The driver dynamically sets this to 1 (BY_CPU) if it's able to set up cpu
* affinity for FCP/NVME I/Os through Work Queues associated with the current
* CPU. Otherwise, the default 0 (Round Robin) scheduling of FCP/NVME I/Os
* through WQs will be used.
*/
LPFC_ATTR_RW(fcp_io_sched, LPFC_FCP_SCHED_BY_CPU,
LPFC_FCP_SCHED_BY_HDWQ,
LPFC_FCP_SCHED_BY_CPU,
"Determine scheduling algorithm for "
"issuing commands [0] - Hardware Queue, [1] - Current CPU");
/*
* lpfc_ns_query: Determine algrithmn for NameServer queries after RSCN
* range is [0,1]. Default value is 0.
* For [0], GID_FT is used for NameServer queries after RSCN (default)
* For [1], GID_PT is used for NameServer queries after RSCN
*
*/
LPFC_ATTR_RW(ns_query, LPFC_NS_QUERY_GID_FT,
LPFC_NS_QUERY_GID_FT, LPFC_NS_QUERY_GID_PT,
"Determine algorithm NameServer queries after RSCN "
"[0] - GID_FT, [1] - GID_PT");
/*
# 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
# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
# cr_delay is set to 0.
*/
LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an "
"interrupt response is generated");
LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an "
"interrupt response is generated");
/*
# lpfc_multi_ring_support: Determines how many rings to spread available
# cmd/rsp IOCB entries across.
# Value range is [1,2]. Default value is 1.
*/
LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary "
"SLI rings to spread IOCB entries across");
/*
# lpfc_multi_ring_rctl: If lpfc_multi_ring_support is enabled, this
# identifies what rctl value to configure the additional ring for.
# Value range is [1,0xff]. Default value is 4 (Unsolicated Data).
*/
LPFC_ATTR_R(multi_ring_rctl, FC_RCTL_DD_UNSOL_DATA, 1, 255, "Identifies RCTL for additional ring configuration");
/*
# lpfc_multi_ring_type: If lpfc_multi_ring_support is enabled, this
# identifies what type value to configure the additional ring for.
# Value range is [1,0xff]. Default value is 5 (LLC/SNAP).
*/
LPFC_ATTR_R(multi_ring_type, FC_TYPE_IP, 1, 255, "Identifies TYPE for additional ring configuration");
/*
# lpfc_enable_SmartSAN: Sets up FDMI support for SmartSAN
# 0 = SmartSAN functionality disabled (default)
# 1 = SmartSAN functionality enabled
# This parameter will override the value of lpfc_fdmi_on module parameter.
# Value range is [0,1]. Default value is 0.
*/
LPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN functionality");
/*
# lpfc_fdmi_on: Controls FDMI support.
# 0 No FDMI support
# 1 Traditional FDMI support (default)
# Traditional FDMI support means the driver will assume FDMI-2 support;
# however, if that fails, it will fallback to FDMI-1.
# If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on.
# If lpfc_enable_SmartSAN is set 0, the driver uses the current value of
# lpfc_fdmi_on.
# Value range [0,1]. Default value is 1.
*/
LPFC_ATTR_R(fdmi_on, 1, 0, 1, "Enable FDMI support");
/*
# Specifies the maximum number of ELS cmds we can have outstanding (for
# discovery). Value range is [1,64]. Default value = 32.
*/
LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
"during discovery");
/*
# 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_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");
/*
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
# Value range is [1,255], default value is 10.
*/
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
# 1 = MSI enabled
# 2 = MSI-X enabled (default)
# Value range is [0,2]. Default value is 2.
*/
LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
"MSI-X (2), if possible");
/*
* lpfc_nvme_oas: Use the oas bit when sending NVME/NVMET IOs
*
* 0 = NVME OAS disabled
* 1 = NVME OAS enabled
*
* Value range is [0,1]. Default value is 0.
*/
LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
"Use OAS bit on NVME IOs");
/*
* lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs
*
* 0 = Put NVME Command in SGL
* 1 = Embed NVME Command in WQE (unless G7)
* 2 = Embed NVME Command in WQE (force)
*
* Value range is [0,2]. Default value is 1.
*/
LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
"Embed NVME Command in WQE");
/*
* lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
* the driver will advertise it supports to the SCSI layer.
*
* 0 = Set nr_hw_queues by the number of CPUs or HW queues.
* 1,256 = Manually specify nr_hw_queue value to be advertised,
*
* Value range is [0,256]. Default value is 8.
*/
LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX, "Set the number of SCSI Queues advertised");
/* *lpfc_hdw_queue:SetthenumberofHardwareQueuesthedriver *willadvertiseitsupportstotheNVMEandSCSIlayers.Thisalso *willmaptothenumberofCQ/WQpairsthedriverwillcreate. * *TheNVMELayerwilltrytocreatethismany,plus1administrative *hardwarequeue.TheadministrativequeuewillalwaysmaptoWQ0 *AhardwareIOqueuemaps(qidx)toaspecificdriverCQ/WQ. * *0=ConfigurethenumberofhdwqueuestothenumberofactiveCPUs. *1,256=Manuallyspecifyhowmanyhdwqueuestouse. * *Valuerangeis[0,256].Defaultvalueis0.
*/
LPFC_ATTR_R(hdw_queue,
LPFC_HBA_HDWQ_DEF,
LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX, "Set the number of I/O Hardware Queues");
/* Check if default setting was passed */ if (val == LPFC_IRQ_CHANN_DEF &&
phba->cfg_hdw_queue == LPFC_HBA_HDWQ_DEF &&
phba->sli_rev == LPFC_SLI_REV4)
lpfc_assign_default_irq_chann(phba);
if (phba->irq_chann_mode != NORMAL_MODE) {
aff_mask = &phba->sli4_hba.irq_aff_mask;
if (cpumask_empty(aff_mask)) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "8533 Could not identify CPUS for " "mode %d, ignoring\n",
phba->irq_chann_mode);
phba->irq_chann_mode = NORMAL_MODE;
phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
} else {
phba->cfg_irq_chann = cpumask_weight(aff_mask);
/* If no hyperthread mode, then set hdwq count to *aff_maskweightaswell
*/ if (phba->irq_chann_mode == NHT_MODE)
phba->cfg_hdw_queue = phba->cfg_irq_chann;
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "8543 lpfc_irq_chann set to %u " "(mode: %d)\n", phba->cfg_irq_chann,
phba->irq_chann_mode);
}
} else { if (val > LPFC_IRQ_CHANN_MAX) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "8545 lpfc_irq_chann attribute cannot " "be set to %u, allowed range is " "[%u,%u]\n",
val,
LPFC_IRQ_CHANN_MIN,
LPFC_IRQ_CHANN_MAX);
phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF; return -EINVAL;
} if (phba->sli_rev == LPFC_SLI_REV4) {
phba->cfg_irq_chann = val;
} else {
phba->cfg_irq_chann = 2;
phba->cfg_hdw_queue = 1;
}
}
static ssize_t
lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val)
{ int ret = 0; enum ras_state state;
if (!lpfc_rangecheck(val, 0, 4)) return -EINVAL;
if (phba->cfg_ras_fwlog_buffsize == val) return0;
if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn)) return -EINVAL;
spin_lock_irq(&phba->ras_fwlog_lock);
state = phba->ras_fwlog.state;
spin_unlock_irq(&phba->ras_fwlog_lock);
if (state == REG_INPROGRESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging " "registration is in progress\n"); return -EBUSY;
}
/* For disable logging: stop the logs and free the DMA. *Forras_fwlog_buffsizesizechangewestillneedtofreeand *reallocatetheDMAinlpfc_sli4_ras_fwlog_init.
*/
phba->cfg_ras_fwlog_buffsize = val; if (state == ACTIVE) {
lpfc_ras_stop_fwlog(phba);
lpfc_sli4_ras_dma_free(phba);
}
lpfc_sli4_ras_init(phba); if (phba->ras_fwlog.ras_enabled)
ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
LPFC_RAS_ENABLE_LOGGING); return ret;
}
int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */
module_param(lpfc_use_cgn_signal, int, 0444);
MODULE_PARM_DESC(lpfc_use_cgn_signal, "Use Congestion signaling if available");
/* Virtual ports do not need ctrl_reg and mbox */ if (vport->port_type == LPFC_NPIV_PORT) return;
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
}
if (vport->port_state > LPFC_FLOGI &&
(test_bit(FC_FABRIC, &vport->fc_flag) ||
(phba->fc_topology == LPFC_TOPOLOGY_LOOP &&
test_bit(FC_PUBLIC_LOOP, &vport->fc_flag))))
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); else /* fabric is local port if there is no F/FL_Port */
node_name = 0;
/** *lpfc_get_hba_function_mode-UsedtodeterminetheHBAfunctioninFCoE *Mode *@phba:lpfc_hbapointer.
**/ staticvoid
lpfc_get_hba_function_mode(struct lpfc_hba *phba)
{ /* If the adapter supports FCoE mode */ switch (phba->pcidev->device) { case PCI_DEVICE_ID_SKYHAWK: case PCI_DEVICE_ID_SKYHAWK_VF: case PCI_DEVICE_ID_LANCER_FCOE: case PCI_DEVICE_ID_LANCER_FCOE_VF: case PCI_DEVICE_ID_ZEPHYR_DCSP: case PCI_DEVICE_ID_TIGERSHARK: case PCI_DEVICE_ID_TOMCAT:
set_bit(HBA_FCOE_MODE, &phba->hba_flag); break; default: /* for others, clear the flag */
clear_bit(HBA_FCOE_MODE, &phba->hba_flag);
}
}
/* A value of 0 means use the number of CPUs found in the system */ if (phba->cfg_hdw_queue == 0)
phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu; if (phba->cfg_irq_chann == 0)
phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu; if (phba->cfg_irq_chann > phba->cfg_hdw_queue &&
phba->sli_rev == LPFC_SLI_REV4)
phba->cfg_irq_chann = phba->cfg_hdw_queue;
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.679Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-12)
¤