diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 098f35219e7d..72eb395ccf1d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -14,6 +14,28 @@ # satisfy certain initialization assumptions in the SCSI layer. # *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*! +CONTEXT_ANALYSIS_constants.o := y +CONTEXT_ANALYSIS_scsi.o := y +CONTEXT_ANALYSIS_scsi_common.o := y +CONTEXT_ANALYSIS_scsi_devinfo.o := y +CONTEXT_ANALYSIS_scsi_dh.o := y +CONTEXT_ANALYSIS_scsi_error.o := y +CONTEXT_ANALYSIS_scsi_ioctl.o := y +CONTEXT_ANALYSIS_scsi_lib.o := y +CONTEXT_ANALYSIS_scsi_lib_dma.o := y +CONTEXT_ANALYSIS_scsi_logging.o := y +CONTEXT_ANALYSIS_scsi_netlink.o := y +CONTEXT_ANALYSIS_scsi_pm.o := y +CONTEXT_ANALYSIS_scsi_proc.o := y +CONTEXT_ANALYSIS_scsi_scan.o := y +CONTEXT_ANALYSIS_scsi_sysfs.o := y +CONTEXT_ANALYSIS_scsi_trace.o := y +CONTEXT_ANALYSIS_scsicam.o := y +CONTEXT_ANALYSIS_sd.o := y +CONTEXT_ANALYSIS_sd_dif.o := y +CONTEXT_ANALYSIS_sd_zbc.o := y +CONTEXT_ANALYSIS_sr.o := y +CONTEXT_ANALYSIS_sr_ioctl.o := y CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile index 0a603aefd2bb..5aa282a63e24 100644 --- a/drivers/scsi/device_handler/Makefile +++ b/drivers/scsi/device_handler/Makefile @@ -2,6 +2,9 @@ # # SCSI Device Handler # + +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index d512080268af..9610dd7aa85f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -73,8 +73,9 @@ static struct class shost_class = { * transition is illegal. **/ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) + __must_hold(shost->host_lock) { - enum scsi_host_state oldstate = shost->shost_state; + enum scsi_host_state oldstate = READ_ONCE(shost->shost_state); if (state == oldstate) return 0; @@ -145,7 +146,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) } break; } - shost->shost_state = state; + WRITE_ONCE(shost->shost_state, state); return 0; illegal: @@ -276,7 +277,8 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, if (error) goto out_disable_runtime_pm; - scsi_host_set_state(shost, SHOST_RUNNING); + scoped_guard(spinlock_irq, shost->host_lock) + scsi_host_set_state(shost, SHOST_RUNNING); get_device(shost->shost_gendev.parent); device_enable_async_suspend(&shost->shost_dev); @@ -350,6 +352,7 @@ EXPORT_SYMBOL(scsi_add_host_with_dma); static void scsi_host_dev_release(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev); + enum scsi_host_state state = scsi_get_host_state(shost); struct device *parent = dev->parent; /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ @@ -362,7 +365,7 @@ static void scsi_host_dev_release(struct device *dev) if (shost->work_q) destroy_workqueue(shost->work_q); - if (shost->shost_state == SHOST_CREATED) { + if (state == SHOST_CREATED) { /* * Free the shost_dev device name and remove the proc host dir * here if scsi_host_{alloc,put}() have been called but neither @@ -378,7 +381,7 @@ static void scsi_host_dev_release(struct device *dev) ida_free(&host_index_ida, shost->host_no); - if (shost->shost_state != SHOST_CREATED) + if (state != SHOST_CREATED) put_device(parent); kfree(shost); } @@ -411,8 +414,8 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv return NULL; shost->host_lock = &shost->default_lock; - spin_lock_init(shost->host_lock); - shost->shost_state = SHOST_CREATED; + scoped_guard(spinlock_init, shost->host_lock) + shost->shost_state = SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); INIT_LIST_HEAD(&shost->__targets); INIT_LIST_HEAD(&shost->eh_abort_list); @@ -598,7 +601,7 @@ EXPORT_SYMBOL(scsi_host_lookup); **/ struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) { - if ((shost->shost_state == SHOST_DEL) || + if (scsi_get_host_state(shost) == SHOST_DEL || !get_device(&shost->shost_gendev)) return NULL; return shost; diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c index 3e1aeceab994..089d0810bd13 100644 --- a/drivers/scsi/leapraid/leapraid_func.c +++ b/drivers/scsi/leapraid/leapraid_func.c @@ -37,7 +37,7 @@ static noinline bool leapraid_shost_in_recovery(struct Scsi_Host *shost) { enum scsi_host_state state; - state = READ_ONCE(shost->shost_state); + state = scsi_get_host_state(shost); return state == SHOST_RECOVERY || state == SHOST_CANCEL_RECOVERY || state == SHOST_DEL_RECOVERY || diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c index 2f3d4ac7490c..a8e1c9f33896 100644 --- a/drivers/scsi/leapraid/leapraid_os.c +++ b/drivers/scsi/leapraid/leapraid_os.c @@ -808,7 +808,7 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter, goto no_connect; if (sdev_priv->block && - scmd->device->host->shost_state == SHOST_RECOVERY && + scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, LEAPRAID_SCSI_ASC_POWER_ON_RESET, diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index f471ab464a78..811c9eb4fef1 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -345,11 +345,10 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, SAS_ADDR(phy->attached_sas_addr), type); } -/* check if we have an existing attached ata device on this expander phy */ -struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id) +/* Return the domain device attached to an expander phy */ +struct domain_device *sas_ex_phy_to_dev(struct domain_device *ex_dev, int phy_id) { struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy_id]; - struct domain_device *dev; struct sas_rphy *rphy; if (!ex_phy->port) @@ -359,7 +358,13 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id) if (!rphy) return NULL; - dev = sas_find_dev_by_rphy(rphy); + return sas_find_dev_by_rphy(rphy); +} + +/* Check if we have an existing attached ata device on this expander phy */ +struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id) +{ + struct domain_device *dev = sas_ex_phy_to_dev(ex_dev, phy_id); if (dev && dev_is_sata(dev)) return dev; @@ -1958,6 +1963,72 @@ static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old) return false; } +static void sas_rediscover_ex_phy(struct domain_device *dev, int phy_id, + bool last) +{ + struct expander_device *ex = &dev->ex_dev; + struct ex_phy *phy = &ex->ex_phy[phy_id]; + + phy->phy_change_count = -1; + ex->ex_change_count = -1; + sas_unregister_devs_sas_addr(dev, phy_id, last); + sas_discover_event(dev->port, DISCE_REVALIDATE_DOMAIN); +} + +static bool sas_dev_is_flutter(struct domain_device *dev, int phy_id, + u8 *sas_addr, enum sas_device_type type) +{ + struct expander_device *ex = &dev->ex_dev; + struct ex_phy *phy = &ex->ex_phy[phy_id]; + struct domain_device *child_dev; + char *action = ""; + int res; + + if (SAS_ADDR(sas_addr) != SAS_ADDR(phy->attached_sas_addr) || + !dev_type_flutter(type, phy->attached_dev_type)) + return false; + + res = sas_ex_phy_discover(dev, phy_id); + if (res) + return false; + + child_dev = sas_ex_phy_to_dev(dev, phy_id); + if (!child_dev) + goto out; + + if (dev_is_sata(child_dev) && + phy->attached_dev_type == SAS_SATA_PENDING) { + action = ", needs recovery"; + goto out; + } + + if (SAS_ADDR(child_dev->sas_addr) != SAS_ADDR(phy->attached_sas_addr)) { + pr_info("ex %016llx phy%02d sas_addr changed from %016llx to %016llx\n", + SAS_ADDR(dev->sas_addr), phy_id, + SAS_ADDR(child_dev->sas_addr), + SAS_ADDR(phy->attached_sas_addr)); + /* + * Device unregistering relies on address matching. Restore + * attached_sas_addr back to the original address so that the old + * device can be unregistered later + */ + memcpy(phy->attached_sas_addr, child_dev->sas_addr, SAS_ADDR_SIZE); + return false; + } + + if (child_dev->linkrate != phy->linkrate) { + pr_info("ex %016llx phy%02d linkrate changed from %d to %d\n", + SAS_ADDR(dev->sas_addr), phy_id, + child_dev->linkrate, phy->linkrate); + return false; + } + +out: + pr_debug("ex %016llx phy%02d broadcast flutter%s\n", + SAS_ADDR(dev->sas_addr), phy_id, action); + return true; +} + static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last, int sibling) { @@ -2011,27 +2082,16 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, if (res == 0) sas_set_ex_phy(dev, phy_id, disc_resp); goto out_free_resp; - } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) && - dev_type_flutter(type, phy->attached_dev_type)) { - struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id); - char *action = ""; - - sas_ex_phy_discover(dev, phy_id); + } - if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING) - action = ", needs recovery"; - pr_debug("ex %016llx phy%02d broadcast flutter%s\n", - SAS_ADDR(dev->sas_addr), phy_id, action); + if (sas_dev_is_flutter(dev, phy_id, sas_addr, type)) goto out_free_resp; - } /* we always have to delete the old device when we went here */ pr_info("ex %016llx phy%02d replace %016llx\n", SAS_ADDR(dev->sas_addr), phy_id, SAS_ADDR(phy->attached_sas_addr)); - sas_unregister_devs_sas_addr(dev, phy_id, last); - - res = sas_discover_new(dev, phy_id); + sas_rediscover_ex_phy(dev, phy_id, last); out_free_resp: kfree(disc_resp); return res; diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 7dce0f587149..f5c75ab10dc4 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -91,6 +91,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy); void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); +struct domain_device *sas_ex_phy_to_dev(struct domain_device *ex_dev, int phy_id); struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); int sas_ex_phy_discover(struct domain_device *dev, int single); int sas_get_report_phy_sata(struct domain_device *dev, int phy_id, diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index f4e8164b94ab..bb5c84f0b787 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -57,7 +57,6 @@ #define LPFC_MIN_DEVLOSS_TMO 1 #define LPFC_MAX_DEVLOSS_TMO 255 -#define LPFC_MAX_INFO_TMP_LEN 100 #define LPFC_INFO_MORE_STR "\nCould be more info...\n" /* * Write key size should be multiple of 4. If write key is changed @@ -126,133 +125,121 @@ lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr, int len = 0; int cpu; u64 rcv, total; - char tmp[LPFC_MAX_INFO_TMP_LEN] = {0}; if (phba->cgn_i) cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - scnprintf(tmp, sizeof(tmp), - "Congestion Mgmt Info: E2Eattr %d Ver %d " - "CMF %d cnt %d\n", - phba->sli4_hba.pc_sli4_params.mi_cap, - cp ? cp->cgn_info_version : 0, - phba->sli4_hba.pc_sli4_params.cmf, phba->cmf_timer_cnt); - - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len = strnlen(buf, PAGE_SIZE); + len += sysfs_emit_at(buf, len, + "Congestion Mgmt Info: E2Eattr %d Ver %d CMF %d cnt %d\n", + phba->sli4_hba.pc_sli4_params.mi_cap, + cp ? cp->cgn_info_version : 0, + phba->sli4_hba.pc_sli4_params.cmf, + phba->cmf_timer_cnt); if (!phba->sli4_hba.pc_sli4_params.cmf) goto buffer_done; switch (phba->cgn_init_reg_signal) { case EDC_CG_SIG_WARN_ONLY: - scnprintf(tmp, sizeof(tmp), - "Register: Init: Signal:WARN "); + len += sysfs_emit_at(buf, len, + "Register: Init: Signal:WARN "); break; case EDC_CG_SIG_WARN_ALARM: - scnprintf(tmp, sizeof(tmp), - "Register: Init: Signal:WARN|ALARM "); + len += sysfs_emit_at(buf, len, + "Register: Init: Signal:WARN|ALARM "); break; default: - scnprintf(tmp, sizeof(tmp), - "Register: Init: Signal:NONE "); + len += sysfs_emit_at(buf, len, + "Register: Init: Signal:NONE "); break; } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; switch (phba->cgn_init_reg_fpin) { case LPFC_CGN_FPIN_WARN: - scnprintf(tmp, sizeof(tmp), - "FPIN:WARN\n"); + len += sysfs_emit_at(buf, len, "FPIN:WARN\n"); break; case LPFC_CGN_FPIN_ALARM: - scnprintf(tmp, sizeof(tmp), - "FPIN:ALARM\n"); + len += sysfs_emit_at(buf, len, "FPIN:ALARM\n"); break; case LPFC_CGN_FPIN_BOTH: - scnprintf(tmp, sizeof(tmp), - "FPIN:WARN|ALARM\n"); + len += sysfs_emit_at(buf, len, "FPIN:WARN|ALARM\n"); break; default: - scnprintf(tmp, sizeof(tmp), - "FPIN:NONE\n"); + len += sysfs_emit_at(buf, len, "FPIN:NONE\n"); break; } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; switch (phba->cgn_reg_signal) { case EDC_CG_SIG_WARN_ONLY: - scnprintf(tmp, sizeof(tmp), - " Current: Signal:WARN "); + len += sysfs_emit_at(buf, len, + " Current: Signal:WARN "); break; case EDC_CG_SIG_WARN_ALARM: - scnprintf(tmp, sizeof(tmp), - " Current: Signal:WARN|ALARM "); + len += sysfs_emit_at(buf, len, + " Current: Signal:WARN|ALARM "); break; default: - scnprintf(tmp, sizeof(tmp), - " Current: Signal:NONE "); + len += sysfs_emit_at(buf, len, + " Current: Signal:NONE "); break; } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; switch (phba->cgn_reg_fpin) { case LPFC_CGN_FPIN_WARN: - scnprintf(tmp, sizeof(tmp), - "FPIN:WARN ACQEcnt:%d\n", phba->cgn_acqe_cnt); + len += sysfs_emit_at(buf, len, + "FPIN:WARN ACQEcnt:%d\n", + phba->cgn_acqe_cnt); break; case LPFC_CGN_FPIN_ALARM: - scnprintf(tmp, sizeof(tmp), - "FPIN:ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt); + len += sysfs_emit_at(buf, len, + "FPIN:ALARM ACQEcnt:%d\n", + phba->cgn_acqe_cnt); break; case LPFC_CGN_FPIN_BOTH: - scnprintf(tmp, sizeof(tmp), - "FPIN:WARN|ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt); + len += sysfs_emit_at(buf, len, + "FPIN:WARN|ALARM ACQEcnt:%d\n", + phba->cgn_acqe_cnt); break; default: - scnprintf(tmp, sizeof(tmp), - "FPIN:NONE ACQEcnt:%d\n", phba->cgn_acqe_cnt); + len += sysfs_emit_at(buf, len, + "FPIN:NONE ACQEcnt:%d\n", + phba->cgn_acqe_cnt); break; } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; if (phba->cmf_active_mode != phba->cgn_p.cgn_param_mode) { switch (phba->cmf_active_mode) { case LPFC_CFG_OFF: - scnprintf(tmp, sizeof(tmp), "Active: Mode:Off\n"); + len += sysfs_emit_at(buf, len, "Active: Mode:Off\n"); break; case LPFC_CFG_MANAGED: - scnprintf(tmp, sizeof(tmp), "Active: Mode:Managed\n"); + len += sysfs_emit_at(buf, len, + "Active: Mode:Managed\n"); break; case LPFC_CFG_MONITOR: - scnprintf(tmp, sizeof(tmp), "Active: Mode:Monitor\n"); + len += sysfs_emit_at(buf, len, + "Active: Mode:Monitor\n"); break; default: - scnprintf(tmp, sizeof(tmp), "Active: Mode:Unknown\n"); + len += sysfs_emit_at(buf, len, + "Active: Mode:Unknown\n"); } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; } switch (phba->cgn_p.cgn_param_mode) { case LPFC_CFG_OFF: - scnprintf(tmp, sizeof(tmp), "Config: Mode:Off "); + len += sysfs_emit_at(buf, len, "Config: Mode:Off "); break; case LPFC_CFG_MANAGED: - scnprintf(tmp, sizeof(tmp), "Config: Mode:Managed "); + len += sysfs_emit_at(buf, len, "Config: Mode:Managed "); break; case LPFC_CFG_MONITOR: - scnprintf(tmp, sizeof(tmp), "Config: Mode:Monitor "); + len += sysfs_emit_at(buf, len, "Config: Mode:Monitor "); break; default: - scnprintf(tmp, sizeof(tmp), "Config: Mode:Unknown "); + len += sysfs_emit_at(buf, len, "Config: Mode:Unknown "); } - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; total = 0; rcv = 0; @@ -262,24 +249,18 @@ lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr, rcv += atomic64_read(&cgs->rcv_bytes); } - scnprintf(tmp, sizeof(tmp), - "IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n", - atomic_read(&phba->cmf_busy), - phba->cmf_active_info, rcv, total); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n", + atomic_read(&phba->cmf_busy), + phba->cmf_active_info, rcv, total); - scnprintf(tmp, sizeof(tmp), - "Port_speed:%d Link_byte_cnt:%ld " - "Max_byte_per_interval:%ld\n", - lpfc_sli_port_speed_get(phba), - (unsigned long)phba->cmf_link_byte_count, - (unsigned long)phba->cmf_max_bytes_per_interval); - strlcat(buf, tmp, PAGE_SIZE); + len += sysfs_emit_at(buf, len, + "Port_speed:%d Link_byte_cnt:%ld Max_byte_per_interval:%ld\n", + lpfc_sli_port_speed_get(phba), + (unsigned long)phba->cmf_link_byte_count, + (unsigned long)phba->cmf_max_bytes_per_interval); buffer_done: - len = strnlen(buf, PAGE_SIZE); - if (unlikely(len >= (PAGE_SIZE - 1))) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "6312 Catching potential buffer " @@ -480,17 +461,19 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, char *statep; int i; int len = 0; - char tmp[LPFC_MAX_INFO_TMP_LEN] = {0}; if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) { - len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n"); + len = sysfs_emit(buf, "NVME Disabled\n"); return len; } + + len = strnlen(buf, PAGE_SIZE); + 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)); + len = sysfs_emit(buf, + "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. */ @@ -498,167 +481,131 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, 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; - - scnprintf(tmp, sizeof(tmp), - "%s%d WWPN x%llx WWNN x%llx DID x%06x\n", - "NVME Target: lpfc", - phba->brd_no, - wwn_to_u64(vport->fc_portname.u.wwn), - wwn_to_u64(vport->fc_nodename.u.wwn), - phba->targetport->port_id); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - if (strlcat(buf, "\nNVME Target: Statistics\n", PAGE_SIZE) - >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "NVME Target Enabled State %s\n", + statep); + + len += sysfs_emit_at(buf, len, + "%s%d WWPN x%llx WWNN x%llx DID x%06x\n", + "NVME Target: lpfc", + phba->brd_no, + wwn_to_u64(vport->fc_portname.u.wwn), + wwn_to_u64(vport->fc_nodename.u.wwn), + phba->targetport->port_id); + + len += sysfs_emit_at(buf, len, "\nNVME Target: Statistics\n"); tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; - scnprintf(tmp, sizeof(tmp), - "LS: Rcv %08x Drop %08x Abort %08x\n", - atomic_read(&tgtp->rcv_ls_req_in), - atomic_read(&tgtp->rcv_ls_req_drop), - atomic_read(&tgtp->xmt_ls_abort)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "LS: Rcv %08x Drop %08x Abort %08x\n", + atomic_read(&tgtp->rcv_ls_req_in), + atomic_read(&tgtp->rcv_ls_req_drop), + atomic_read(&tgtp->xmt_ls_abort)); if (atomic_read(&tgtp->rcv_ls_req_in) != atomic_read(&tgtp->rcv_ls_req_out)) { - scnprintf(tmp, sizeof(tmp), - "Rcv LS: in %08x != out %08x\n", - atomic_read(&tgtp->rcv_ls_req_in), - atomic_read(&tgtp->rcv_ls_req_out)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "Rcv LS: in %08x != out %08x\n", + atomic_read(&tgtp->rcv_ls_req_in), + atomic_read(&tgtp->rcv_ls_req_out)); } - scnprintf(tmp, sizeof(tmp), - "LS: Xmt %08x Drop %08x Cmpl %08x\n", - atomic_read(&tgtp->xmt_ls_rsp), - atomic_read(&tgtp->xmt_ls_drop), - atomic_read(&tgtp->xmt_ls_rsp_cmpl)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "LS: RSP Abort %08x xb %08x Err %08x\n", - atomic_read(&tgtp->xmt_ls_rsp_aborted), - atomic_read(&tgtp->xmt_ls_rsp_xb_set), - atomic_read(&tgtp->xmt_ls_rsp_error)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "FCP: Rcv %08x Defer %08x Release %08x " - "Drop %08x\n", - atomic_read(&tgtp->rcv_fcp_cmd_in), - atomic_read(&tgtp->rcv_fcp_cmd_defer), - atomic_read(&tgtp->xmt_fcp_release), - atomic_read(&tgtp->rcv_fcp_cmd_drop)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "LS: Xmt %08x Drop %08x Cmpl %08x\n", + atomic_read(&tgtp->xmt_ls_rsp), + atomic_read(&tgtp->xmt_ls_drop), + atomic_read(&tgtp->xmt_ls_rsp_cmpl)); + + len += sysfs_emit_at(buf, len, + "LS: RSP Abort %08x xb %08x Err %08x\n", + atomic_read(&tgtp->xmt_ls_rsp_aborted), + atomic_read(&tgtp->xmt_ls_rsp_xb_set), + atomic_read(&tgtp->xmt_ls_rsp_error)); + + len += sysfs_emit_at(buf, len, + "FCP: Rcv %08x Defer %08x Release %08x Drop %08x\n", + atomic_read(&tgtp->rcv_fcp_cmd_in), + atomic_read(&tgtp->rcv_fcp_cmd_defer), + atomic_read(&tgtp->xmt_fcp_release), + atomic_read(&tgtp->rcv_fcp_cmd_drop)); if (atomic_read(&tgtp->rcv_fcp_cmd_in) != atomic_read(&tgtp->rcv_fcp_cmd_out)) { - scnprintf(tmp, sizeof(tmp), - "Rcv FCP: in %08x != out %08x\n", - atomic_read(&tgtp->rcv_fcp_cmd_in), - atomic_read(&tgtp->rcv_fcp_cmd_out)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "Rcv FCP: in %08x != out %08x\n", + atomic_read(&tgtp->rcv_fcp_cmd_in), + atomic_read(&tgtp->rcv_fcp_cmd_out)); } - scnprintf(tmp, sizeof(tmp), - "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x " - "drop %08x\n", - atomic_read(&tgtp->xmt_fcp_read), - atomic_read(&tgtp->xmt_fcp_read_rsp), - atomic_read(&tgtp->xmt_fcp_write), - atomic_read(&tgtp->xmt_fcp_rsp), - atomic_read(&tgtp->xmt_fcp_drop)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "FCP Rsp Cmpl: %08x err %08x drop %08x\n", - atomic_read(&tgtp->xmt_fcp_rsp_cmpl), - atomic_read(&tgtp->xmt_fcp_rsp_error), - atomic_read(&tgtp->xmt_fcp_rsp_drop)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "FCP Rsp Abort: %08x xb %08x xricqe %08x\n", - atomic_read(&tgtp->xmt_fcp_rsp_aborted), - atomic_read(&tgtp->xmt_fcp_rsp_xb_set), - atomic_read(&tgtp->xmt_fcp_xri_abort_cqe)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "ABORT: Xmt %08x Cmpl %08x\n", - atomic_read(&tgtp->xmt_fcp_abort), - atomic_read(&tgtp->xmt_fcp_abort_cmpl)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x\n", - atomic_read(&tgtp->xmt_abort_sol), - atomic_read(&tgtp->xmt_abort_unsol), - atomic_read(&tgtp->xmt_abort_rsp), - atomic_read(&tgtp->xmt_abort_rsp_error)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "DELAY: ctx %08x fod %08x wqfull %08x\n", - atomic_read(&tgtp->defer_ctx), - atomic_read(&tgtp->defer_fod), - atomic_read(&tgtp->defer_wqfull)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x drop %08x\n", + atomic_read(&tgtp->xmt_fcp_read), + atomic_read(&tgtp->xmt_fcp_read_rsp), + atomic_read(&tgtp->xmt_fcp_write), + atomic_read(&tgtp->xmt_fcp_rsp), + atomic_read(&tgtp->xmt_fcp_drop)); + + len += sysfs_emit_at(buf, len, + "FCP Rsp Cmpl: %08x err %08x drop %08x\n", + atomic_read(&tgtp->xmt_fcp_rsp_cmpl), + atomic_read(&tgtp->xmt_fcp_rsp_error), + atomic_read(&tgtp->xmt_fcp_rsp_drop)); + + len += sysfs_emit_at(buf, len, + "FCP Rsp Abort: %08x xb %08x xricqe %08x\n", + atomic_read(&tgtp->xmt_fcp_rsp_aborted), + atomic_read(&tgtp->xmt_fcp_rsp_xb_set), + atomic_read(&tgtp->xmt_fcp_xri_abort_cqe)); + + len += sysfs_emit_at(buf, len, + "ABORT: Xmt %08x Cmpl %08x\n", + atomic_read(&tgtp->xmt_fcp_abort), + atomic_read(&tgtp->xmt_fcp_abort_cmpl)); + + len += sysfs_emit_at(buf, len, + "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x\n", + atomic_read(&tgtp->xmt_abort_sol), + atomic_read(&tgtp->xmt_abort_unsol), + atomic_read(&tgtp->xmt_abort_rsp), + atomic_read(&tgtp->xmt_abort_rsp_error)); + + len += sysfs_emit_at(buf, len, + "DELAY: ctx %08x fod %08x wqfull %08x\n", + atomic_read(&tgtp->defer_ctx), + atomic_read(&tgtp->defer_fod), + atomic_read(&tgtp->defer_wqfull)); /* Calculate outstanding IOs */ tot = atomic_read(&tgtp->rcv_fcp_cmd_drop); tot += atomic_read(&tgtp->xmt_fcp_release); tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot; - scnprintf(tmp, sizeof(tmp), - "IO_CTX: %08x WAIT: cur %08x tot %08x\n" - "CTX Outstanding %08llx\n\n", - phba->sli4_hba.nvmet_xri_cnt, - phba->sli4_hba.nvmet_io_wait_cnt, - phba->sli4_hba.nvmet_io_wait_total, - tot); - strlcat(buf, tmp, PAGE_SIZE); + len += sysfs_emit_at(buf, len, + "IO_CTX: %08x WAIT: cur %08x tot %08x\n" + "CTX Outstanding %08llx\n\n", + phba->sli4_hba.nvmet_xri_cnt, + phba->sli4_hba.nvmet_io_wait_cnt, + phba->sli4_hba.nvmet_io_wait_total, + tot); goto buffer_done; } localport = vport->localport; if (!localport) { - len = scnprintf(buf, PAGE_SIZE, - "NVME Initiator x%llx is not allocated\n", - wwn_to_u64(vport->fc_portname.u.wwn)); + len = sysfs_emit(buf, + "NVME Initiator x%llx is not allocated\n", + wwn_to_u64(vport->fc_portname.u.wwn)); return len; } lport = (struct lpfc_nvme_lport *)localport->private; - if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, "\nNVME Initiator Enabled\n"); - scnprintf(tmp, sizeof(tmp), - "XRI Dist lpfc%d Total %d IO %d ELS %d\n", - phba->brd_no, - phba->sli4_hba.max_cfg_param.max_xri, - phba->sli4_hba.io_xri_max, - lpfc_sli4_get_els_iocb_cnt(phba)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "XRI Dist lpfc%d Total %d IO %d ELS %d\n", + phba->brd_no, + phba->sli4_hba.max_cfg_param.max_xri, + phba->sli4_hba.io_xri_max, + lpfc_sli4_get_els_iocb_cnt(phba)); /* Port state is only one of two values for now. */ if (localport->port_id) @@ -666,15 +613,13 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, else statep = "UNKNOWN "; - scnprintf(tmp, sizeof(tmp), - "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n", - "NVME LPORT lpfc", - phba->brd_no, - wwn_to_u64(vport->fc_portname.u.wwn), - wwn_to_u64(vport->fc_nodename.u.wwn), - localport->port_id, statep); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n", + "NVME LPORT lpfc", + phba->brd_no, + wwn_to_u64(vport->fc_portname.u.wwn), + wwn_to_u64(vport->fc_nodename.u.wwn), + localport->port_id, statep); spin_lock_irqsave(&vport->fc_nodes_list_lock, iflags); @@ -702,77 +647,55 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, } /* 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; - } + len += sysfs_emit_at(buf, len, "NVME RPORT "); + if (phba->brd_no >= 10) + len += sysfs_emit_at(buf, len, " "); - scnprintf(tmp, sizeof(tmp), "WWPN x%llx ", - nrport->port_name); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; + len += sysfs_emit_at(buf, len, "WWPN x%llx ", + nrport->port_name); - scnprintf(tmp, sizeof(tmp), "WWNN x%llx ", - nrport->node_name); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; + len += sysfs_emit_at(buf, len, "WWNN x%llx ", + nrport->node_name); - scnprintf(tmp, sizeof(tmp), "DID x%06x ", - nrport->port_id); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; + len += sysfs_emit_at(buf, len, "DID x%06x ", + nrport->port_id); /* An NVME rport can have multiple roles. */ - if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) { - if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; - } - if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) { - if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; - } - if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) { - if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; - } + if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) + len += sysfs_emit_at(buf, len, "INITIATOR "); + if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) + len += sysfs_emit_at(buf, len, "TARGET "); + if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) + len += sysfs_emit_at(buf, len, "DISCSRVC "); if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | FC_PORT_ROLE_NVME_TARGET | - FC_PORT_ROLE_NVME_DISCOVERY)) { - scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x", - nrport->port_role); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; - } + FC_PORT_ROLE_NVME_DISCOVERY)) + len += sysfs_emit_at(buf, len, "UNKNOWN ROLE x%x", + nrport->port_role); + + len += sysfs_emit_at(buf, len, "%s\n", statep); - scnprintf(tmp, sizeof(tmp), "%s\n", statep); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto unlock_buf_done; + if (len >= PAGE_SIZE - 1) + break; } spin_unlock_irqrestore(&vport->fc_nodes_list_lock, iflags); if (!lport) goto buffer_done; - if (strlcat(buf, "\nNVME Statistics\n", PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, "\nNVME Statistics\n"); - scnprintf(tmp, sizeof(tmp), - "LS: Xmt %010x Cmpl %010x Abort %08x\n", - atomic_read(&lport->fc4NvmeLsRequests), - atomic_read(&lport->fc4NvmeLsCmpls), - atomic_read(&lport->xmt_ls_abort)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "LS: Xmt %010x Cmpl %010x Abort %08x\n", + atomic_read(&lport->fc4NvmeLsRequests), + atomic_read(&lport->fc4NvmeLsCmpls), + atomic_read(&lport->xmt_ls_abort)); - scnprintf(tmp, sizeof(tmp), - "LS XMIT: Err %08x CMPL: xb %08x Err %08x\n", - atomic_read(&lport->xmt_ls_err), - atomic_read(&lport->cmpl_ls_xb), - atomic_read(&lport->cmpl_ls_err)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "LS XMIT: Err %08x CMPL: xb %08x Err %08x\n", + atomic_read(&lport->xmt_ls_err), + atomic_read(&lport->cmpl_ls_xb), + atomic_read(&lport->cmpl_ls_err)); totin = 0; totout = 0; @@ -785,40 +708,25 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, data3 = cstat->control_requests; totout += (data1 + data2 + data3); } - scnprintf(tmp, sizeof(tmp), - "Total FCP Cmpl %016llx Issue %016llx " - "OutIO %016llx\n", - totin, totout, totout - totin); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "\tabort %08x noxri %08x nondlp %08x qdepth %08x " - "wqerr %08x err %08x\n", - atomic_read(&lport->xmt_fcp_abort), - atomic_read(&lport->xmt_fcp_noxri), - atomic_read(&lport->xmt_fcp_bad_ndlp), - atomic_read(&lport->xmt_fcp_qdepth), - atomic_read(&lport->xmt_fcp_wqerr), - atomic_read(&lport->xmt_fcp_err)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), - "FCP CMPL: xb %08x Err %08x\n", - atomic_read(&lport->cmpl_fcp_xb), - atomic_read(&lport->cmpl_fcp_err)); - strlcat(buf, tmp, PAGE_SIZE); - - /* host_lock is already unlocked. */ - goto buffer_done; - - unlock_buf_done: - spin_unlock_irqrestore(&vport->fc_nodes_list_lock, iflags); + len += sysfs_emit_at(buf, len, + "Total FCP Cmpl %016llx Issue %016llx OutIO %016llx\n", + totin, totout, totout - totin); + + len += sysfs_emit_at(buf, len, + "\tabort %08x noxri %08x nondlp %08x qdepth %08x wqerr %08x err %08x\n", + atomic_read(&lport->xmt_fcp_abort), + atomic_read(&lport->xmt_fcp_noxri), + atomic_read(&lport->xmt_fcp_bad_ndlp), + atomic_read(&lport->xmt_fcp_qdepth), + atomic_read(&lport->xmt_fcp_wqerr), + atomic_read(&lport->xmt_fcp_err)); + + len += sysfs_emit_at(buf, len, + "FCP CMPL: xb %08x Err %08x\n", + atomic_read(&lport->cmpl_fcp_xb), + atomic_read(&lport->cmpl_fcp_err)); buffer_done: - len = strnlen(buf, PAGE_SIZE); - if (unlikely(len >= (PAGE_SIZE - 1))) { lpfc_printf_log(phba, KERN_INFO, LOG_NVME, "6314 Catching potential buffer " @@ -844,13 +752,12 @@ lpfc_scsi_stat_show(struct device *dev, struct device_attribute *attr, u64 data1, data2, data3; u64 tot, totin, totout; int i; - char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) || (phba->sli_rev != LPFC_SLI_REV4)) return 0; - scnprintf(buf, PAGE_SIZE, "SCSI HDWQ Statistics\n"); + len = sysfs_emit(buf, "SCSI HDWQ Statistics\n"); totin = 0; totout = 0; @@ -863,22 +770,20 @@ lpfc_scsi_stat_show(struct device *dev, struct device_attribute *attr, data3 = cstat->control_requests; totout += (data1 + data2 + data3); - scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx " - "IO %016llx ", i, data1, data2, data3); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; + len += sysfs_emit_at(buf, len, + "HDWQ (%d): Rd %016llx Wr %016llx IO %016llx ", + i, data1, data2, data3); - scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n", - tot, ((data1 + data2 + data3) - tot)); - if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) - goto buffer_done; - } - scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx " - "OutIO %016llx\n", totin, totout, totout - totin); - strlcat(buf, tmp, PAGE_SIZE); + len += sysfs_emit_at(buf, len, + "Cmpl %016llx OutIO %016llx\n", + tot, ((data1 + data2 + data3) - tot)); -buffer_done: - len = strnlen(buf, PAGE_SIZE); + if (len >= PAGE_SIZE - 1) + break; + } + len += sysfs_emit_at(buf, len, + "Total FCP Cmpl %016llx Issue %016llx OutIO %016llx\n", + totin, totout, totout - totin); return len; } diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c7853e7fe071..0734ab3be3e3 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1823,34 +1823,15 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, size_t size) { char fwrev[FW_REV_STR_SIZE] = {0}; - char tmp[MAXHOSTNAMELEN] = {0}; - - memset(symbol, 0, size); - - scnprintf(tmp, sizeof(tmp), "Emulex %s", vport->phba->ModelName); - if (strlcat(symbol, tmp, size) >= size) - goto buffer_done; lpfc_decode_firmware_rev(vport->phba, fwrev, 0); - scnprintf(tmp, sizeof(tmp), " FV%s", fwrev); - if (strlcat(symbol, tmp, size) >= size) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), " DV%s", lpfc_release_version); - if (strlcat(symbol, tmp, size) >= size) - goto buffer_done; - - scnprintf(tmp, sizeof(tmp), " HN:%s", vport->phba->os_host_name); - if (strlcat(symbol, tmp, size) >= size) - goto buffer_done; + memset(symbol, 0, size); /* Note :- OS name is "Linux" */ - scnprintf(tmp, sizeof(tmp), " OS:%s", init_utsname()->sysname); - strlcat(symbol, tmp, size); - -buffer_done: - return strnlen(symbol, size); - + return scnprintf(symbol, size, "Emulex %s FV%s DV%s HN:%s OS:%s", + vport->phba->ModelName, fwrev, + lpfc_release_version, vport->phba->os_host_name, + init_utsname()->sysname); } static uint32_t diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 052023fc1733..30e3cc050aaa 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -462,7 +463,8 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) struct lpfc_pvt_pool *pvt_pool; struct lpfc_pbl_pool *pbl_pool; u32 txcmplq_cnt; - char tmp[LPFC_DEBUG_OUT_LINE_SZ] = {0}; + size_t used; + struct seq_buf s; if (phba->sli_rev != LPFC_SLI_REV4) return 0; @@ -475,6 +477,9 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) return i; } + used = strnlen(buf, size); + seq_buf_init(&s, buf + used, size - used); + /* * Pbl: Current number of free XRIs in public pool * Pvt: Current number of free XRIs in private pool @@ -484,10 +489,8 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) * pbl_empty: Incremented by 1 when all pbl_pool are empty during * IO submission */ - scnprintf(tmp, sizeof(tmp), - "HWQ: Pbl Pvt Busy HWM | pvt_empty pbl_empty "); - if (strlcat(buf, tmp, size) >= size) - return strnlen(buf, size); + seq_buf_printf(&s, + "HWQ: Pbl Pvt Busy HWM | pvt_empty pbl_empty "); #ifdef LPFC_MXP_STAT /* @@ -501,25 +504,17 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) * othPbl_hit: Incremented by 1 if successfully get a batch of XRI from * other pbl_pool */ - scnprintf(tmp, sizeof(tmp), - "MAXH above_lmt below_lmt locPbl_hit othPbl_hit"); - if (strlcat(buf, tmp, size) >= size) - return strnlen(buf, size); + seq_buf_printf(&s, "MAXH above_lmt below_lmt locPbl_hit othPbl_hit"); /* * sPbl: snapshot of Pbl 15 sec after stat gets cleared * sPvt: snapshot of Pvt 15 sec after stat gets cleared * sBusy: snapshot of Busy 15 sec after stat gets cleared */ - scnprintf(tmp, sizeof(tmp), - " | sPbl sPvt sBusy"); - if (strlcat(buf, tmp, size) >= size) - return strnlen(buf, size); + seq_buf_printf(&s, " | sPbl sPvt sBusy"); #endif - scnprintf(tmp, sizeof(tmp), "\n"); - if (strlcat(buf, tmp, size) >= size) - return strnlen(buf, size); + seq_buf_printf(&s, "\n"); hwq_count = phba->cfg_hdw_queue; for (i = 0; i < hwq_count; i++) { @@ -531,36 +526,32 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) pvt_pool = &multixri_pool->pvt_pool; txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; - scnprintf(tmp, sizeof(tmp), - "%03d: %4d %4d %4d %4d | %10d %10d ", - i, pbl_pool->count, pvt_pool->count, - txcmplq_cnt, pvt_pool->high_watermark, - qp->empty_io_bufs, multixri_pool->pbl_empty_count); - if (strlcat(buf, tmp, size) >= size) - break; + seq_buf_printf(&s, + "%03d: %4d %4d %4d %4d | %10d %10d ", + i, pbl_pool->count, pvt_pool->count, + txcmplq_cnt, pvt_pool->high_watermark, + qp->empty_io_bufs, + multixri_pool->pbl_empty_count); #ifdef LPFC_MXP_STAT - scnprintf(tmp, sizeof(tmp), - "%4d %10d %10d %10d %10d", - multixri_pool->stat_max_hwm, - multixri_pool->above_limit_count, - multixri_pool->below_limit_count, - multixri_pool->local_pbl_hit_count, - multixri_pool->other_pbl_hit_count); - if (strlcat(buf, tmp, size) >= size) - break; - - scnprintf(tmp, sizeof(tmp), - " | %4d %4d %5d", - multixri_pool->stat_pbl_count, - multixri_pool->stat_pvt_count, - multixri_pool->stat_busy_count); - if (strlcat(buf, tmp, size) >= size) - break; + seq_buf_printf(&s, + "%4d %10d %10d %10d %10d", + multixri_pool->stat_max_hwm, + multixri_pool->above_limit_count, + multixri_pool->below_limit_count, + multixri_pool->local_pbl_hit_count, + multixri_pool->other_pbl_hit_count); + + seq_buf_printf(&s, + " | %4d %4d %5d", + multixri_pool->stat_pbl_count, + multixri_pool->stat_pvt_count, + multixri_pool->stat_busy_count); #endif - scnprintf(tmp, sizeof(tmp), "\n"); - if (strlcat(buf, tmp, size) >= size) + seq_buf_printf(&s, "\n"); + + if (seq_buf_has_overflowed(&s)) break; } return strnlen(buf, size); @@ -1261,13 +1252,14 @@ lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size) u64 data1, data2, data3; u64 tot, totin, totout; int i; - char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; + struct seq_buf s; if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) || (phba->sli_rev != LPFC_SLI_REV4)) return 0; - scnprintf(buf, size, "SCSI HDWQ Statistics\n"); + seq_buf_init(&s, buf, size); + seq_buf_printf(&s, "SCSI HDWQ Statistics\n"); totin = 0; totout = 0; @@ -1280,21 +1272,18 @@ lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size) data3 = cstat->control_requests; totout += (data1 + data2 + data3); - scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx " - "IO %016llx ", i, data1, data2, data3); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_printf(&s, "HDWQ (%d): Rd %016llx Wr %016llx IO %016llx ", + i, data1, data2, data3); + + seq_buf_printf(&s, "Cmpl %016llx OutIO %016llx\n", + tot, ((data1 + data2 + data3) - tot)); - scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n", - tot, ((data1 + data2 + data3) - tot)); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + if (seq_buf_has_overflowed(&s)) + break; } - scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx " - "OutIO %016llx\n", totin, totout, totout - totin); - strlcat(buf, tmp, size); + seq_buf_printf(&s, "Total FCP Cmpl %016llx Issue %016llx OutIO %016llx\n", + totin, totout, totout - totin); -buffer_done: len = strnlen(buf, size); return len; @@ -1704,28 +1693,23 @@ lpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size) uint32_t tot_xmt; uint32_t tot_rcv; uint32_t tot_cmpl; - char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; + size_t used = strnlen(buf, size); + struct seq_buf s; - scnprintf(tmp, sizeof(tmp), "HDWQ Stats:\n\n"); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_init(&s, buf + used, size - used); - scnprintf(tmp, sizeof(tmp), "(NVME Accounting: %s) ", - (phba->hdwqstat_on & - (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ? - "Enabled" : "Disabled")); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_printf(&s, "HDWQ Stats:\n\n"); - scnprintf(tmp, sizeof(tmp), "(SCSI Accounting: %s) ", - (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ? - "Enabled" : "Disabled")); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_printf(&s, "(NVME Accounting: %s) ", + (phba->hdwqstat_on & + (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ? + "Enabled" : "Disabled")); - scnprintf(tmp, sizeof(tmp), "\n\n"); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_printf(&s, "(SCSI Accounting: %s) ", + (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ? + "Enabled" : "Disabled")); + + seq_buf_printf(&s, "\n\n"); for (i = 0; i < phba->cfg_hdw_queue; i++) { tot_rcv = 0; @@ -1744,62 +1728,50 @@ lpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size) !c_stat->rcv_io) continue; - if (!tot_xmt && !tot_cmpl && !tot_rcv) { - /* Print HDWQ string only the first time */ - scnprintf(tmp, sizeof(tmp), "[HDWQ %d]:\t", i); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - } + /* Print HDWQ string only the first time */ + if (!tot_xmt && !tot_cmpl && !tot_rcv) + seq_buf_printf(&s, "[HDWQ %d]:\t", i); tot_xmt += c_stat->xmt_io; tot_cmpl += c_stat->cmpl_io; if (phba->nvmet_support) tot_rcv += c_stat->rcv_io; - scnprintf(tmp, sizeof(tmp), "| [CPU %d]: ", j); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - - if (phba->nvmet_support) { - scnprintf(tmp, sizeof(tmp), - "XMT 0x%x CMPL 0x%x RCV 0x%x |", - c_stat->xmt_io, c_stat->cmpl_io, - c_stat->rcv_io); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - } else { - scnprintf(tmp, sizeof(tmp), - "XMT 0x%x CMPL 0x%x |", - c_stat->xmt_io, c_stat->cmpl_io); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - } + seq_buf_printf(&s, "| [CPU %d]: ", j); + + if (phba->nvmet_support) + seq_buf_printf(&s, + "XMT 0x%x CMPL 0x%x RCV 0x%x |", + c_stat->xmt_io, c_stat->cmpl_io, + c_stat->rcv_io); + else + seq_buf_printf(&s, + "XMT 0x%x CMPL 0x%x |", + c_stat->xmt_io, c_stat->cmpl_io); + + if (seq_buf_has_overflowed(&s)) + break; } + if (seq_buf_has_overflowed(&s)) + break; + /* Check if nothing to display */ if (!tot_xmt && !tot_cmpl && !tot_rcv) continue; - scnprintf(tmp, sizeof(tmp), "\t->\t[HDWQ Total: "); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; + seq_buf_printf(&s, "\t->\t[HDWQ Total: "); - if (phba->nvmet_support) { - scnprintf(tmp, sizeof(tmp), - "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n", - tot_xmt, tot_cmpl, tot_rcv); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - } else { - scnprintf(tmp, sizeof(tmp), - "XMT 0x%x CMPL 0x%x]\n\n", - tot_xmt, tot_cmpl); - if (strlcat(buf, tmp, size) >= size) - goto buffer_done; - } + if (phba->nvmet_support) + seq_buf_printf(&s, + "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n", + tot_xmt, tot_cmpl, tot_rcv); + else + seq_buf_printf(&s, + "XMT 0x%x CMPL 0x%x]\n\n", + tot_xmt, tot_cmpl); } -buffer_done: len = strnlen(buf, size); return len; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f2cab134af7f..8a795c65e3c3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -21,6 +21,7 @@ * included with this package. * *******************************************************************/ #include +#include #include #include #include @@ -5103,57 +5104,37 @@ lpfc_info(struct Scsi_Host *host) struct lpfc_hba *phba = vport->phba; int link_speed = 0; static char lpfcinfobuf[384]; - char tmp[384] = {0}; + struct seq_buf s; memset(lpfcinfobuf, 0, sizeof(lpfcinfobuf)); + seq_buf_init(&s, lpfcinfobuf, sizeof(lpfcinfobuf)); if (phba && phba->pcidev){ /* Model Description */ - scnprintf(tmp, sizeof(tmp), phba->ModelDesc); - if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >= - sizeof(lpfcinfobuf)) - goto buffer_done; + seq_buf_printf(&s, "%s", phba->ModelDesc); /* PCI Info */ - scnprintf(tmp, sizeof(tmp), - " on PCI bus %02x device %02x irq %d", - phba->pcidev->bus->number, phba->pcidev->devfn, - phba->pcidev->irq); - if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >= - sizeof(lpfcinfobuf)) - goto buffer_done; + seq_buf_printf(&s, " on PCI bus %02x device %02x irq %d", + phba->pcidev->bus->number, phba->pcidev->devfn, + phba->pcidev->irq); /* Port Number */ - if (phba->Port[0]) { - scnprintf(tmp, sizeof(tmp), " port %s", phba->Port); - if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >= - sizeof(lpfcinfobuf)) - goto buffer_done; - } + if (phba->Port[0]) + seq_buf_printf(&s, " port %s", phba->Port); /* Link Speed */ link_speed = lpfc_sli_port_speed_get(phba); - if (link_speed != 0) { - scnprintf(tmp, sizeof(tmp), - " Logical Link Speed: %d Mbps", link_speed); - if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >= - sizeof(lpfcinfobuf)) - goto buffer_done; - } + if (link_speed != 0) + seq_buf_printf(&s, " Logical Link Speed: %d Mbps", + link_speed); /* Support for BSG ioctls */ - scnprintf(tmp, sizeof(tmp), " BSG"); - if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >= - sizeof(lpfcinfobuf)) - goto buffer_done; + seq_buf_printf(&s, " BSG"); /* PCI resettable */ - if (!lpfc_check_pci_resettable(phba)) { - scnprintf(tmp, sizeof(tmp), " PCI resettable"); - strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)); - } + if (!lpfc_check_pci_resettable(phba)) + seq_buf_printf(&s, " PCI resettable"); } -buffer_done: return lpfcinfobuf; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index a05d203e4777..3e0937cf3ff3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -158,6 +158,3 @@ struct fcp_cmnd32 { #define TXRDY_PAYLOAD_LEN 12 -/* For sysfs/debugfs tmp string max len */ -#define LPFC_MAX_SCSI_INFO_TMP_LEN 79 - diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 62a30a92b792..cfa4371169f1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -8109,17 +8110,18 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, u32 cnt = 0; char tmp[DBG_LOG_STR_SZ] = {0}; bool log_to_kmsg = (!buf || !buf_len) ? true : false; + struct seq_buf s; if (!log_to_kmsg) { /* clear the buffer to be sure */ memset(buf, 0, buf_len); - scnprintf(buf, buf_len, "\t%-16s%-16s%-16s%-16s%-8s%-8s%-8s" - "%-8s%-8s%-8s%-16s\n", - "MaxBPI", "Tot_Data_CMF", - "Tot_Data_Cmd", "Tot_Data_Cmpl", - "Lat(us)", "Avg_IO", "Max_IO", "Bsy", - "IO_cnt", "Info", "BWutil(ms)"); + seq_buf_init(&s, buf, buf_len); + seq_buf_printf(&s, "\t%-16s%-16s%-16s%-16s%-8s%-8s%-8s%-8s%-8s%-8s%-16s\n", + "MaxBPI", "Tot_Data_CMF", + "Tot_Data_Cmd", "Tot_Data_Cmpl", + "Lat(us)", "Avg_IO", "Max_IO", "Bsy", + "IO_cnt", "Info", "BWutil(ms)"); } /* Needs to be _irq because record is called from timer interrupt @@ -8131,24 +8133,27 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, /* Read out this entry's data. */ if (!log_to_kmsg) { - /* If !log_to_kmsg, then store to buf. */ + /* + * Drop a record whole if it does not fit, without + * consuming its ring entry. + */ scnprintf(tmp, sizeof(tmp), - "%03d:\t%-16llu%-16llu%-16llu%-16llu%-8llu" - "%-8llu%-8llu%-8u%-8u%-8u%u(%u)\n", - *head_idx, entry->max_bytes_per_interval, - entry->cmf_bytes, entry->total_bytes, - entry->rcv_bytes, entry->avg_io_latency, - entry->avg_io_size, entry->max_read_cnt, + "%03d:\t%-16llu%-16llu%-16llu%-16llu%-8llu%-8llu%-8llu%-8u%-8u%-8u%u(%u)\n", + *head_idx, + entry->max_bytes_per_interval, + entry->cmf_bytes, + entry->total_bytes, + entry->rcv_bytes, + entry->avg_io_latency, + entry->avg_io_size, + entry->max_read_cnt, entry->cmf_busy, entry->io_cnt, - entry->cmf_info, entry->timer_utilization, + entry->cmf_info, + entry->timer_utilization, entry->timer_interval); - /* Check for buffer overflow */ - if ((strlen(buf) + strlen(tmp)) >= buf_len) + if (seq_buf_puts(&s, tmp) < 0) break; - - /* Append entry's data to buffer */ - strlcat(buf, tmp, buf_len); } else { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "4410 %02u: MBPI %llu Xmit %llu " diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index ecd365d78ae3..f0152b043e18 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3072,7 +3072,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) scmd_printk(KERN_INFO, scmd, "SCSI host state: %d SCSI host busy: %d FW outstanding: %d\n", - scmd->device->host->shost_state, + scsi_get_host_state(scmd->device->host), scsi_host_busy(scmd->device->host), atomic_read(&instance->fw_outstanding)); /* diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 402d1f35d214..f80a21ec161b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5172,7 +5172,7 @@ static enum scsi_qc_status mpi3mr_qcmd(struct Scsi_Host *shost, /* Avoid error handling escalation when device is removed or blocked */ - if (scmd->device->host->shost_state == SHOST_RECOVERY && + if (scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY && (stgt_priv_data->dev_removed || (dev_handle == MPI3MR_INVALID_DEV_HANDLE))) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 791a3c5fbf44..fed7aeffec58 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5870,6 +5870,8 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) if (ioc->pcie_sgl_dma_pool) { for (i = 0; i < ioc->scsiio_depth; i++) { + if (!ioc->pcie_sg_lookup[i].pcie_sgl) + continue; dma_pool_free(ioc->pcie_sgl_dma_pool, ioc->pcie_sg_lookup[i].pcie_sgl, ioc->pcie_sg_lookup[i].pcie_sgl_dma); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index dea78688cc9b..0e12009a87f6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5472,7 +5472,7 @@ static enum scsi_qc_status scsih_qcmd(struct Scsi_Host *shost, * Avoid error handling escallation when device is disconnected */ if (handle == MPT3SAS_INVALID_DEVICE_HANDLE || sas_device_priv_data->block) { - if (scmd->device->host->shost_state == SHOST_RECOVERY && + if (scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); scsi_done(scmd); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2b9a9c672ec6..900cd141928e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -9269,7 +9269,7 @@ static int qla29xx_process_rd_image(struct scsi_qla_host *vha, if (section == TIM) { if (section_size > req->length * qla_req_entry_size(ha)) { ql_log(ql_log_fatal, vha, 0x0098, - "TIM section too large (0x%x bytes, ring 0x%lx bytes).\n", + "TIM section too large (0x%x bytes, ring 0x%zx bytes).\n", section_size, req->length * qla_req_entry_size(ha)); return QLA_FUNCTION_FAILED; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index d598ab4126f8..c9d9fc7c81fb 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -9411,11 +9411,9 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) * This routine finds that if reset host is called in EH * scenario or from some application like sg_reset **/ -static int qla4xxx_is_eh_active(struct Scsi_Host *shost) +static bool qla4xxx_is_eh_active(struct Scsi_Host *shost) { - if (shost->shost_state == SHOST_RECOVERY) - return 1; - return 0; + return scsi_get_host_state(shost) == SHOST_RECOVERY; } /** diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 686cef2406b3..2e07b686090f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1663,10 +1663,9 @@ static enum scsi_qc_status scsi_dispatch_cmd(struct scsi_cmnd *cmd) goto done; } - if (unlikely(host->shost_state == SHOST_DEL)) { + if (unlikely(scsi_get_host_state(host) == SHOST_DEL)) { cmd->result = (DID_NO_CONNECT << 16); goto done; - } trace_scsi_dispatch_cmd_start(cmd); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e27da038603a..3b82e80e807a 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1169,6 +1169,7 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it + * @shost: SCSI host pointer * @starget: pointer to target device structure * @lun: LUN of target device * @bflagsp: store bflags here if not NULL @@ -1188,17 +1189,18 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * attached at the LUN * - SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ -static int scsi_probe_and_add_lun(struct scsi_target *starget, +static int scsi_probe_and_add_lun(struct Scsi_Host *shost, + struct scsi_target *starget, u64 lun, blist_flags_t *bflagsp, struct scsi_device **sdevp, enum scsi_scan_mode rescan, void *hostdata) + __must_hold(&shost->scan_mutex) { struct scsi_device *sdev; unsigned char *result; blist_flags_t bflags; int res = SCSI_SCAN_NO_RESPONSE, result_len = 256; - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); /* * The rescan flag is used as an optimization, the first scan of a @@ -1334,6 +1336,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, /** * scsi_sequential_lun_scan - sequentially scan a SCSI target + * @shost: SCSI host pointer * @starget: pointer to target structure to scan * @bflags: black/white list flag for LUN 0 * @scsi_level: Which version of the standard does this device adhere to @@ -1346,13 +1349,14 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * * Modifies sdevscan->lun. **/ -static void scsi_sequential_lun_scan(struct scsi_target *starget, +static void scsi_sequential_lun_scan(struct Scsi_Host *shost, + struct scsi_target *starget, blist_flags_t bflags, int scsi_level, enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { uint max_dev_lun; u64 sparse_lun, lun; - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget, "scsi scan: Sequential scan\n")); @@ -1412,14 +1416,15 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * sparse_lun. */ for (lun = 1; lun < max_dev_lun; ++lun) - if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, - NULL) != SCSI_SCAN_LUN_PRESENT) && + if (scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, + rescan, NULL) != SCSI_SCAN_LUN_PRESENT && !sparse_lun) return; } /** * scsi_report_lun_scan - Scan using SCSI REPORT LUN results + * @shost: SCSI host pointer * @starget: which target * @bflags: Zero or a mix of BLIST_NOLUN, BLIST_REPORTLUN2, or BLIST_NOREPORTLUN * @rescan: nonzero if we can skip code only needed on first scan @@ -1438,8 +1443,10 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * 0: scan completed (or no memory, so further scanning is futile) * 1: could not scan with REPORT LUN **/ -static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflags, - enum scsi_scan_mode rescan) +static int scsi_report_lun_scan(struct Scsi_Host *shost, + struct scsi_target *starget, blist_flags_t bflags, + enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; @@ -1448,7 +1455,6 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag int result; struct scsi_lun *lunp, *lun_data; struct scsi_device *sdev; - struct Scsi_Host *shost = dev_to_shost(&starget->dev); struct scsi_failure failure_defs[] = { { .sense = UNIT_ATTENTION, @@ -1594,7 +1600,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag } else { int res; - res = scsi_probe_and_add_lun(starget, + res = scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, rescan, NULL); if (res == SCSI_SCAN_NO_RESPONSE) { /* @@ -1641,7 +1647,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, scsi_complete_async_scans(); if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { - scsi_probe_and_add_lun(starget, lun, NULL, &sdev, + scsi_probe_and_add_lun(shost, starget, lun, NULL, &sdev, SCSI_SCAN_RESCAN, hostdata); scsi_autopm_put_host(shost); } @@ -1763,10 +1769,11 @@ int scsi_rescan_device(struct scsi_device *sdev) } EXPORT_SYMBOL(scsi_rescan_device); -static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, enum scsi_scan_mode rescan) +static void __scsi_scan_target(struct Scsi_Host *shost, struct device *parent, + unsigned int channel, unsigned int id, u64 lun, + enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { - struct Scsi_Host *shost = dev_to_shost(parent); blist_flags_t bflags = 0; int res; struct scsi_target *starget; @@ -1786,7 +1793,8 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, /* * Scan for a specific host/chan/id/lun. */ - scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); + scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, rescan, + NULL); goto out_reap; } @@ -1794,14 +1802,15 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * Scan LUN 0, if there is some response, scan further. Ideally, we * would not configure LUN 0 until all LUNs are scanned. */ - res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); + res = scsi_probe_and_add_lun(shost, starget, 0, &bflags, NULL, rescan, + NULL); if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { - if (scsi_report_lun_scan(starget, bflags, rescan) != 0) + if (scsi_report_lun_scan(shost, starget, bflags, rescan) != 0) /* * The REPORT LUN did not scan the target, * do a sequential scan. */ - scsi_sequential_lun_scan(starget, bflags, + scsi_sequential_lun_scan(shost, starget, bflags, starget->scsi_level, rescan); } @@ -1851,7 +1860,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, scsi_complete_async_scans(); if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { - __scsi_scan_target(parent, channel, id, lun, rescan); + __scsi_scan_target(shost, parent, channel, id, lun, rescan); scsi_autopm_put_host(shost); } mutex_unlock(&shost->scan_mutex); @@ -1861,6 +1870,7 @@ EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, unsigned int id, u64 lun, enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { uint order_id; @@ -1882,11 +1892,11 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, order_id = shost->max_id - id - 1; else order_id = id; - __scsi_scan_target(&shost->shost_gendev, channel, + __scsi_scan_target(shost, &shost->shost_gendev, channel, order_id, lun, rescan); } else - __scsi_scan_target(&shost->shost_gendev, channel, + __scsi_scan_target(shost, &shost->shost_gendev, channel, id, lun, rescan); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index dfc3559e7e04..9480432f650b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -214,8 +214,9 @@ store_shost_state(struct device *dev, struct device_attribute *attr, if (!state) return -EINVAL; - if (scsi_host_set_state(shost, state)) - return -EINVAL; + scoped_guard(spinlock_irq, shost->host_lock) + if (scsi_host_set_state(shost, state)) + return -EINVAL; return count; } @@ -223,7 +224,7 @@ static ssize_t show_shost_state(struct device *dev, struct device_attribute *attr, char *buf) { struct Scsi_Host *shost = class_to_shost(dev); - const char *name = scsi_host_state_name(shost->shost_state); + const char *name = scsi_host_state_name(scsi_get_host_state(shost)); if (!name) return -EINVAL; diff --git a/drivers/ufs/core/Makefile b/drivers/ufs/core/Makefile index ce7d16d2cf35..67ab9ffbdf5d 100644 --- a/drivers/ufs/core/Makefile +++ b/drivers/ufs/core/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-y += ufshcd.o ufs-sysfs.o ufs-mcq.o ufs-txeq.o ufshcd-core-$(CONFIG_RPMB) += ufs-rpmb.o diff --git a/drivers/ufs/core/ufs-debugfs.c b/drivers/ufs/core/ufs-debugfs.c index be527209540d..ed1de70e2ec1 100644 --- a/drivers/ufs/core/ufs-debugfs.c +++ b/drivers/ufs/core/ufs-debugfs.c @@ -65,8 +65,10 @@ static int ee_usr_mask_get(void *data, u64 *val) return 0; } +token_context_lock(ufs_debugfs); + static int ufs_debugfs_get_user_access(struct ufs_hba *hba) -__acquires(&hba->host_sem) + __cond_acquires(0, ufs_debugfs) { down(&hba->host_sem); if (!ufshcd_is_user_access_allowed(hba)) { @@ -74,14 +76,16 @@ __acquires(&hba->host_sem) return -EBUSY; } ufshcd_rpm_get_sync(hba); + __acquire(ufs_debugfs); return 0; } static void ufs_debugfs_put_user_access(struct ufs_hba *hba) -__releases(&hba->host_sem) + __releases(ufs_debugfs) { ufshcd_rpm_put_sync(hba); up(&hba->host_sem); + __release(ufs_debugfs); } static int ee_usr_mask_set(void *data, u64 val) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a51e071916cf..67745d2796d0 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1317,6 +1317,7 @@ static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba, break; } + __set_current_state(TASK_UNINTERRUPTIBLE); io_schedule_timeout(msecs_to_jiffies(20)); if (ktime_to_us(ktime_sub(ktime_get(), start)) > wait_timeout_us) { @@ -1353,6 +1354,8 @@ static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba, * On failure, all acquired locks are released and the tagset is unquiesced. */ int ufshcd_pause_command_processing(struct ufs_hba *hba, u64 timeout_us) + __cond_acquires(0, &hba->host->scan_mutex) + __cond_acquires(0, &hba->clk_scaling_lock) { int ret = 0; @@ -1377,6 +1380,8 @@ int ufshcd_pause_command_processing(struct ufs_hba *hba, u64 timeout_us) * This function resumes command submissions. */ void ufshcd_resume_command_processing(struct ufs_hba *hba) + __releases(&hba->clk_scaling_lock) + __releases(&hba->host->scan_mutex) { up_write(&hba->clk_scaling_lock); blk_mq_unquiesce_tagset(&hba->host->tag_set); @@ -1446,6 +1451,9 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, u32 target_gear, bool scale_up * Return: 0 upon success; -EBUSY upon timeout. */ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) + __cond_acquires(0, &hba->host->scan_mutex) + __cond_acquires(0, &hba->wb_mutex) + __cond_acquires(0, &hba->clk_scaling_lock) { int ret = 0; /* @@ -1475,6 +1483,9 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) } static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err) + __releases(&hba->clk_scaling_lock) + __releases(&hba->wb_mutex) + __releases(&hba->host->scan_mutex) { up_write(&hba->clk_scaling_lock); mutex_unlock(&hba->wb_mutex); @@ -3304,6 +3315,8 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) } static void ufshcd_dev_man_lock(struct ufs_hba *hba) + __acquires(&hba->dev_cmd.lock) + __acquires_shared(&hba->clk_scaling_lock) { ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); @@ -3311,6 +3324,8 @@ static void ufshcd_dev_man_lock(struct ufs_hba *hba) } static void ufshcd_dev_man_unlock(struct ufs_hba *hba) + __releases_shared(&hba->clk_scaling_lock) + __releases(&hba->dev_cmd.lock) { up_read(&hba->clk_scaling_lock); mutex_unlock(&hba->dev_cmd.lock); diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile index 65d8bb23ab7b..7d8db67eb23c 100644 --- a/drivers/ufs/host/Makefile +++ b/drivers/ufs/host/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7e2011830ba4..c9754771bf29 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -2,6 +2,7 @@ #ifndef _SCSI_SCSI_HOST_H #define _SCSI_SCSI_HOST_H +#include #include #include #include @@ -727,7 +728,7 @@ struct Scsi_Host { unsigned int irq; - enum scsi_host_state shost_state; + enum scsi_host_state shost_state __guarded_by(host_lock); /* ldm bits */ struct device shost_gendev, shost_dev; @@ -785,11 +786,18 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev) return container_of(dev, struct Scsi_Host, shost_gendev); } +static inline enum scsi_host_state scsi_get_host_state(struct Scsi_Host *shost) +{ + return context_unsafe(READ_ONCE(shost->shost_state)); +} + static inline int scsi_host_in_recovery(struct Scsi_Host *shost) { - return shost->shost_state == SHOST_RECOVERY || - shost->shost_state == SHOST_CANCEL_RECOVERY || - shost->shost_state == SHOST_DEL_RECOVERY || + enum scsi_host_state state = scsi_get_host_state(shost); + + return state == SHOST_RECOVERY || + state == SHOST_CANCEL_RECOVERY || + state == SHOST_DEL_RECOVERY || shost->tmf_in_progress; } @@ -835,8 +843,9 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost) **/ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) { - return shost->shost_state == SHOST_RUNNING || - shost->shost_state == SHOST_RECOVERY; + enum scsi_host_state state = scsi_get_host_state(shost); + + return state == SHOST_RUNNING || state == SHOST_RECOVERY; } extern void scsi_unblock_requests(struct Scsi_Host *); @@ -940,6 +949,7 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) return shost->prot_guard_type; } -extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state); +int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) + __must_hold(shost->host_lock); #endif /* _SCSI_SCSI_HOST_H */ .