summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-29 11:55:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-29 11:55:36 -0700
commit08dbfad3f5040f5bdb6c529da20d6d4e81fefd72 (patch)
tree94767b4d009979fd40f7c1deab59bb578c88529b /drivers
parentcf72cbb39da84b6f02f90c07f33b102fc10b16f0 (diff)
parent12e67eb89eb2b9516685c744d3f7de0a2d1bd701 (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi
Pull more SCSI updates from Martin Petersen: "Remaining updates for the 7.3 merge window. The only core change is enabling context analysis for the SCSI layer and UFS. The remaining changes are either bug fixes or hardening" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi: (26 commits) scsi: snic: Fix SCSI host leak on workqueue allocation failure scsi: MAINTAINERS: Update my email address scsi: MAINTAINERS: Leave the cumana_1 and oak drivers to the RISCPC maintainers scsi: leapraid: Standardize NCQ priority sysfs attributes scsi: leapraid: Serialize firmware log mmap with teardown scsi: leapraid: Balance host references for firmware log VMAs scsi: lpfc: Remove unnnecessary NULL check scsi: qla2xxx: Fix an loop timeout test scsi: qla2xxx: Fix an error code in qla_get_tmf() scsi: ibmvfc: Fix use of uninitialized rport in ibmvfc_do_work() scsi: core: Enable context analysis for hosts.o scsi: lpfc: Replace strlcat() with sysfs_emit_at() in the sysfs show functions scsi: lpfc: Replace strlcat() with seq_buf in the debugfs dump helpers scsi: lpfc: Replace strlcat() with seq_buf in lpfc_rx_monitor_report() scsi: lpfc: Replace strlcat() with scnprintf() in lpfc_vport_symbolic_node_name() scsi: lpfc: Replace strlcat() with seq_buf in lpfc_info() scsi: core: Enable context analysis scsi: core: Protect host state changes with the host lock scsi: core: Add lock context annotations scsi: core: Pass the SCSI host pointer directly to scanning functions ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/Makefile23
-rw-r--r--drivers/scsi/device_handler/Makefile3
-rw-r--r--drivers/scsi/hosts.c19
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc-core.c2
-rw-r--r--drivers/scsi/leapraid/leapraid_app.c14
-rw-r--r--drivers/scsi/leapraid/leapraid_func.c2
-rw-r--r--drivers/scsi/leapraid/leapraid_func.h4
-rw-r--r--drivers/scsi/leapraid/leapraid_os.c89
-rw-r--r--drivers/scsi/libsas/sas_expander.c96
-rw-r--r--drivers/scsi/libsas/sas_internal.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c555
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c29
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c202
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c49
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c43
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c2
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_nx2.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c6
-rw-r--r--drivers/scsi/scsi_lib.c3
-rw-r--r--drivers/scsi/scsi_scan.c52
-rw-r--r--drivers/scsi/scsi_sysfs.c7
-rw-r--r--drivers/scsi/snic/snic_main.c1
-rw-r--r--drivers/ufs/core/Makefile2
-rw-r--r--drivers/ufs/core/ufs-debugfs.c8
-rw-r--r--drivers/ufs/core/ufshcd.c15
-rw-r--r--drivers/ufs/host/Makefile2
32 files changed, 622 insertions, 628 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 098f35219e7d..533623382eca 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -14,6 +14,29 @@
# satisfy certain initialization assumptions in the SCSI layer.
# *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
+CONTEXT_ANALYSIS_constants.o := y
+CONTEXT_ANALYSIS_hosts.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 08ec144f7bf7..e72055c1ebbb 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, ...) */
@@ -363,7 +366,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
@@ -379,7 +382,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);
}
@@ -412,8 +415,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);
@@ -600,7 +603,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/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index 93b9f699c2e5..b3bc3ce872d6 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -6151,7 +6151,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
timer_delete_sync(&tgt->timer);
kref_put(&tgt->kref, ibmvfc_release_tgt);
return;
- } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
+ } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
tgt_dbg(tgt, "Deleting NVMe rport with outstanding I/O\n");
nvme_rport = tgt->nvme_remote_port;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT);
diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c
index 742f19c07fcb..84eef50947ae 100644
--- a/drivers/scsi/leapraid/leapraid_app.c
+++ b/drivers/scsi/leapraid/leapraid_app.c
@@ -171,7 +171,8 @@ static int leapraid_ctl_validate_sge_offset(struct leapraid_adapter *adapter,
return 0;
}
-static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
+static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id,
+ bool track_mmap)
{
struct leapraid_adapter *adapter;
struct Scsi_Host *shost;
@@ -184,6 +185,8 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
shost = adapter->shost;
if (!shost || !scsi_host_get(shost))
break;
+ if (track_mmap)
+ atomic_inc(&adapter->fw_log_desc.mmap_refcnt);
spin_unlock(&leapraid_adapter_lock);
return adapter;
}
@@ -589,7 +592,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
return -EFAULT;
}
- adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id);
+ adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id, false);
if (!adapter)
return -EFAULT;
@@ -697,6 +700,7 @@ static void leapraid_fw_mmap_open(struct vm_area_struct *vma)
if (!adapter)
return;
+ get_device(&adapter->shost->shost_gendev);
atomic_inc(&adapter->fw_log_desc.mmap_refcnt);
}
@@ -727,7 +731,7 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
length = vma->vm_end - vma->vm_start;
- adapter = leapraid_ctl_lookup_adapter(adapter_id);
+ adapter = leapraid_ctl_lookup_adapter(adapter_id, true);
if (!adapter) {
pr_err("%s: No adapter found!\n", __func__);
return -EINVAL;
@@ -767,10 +771,12 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_private_data = adapter;
vma->vm_ops = &leapraid_fw_mmap_vm_ops;
leapraid_fw_mmap_open(vma);
- adapter = NULL;
rc = 0;
out_put:
+ if (adapter &&
+ atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt))
+ wake_up(&adapter->fw_log_desc.mmap_waitq);
leapraid_ctl_put_adapter(adapter);
return rc;
}
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_func.h b/drivers/scsi/leapraid/leapraid_func.h
index 923596211aa1..4c0b9ca728d8 100644
--- a/drivers/scsi/leapraid/leapraid_func.h
+++ b/drivers/scsi/leapraid/leapraid_func.h
@@ -1064,7 +1064,7 @@ struct leapraid_starget_priv {
* @starget_priv: Associated target private data.
* @lun: Logical Unit Number.
* @flg: Flags.
- * @ncq_cmd_prio_enable: Enables NCQ command priority for RT I/O.
+ * @ncq_prio_enable: Enables NCQ command priority for RT I/O.
* @block: Block flag.
* @deleted: Deletion flag.
* @sep: SEP flag.
@@ -1073,7 +1073,7 @@ struct leapraid_sdev_priv {
struct leapraid_starget_priv *starget_priv;
unsigned int lun;
u32 flg;
- u8 ncq_cmd_prio_enable;
+ u8 ncq_prio_enable;
u8 block;
u8 deleted;
u8 sep;
diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c
index 2f3d4ac7490c..ee3242779dfd 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,
@@ -859,7 +859,7 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd,
control |= LEAPRAID_SCSIIO_CTRL_SIMPLEQ;
- if (sdev_priv->ncq_cmd_prio_enable &&
+ if (sdev_priv->ncq_prio_enable &&
(IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))) ==
IOPRIO_CLASS_RT))
control |= LEAPRAID_SCSIIO_CTRL_CMDPRI;
@@ -1854,7 +1854,16 @@ static ssize_t sas_device_handle_show(struct device *dev,
sas_device_priv_data->starget_priv->hdl);
}
-static ssize_t ncq_cmd_prio_enable_show(struct device *dev,
+static ssize_t sas_ncq_prio_supported_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ return sysfs_emit(buf, "%d\n", sas_ata_ncq_prio_supported(sdev));
+}
+
+static ssize_t sas_ncq_prio_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1867,19 +1876,16 @@ static ssize_t ncq_cmd_prio_enable_show(struct device *dev,
return -EINVAL;
}
- return sysfs_emit(buf, "%d\n",
- sas_device_priv_data->ncq_cmd_prio_enable);
+ return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq_prio_enable);
}
-static ssize_t ncq_cmd_prio_enable_store(struct device *dev,
+static ssize_t sas_ncq_prio_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
- struct scsi_vpd *vpd_pg89;
- int ncq_cmd_prio_enable;
- bool ncq_supported;
+ bool enable;
if (!sas_device_priv_data) {
dev_err(&sdev->sdev_gendev,
@@ -1887,44 +1893,63 @@ static ssize_t ncq_cmd_prio_enable_store(struct device *dev,
return -EINVAL;
}
- if (kstrtoint(buf, 0, &ncq_cmd_prio_enable))
- return -EINVAL;
-
- if (ncq_cmd_prio_enable != 0 && ncq_cmd_prio_enable != 1) {
- dev_err(&sdev->sdev_gendev,
- "%s: Invalid NCQ cmd prio %d (0/1 only)\n",
- __func__, ncq_cmd_prio_enable);
+ if (kstrtobool(buf, &enable))
return -EINVAL;
- }
- rcu_read_lock();
- vpd_pg89 = rcu_dereference(sdev->vpd_pg89);
- if (!vpd_pg89 || vpd_pg89->len < LEAPRAID_VPD_PG89_MIN_LEN) {
- rcu_read_unlock();
+ if (!sas_ata_ncq_prio_supported(sdev))
return -EINVAL;
- }
- ncq_supported = (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
- LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) &
- LEAPRAID_VPD_PG89_NCQ_BIT_MASK;
- rcu_read_unlock();
- if (ncq_supported)
- sas_device_priv_data->ncq_cmd_prio_enable =
- ncq_cmd_prio_enable;
+ sas_device_priv_data->ncq_prio_enable = enable;
return count;
}
static DEVICE_ATTR_RO(sas_device_handle);
+static DEVICE_ATTR_RO(sas_ncq_prio_supported);
+static DEVICE_ATTR_RW(sas_ncq_prio_enable);
+
+static bool leapraid_sdev_is_sata(struct scsi_device *sdev)
+{
+ struct scsi_target *starget = sdev->sdev_target;
+ struct leapraid_starget_priv *starget_priv = starget->hostdata;
+ struct leapraid_sas_dev *sas_dev;
-static DEVICE_ATTR_RW(ncq_cmd_prio_enable);
+ if (!starget_priv)
+ return false;
+
+ sas_dev = starget_priv->sas_dev;
+ return sas_dev && (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV);
+}
static struct attribute *leapraid_sdev_attrs[] = {
&dev_attr_sas_device_handle.attr,
- &dev_attr_ncq_cmd_prio_enable.attr,
+ &dev_attr_sas_ncq_prio_supported.attr,
+ &dev_attr_sas_ncq_prio_enable.attr,
NULL,
};
-ATTRIBUTE_GROUPS(leapraid_sdev);
+static umode_t leapraid_sdev_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (attr == &dev_attr_sas_ncq_prio_supported.attr ||
+ attr == &dev_attr_sas_ncq_prio_enable.attr)
+ if (!leapraid_sdev_is_sata(sdev))
+ return 0;
+
+ return attr->mode;
+}
+
+static const struct attribute_group leapraid_sdev_attr_group = {
+ .attrs = leapraid_sdev_attrs,
+ .is_visible = leapraid_sdev_attr_is_visible,
+};
+
+static const struct attribute_group *leapraid_sdev_groups[] = {
+ &leapraid_sdev_attr_group,
+ NULL,
+};
static struct scsi_host_template leapraid_driver_template = {
.module = THIS_MODULE,
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_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index c95165905483..7354ae9ba8e5 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -1329,10 +1329,8 @@ lpfc_bsg_hba_get_event(struct bsg_job *job)
else
bsg_reply->reply_payload_rcv_len = 0;
- if (evt_dat) {
- kfree(evt_dat->data);
- kfree(evt_dat);
- }
+ kfree(evt_dat->data);
+ kfree(evt_dat);
spin_lock_irqsave(&phba->ct_ev_lock, flags);
lpfc_bsg_event_unref(evt);
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 <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
+#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
@@ -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 <linux/pci.h>
+#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/export.h>
@@ -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 <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/lockdep.h>
#include <linux/dmi.h>
@@ -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..bb0cc71de37b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2302,7 +2302,7 @@ int qla_get_tmf(struct tmf_arg *arg)
if (TMF_NOT_READY(fcport)) {
ql_log(ql_log_warn, vha, 0x802c,
"Unable to acquire TM resource due to disruption.\n");
- rc = EIO;
+ rc = -EIO;
break;
}
if (ha->active_tmf < MAX_ACTIVE_TMF &&
@@ -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/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index 41ff6fbdb933..04d7ab6ad037 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -3507,7 +3507,7 @@ qla8044_poll_flash_status_reg(struct scsi_qla_host *vha)
msleep(QLA8044_FLASH_STATUS_REG_POLL_DELAY);
}
- if (!retries)
+ if (retries == -1)
ret_val = QLA_FUNCTION_FAILED;
return ret_val;
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 480a0bf2aff3..af27fd3df8d4 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 @@ retry:
} 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 @@ unlock:
}
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/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c
index 82953e6a0915..cd638b4a4d7b 100644
--- a/drivers/scsi/snic/snic_main.c
+++ b/drivers/scsi/snic/snic_main.c
@@ -305,6 +305,7 @@ snic_add_host(struct Scsi_Host *shost, struct pci_dev *pdev)
if (!shost->work_q) {
SNIC_HOST_ERR(shost, "Failed to Create ScsiHost wq.\n");
+ scsi_remove_host(shost);
ret = -ENOMEM;
}
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 69d92387e9d2..2ba244cf40ac 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 @@ out:
* 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 @@ config_pwr_mode:
* 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 @@ out:
}
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