diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 101 |
1 files changed, 68 insertions, 33 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index bb2d9e238225..4ed48ed38e79 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -148,9 +148,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, struct lpfc_hba *phba = vport->phba; struct lpfc_nvmet_tgtport *tgtp; struct nvme_fc_local_port *localport; - struct lpfc_nvme_lport *lport; - struct lpfc_nvme_rport *rport; + struct lpfc_nodelist *ndlp; struct nvme_fc_remote_port *nrport; + uint64_t data1, data2, data3, tot; char *statep; int len = 0; @@ -171,7 +171,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, else statep = "INIT"; len += snprintf(buf + len, PAGE_SIZE - len, - "NVME Target: Enabled State %s\n", + "NVME Target Enabled State %s\n", statep); len += snprintf(buf + len, PAGE_SIZE - len, "%s%d WWPN x%llx WWNN x%llx DID x%06x\n", @@ -245,11 +245,21 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, atomic_read(&tgtp->xmt_abort_rsp), atomic_read(&tgtp->xmt_abort_rsp_error)); + spin_lock(&phba->sli4_hba.nvmet_ctx_get_lock); + spin_lock(&phba->sli4_hba.nvmet_ctx_put_lock); + tot = phba->sli4_hba.nvmet_xri_cnt - + (phba->sli4_hba.nvmet_ctx_get_cnt + + phba->sli4_hba.nvmet_ctx_put_cnt); + spin_unlock(&phba->sli4_hba.nvmet_ctx_put_lock); + spin_unlock(&phba->sli4_hba.nvmet_ctx_get_lock); + len += snprintf(buf + len, PAGE_SIZE - len, - "IO_CTX: %08x outstanding %08x total %x", - phba->sli4_hba.nvmet_ctx_cnt, + "IO_CTX: %08x WAIT: cur %08x tot %08x\n" + "CTX Outstanding %08llx\n", + phba->sli4_hba.nvmet_xri_cnt, phba->sli4_hba.nvmet_io_wait_cnt, - phba->sli4_hba.nvmet_io_wait_total); + phba->sli4_hba.nvmet_io_wait_total, + tot); len += snprintf(buf+len, PAGE_SIZE-len, "\n"); return len; @@ -265,7 +275,6 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, len = snprintf(buf, PAGE_SIZE, "NVME Initiator Enabled\n"); spin_lock_irq(shost->host_lock); - lport = (struct lpfc_nvme_lport *)localport->private; /* Port state is only one of two values for now. */ if (localport->port_id) @@ -281,9 +290,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, wwn_to_u64(vport->fc_nodename.u.wwn), localport->port_id, statep); - list_for_each_entry(rport, &lport->rport_list, list) { + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + if (!ndlp->nrport) + continue; + /* local short-hand pointer. */ - nrport = rport->remoteport; + nrport = ndlp->nrport->remoteport; /* Port state is only one of two values for now. */ switch (nrport->port_state) { @@ -311,25 +323,23 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, len += snprintf(buf + len, PAGE_SIZE - len, "DID x%06x ", nrport->port_id); - switch (nrport->port_role) { - case FC_PORT_ROLE_NVME_INITIATOR: + /* An NVME rport can have multiple roles. */ + if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) len += snprintf(buf + len, PAGE_SIZE - len, "INITIATOR "); - break; - case FC_PORT_ROLE_NVME_TARGET: + if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) len += snprintf(buf + len, PAGE_SIZE - len, "TARGET "); - break; - case FC_PORT_ROLE_NVME_DISCOVERY: + if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) len += snprintf(buf + len, PAGE_SIZE - len, - "DISCOVERY "); - break; - default: + "DISCSRVC "); + if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | + FC_PORT_ROLE_NVME_TARGET | + FC_PORT_ROLE_NVME_DISCOVERY)) len += snprintf(buf + len, PAGE_SIZE - len, - "UNKNOWN_ROLE x%x", + "UNKNOWN ROLE x%x", nrport->port_role); - break; - } + len += snprintf(buf + len, PAGE_SIZE - len, "%s ", statep); /* Terminate the string. */ len += snprintf(buf + len, PAGE_SIZE - len, "\n"); @@ -338,19 +348,21 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, len += snprintf(buf + len, PAGE_SIZE - len, "\nNVME Statistics\n"); len += snprintf(buf+len, PAGE_SIZE-len, - "LS: Xmt %016llx Cmpl %016llx\n", - phba->fc4NvmeLsRequests, - phba->fc4NvmeLsCmpls); - + "LS: Xmt %016x Cmpl %016x\n", + atomic_read(&phba->fc4NvmeLsRequests), + atomic_read(&phba->fc4NvmeLsCmpls)); + + tot = atomic_read(&phba->fc4NvmeIoCmpls); + data1 = atomic_read(&phba->fc4NvmeInputRequests); + data2 = atomic_read(&phba->fc4NvmeOutputRequests); + data3 = atomic_read(&phba->fc4NvmeControlRequests); len += snprintf(buf+len, PAGE_SIZE-len, "FCP: Rd %016llx Wr %016llx IO %016llx\n", - phba->fc4NvmeInputRequests, - phba->fc4NvmeOutputRequests, - phba->fc4NvmeControlRequests); + data1, data2, data3); len += snprintf(buf+len, PAGE_SIZE-len, - " Cmpl %016llx\n", phba->fc4NvmeIoCmpls); - + " Cmpl %016llx Outstanding %016llx\n", + tot, (data1 + data2 + data3) - tot); return len; } @@ -1342,6 +1354,8 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, goto board_mode_out; } wait_for_completion(&online_compl); + if (status) + status = -EIO; } 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) @@ -3198,9 +3212,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) shost = lpfc_shost_from_vport(vport); spin_lock_irq(shost->host_lock); - list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) - if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport) + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + if (!NLP_CHK_NODE_ACT(ndlp)) + continue; + if (ndlp->rport) ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; + } spin_unlock_irq(shost->host_lock); } @@ -4467,9 +4484,11 @@ lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr, return -EINVAL; phba->cfg_fcp_imax = (uint32_t)val; + phba->initial_imax = phba->cfg_fcp_imax; for (i = 0; i < phba->io_channel_irqs; i += LPFC_MAX_EQ_DELAY_EQID_CNT) - lpfc_modify_hba_eq_delay(phba, i); + lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT, + val); return strlen(buf); } @@ -4524,6 +4543,16 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val) static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, lpfc_fcp_imax_show, lpfc_fcp_imax_store); +/* + * lpfc_auto_imax: Controls Auto-interrupt coalescing values support. + * 0 No auto_imax support + * 1 auto imax on + * Auto imax will change the value of fcp_imax on a per EQ basis, using + * the EQ Delay Multiplier, depending on the activity for that EQ. + * Value range [0,1]. Default value is 1. + */ +LPFC_ATTR_RW(auto_imax, 1, 0, 1, "Enable Auto imax"); + /** * lpfc_state_show - Display current driver CPU affinity * @dev: class converted to a Scsi_host structure. @@ -5150,6 +5179,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_task_mgmt_tmo, &dev_attr_lpfc_use_msi, &dev_attr_lpfc_nvme_oas, + &dev_attr_lpfc_auto_imax, &dev_attr_lpfc_fcp_imax, &dev_attr_lpfc_fcp_cpu_map, &dev_attr_lpfc_fcp_io_channel, @@ -6168,6 +6198,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN); lpfc_use_msi_init(phba, lpfc_use_msi); lpfc_nvme_oas_init(phba, lpfc_nvme_oas); + lpfc_auto_imax_init(phba, lpfc_auto_imax); lpfc_fcp_imax_init(phba, lpfc_fcp_imax); lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map); lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset); @@ -6212,6 +6243,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_enable_fc4_type |= LPFC_ENABLE_FCP; } + if (phba->cfg_auto_imax && !phba->cfg_fcp_imax) + phba->cfg_auto_imax = 0; + phba->initial_imax = phba->cfg_fcp_imax; + /* A value of 0 means use the number of CPUs found in the system */ if (phba->cfg_fcp_io_channel == 0) phba->cfg_fcp_io_channel = phba->sli4_hba.num_present_cpu; |