aboutsummaryrefslogtreecommitdiff
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
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 ...
-rw-r--r--.mailmap3
-rw-r--r--Documentation/scsi/leapraid.rst14
-rw-r--r--MAINTAINERS6
-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
-rw-r--r--include/scsi/scsi_host.h24
36 files changed, 654 insertions, 643 deletions
diff --git a/.mailmap b/.mailmap
index 8fb9f3898d7a..eeb885837e88 100644
--- a/.mailmap
+++ b/.mailmap
@@ -577,6 +577,9 @@ Mark Brown <broonie@sirena.org.uk>
Mark Starovoytov <mstarovo@pm.me> <mstarovoitov@marvell.com>
Markus Schneider-Pargmann <msp@baylibre.com> <mpa@pengutronix.de>
Mark Yao <markyao0591@gmail.com> <mark.yao@rock-chips.com>
+Martin K. Petersen <mkp@kernel.org> <martin.petersen@oracle.com>
+Martin K. Petersen <mkp@kernel.org> <mkp@mkp.net>
+Martin K. Petersen <mkp@kernel.org> <mkp@linuxcare.com>
Martin Kepplinger-Novakovic <martink@posteo.de> <martin.kepplinger-novakovic@ginzinger.com>
Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> <martyna.szapar-mudlaw@intel.com>
Mathieu Othacehe <othacehe@gnu.org> <m.othacehe@gmail.com>
diff --git a/Documentation/scsi/leapraid.rst b/Documentation/scsi/leapraid.rst
index 99930ce2b8d0..d36ff627d9f0 100644
--- a/Documentation/scsi/leapraid.rst
+++ b/Documentation/scsi/leapraid.rst
@@ -22,6 +22,7 @@ Supported devices
Features
========
+
- PCIe Gen4 x8 host interface
- Support for SAS and SATA devices
- RAID levels: 0, 1, 10, 5, 50, 6, 60
@@ -50,16 +51,20 @@ LeapRAID specific disk attributes
::
- /sys/class/scsi_disk/host:bus:target:lun/device/sas_device_handle
- /sys/class/scsi_disk/host:bus:target:lun/device/ncq_cmd_prio_enable
+ /sys/block/<disk>/device/sas_device_handle
+ /sys/block/<disk>/device/sas_ncq_prio_supported
+ /sys/block/<disk>/device/sas_ncq_prio_enable
The read-only attribute "sas_device_handle" represents the disk's device
handle, which is a unique identifier maintained by the firmware.
-This attribute "ncq_cmd_prio_enable" controls NCQ command priority. A value
+The read-only attribute "sas_ncq_prio_supported" reports whether a SATA
+device supports NCQ command priority.
+
+The attribute "sas_ncq_prio_enable" controls NCQ command priority. A value
of 0 disables NCQ priority handling for RT-priority I/O. Writing 1 enables
NCQ priority handling when the device reports support for the feature through
-VPD page 0x89. Unsupported devices keep the effective state at 0.
+VPD page 0x89. Writes to unsupported devices fail with an error.
LeapRAID module parameters
==========================
@@ -100,6 +105,7 @@ in io_uring poll mode. The default value is 0.
File Location
=============
+
The driver source is located at:
``drivers/scsi/leapraid/``
diff --git a/MAINTAINERS b/MAINTAINERS
index 98c528c99917..3a19da74d00c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18776,8 +18776,6 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: Documentation/scsi/g_NCR5380.rst
F: drivers/scsi/NCR5380.*
-F: drivers/scsi/arm/cumana_1.c
-F: drivers/scsi/arm/oak.c
F: drivers/scsi/atari_scsi.*
F: drivers/scsi/dmx3191d.c
F: drivers/scsi/g_NCR5380.*
@@ -24571,7 +24569,7 @@ F: include/scsi/sg.h
SCSI SUBSYSTEM
M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
-M: "Martin K. Petersen" <martin.petersen@oracle.com>
+M: "Martin K. Petersen" <mkp@kernel.org>
L: linux-scsi@vger.kernel.org
S: Maintained
Q: https://patchwork.kernel.org/project/linux-scsi/list/
@@ -24601,7 +24599,7 @@ F: drivers/target/target_core_user.c
F: include/uapi/linux/target_core_user.h
SCSI TARGET SUBSYSTEM
-M: "Martin K. Petersen" <martin.petersen@oracle.com>
+M: "Martin K. Petersen" <mkp@kernel.org>
L: linux-scsi@vger.kernel.org
L: target-devel@vger.kernel.org
S: Supported
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),