Skip to content

Commit 7adf8b1

Browse files
committed
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "Small drivers fixes, except for ufs which has two large updates, one for exposing the device level feature, which is a new addition to the device spec and the other reworking the exynos driver to fix coherence issues on some android phones" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: megaraid_sas: Driver version update to 07.734.00.00-rc1 scsi: megaraid_sas: Block zero-length ATA VPD inquiry scsi: scsi_transport_srp: Replace min/max nesting with clamp() scsi: ufs: core: Add device level exception support scsi: ufs: core: Rename ufshcd_wb_presrv_usrspc_keep_vcc_on() scsi: smartpqi: Use is_kdump_kernel() to check for kdump scsi: pm80xx: Set phy_attached to zero when device is gone scsi: ufs: exynos: gs101: Put UFS device in reset on .suspend() scsi: ufs: exynos: Move phy calls to .exit() callback scsi: ufs: exynos: Enable PRDT pre-fetching with UFSHCD_CAP_CRYPTO scsi: ufs: exynos: Ensure consistent phy reference counts scsi: ufs: exynos: Disable iocc if dma-coherent property isn't set scsi: ufs: exynos: Move UFS shareability value to drvdata scsi: ufs: exynos: Ensure pre_link() executes before exynos_ufs_phy_init() scsi: iscsi: Fix missing scsi_host_put() in error path scsi: ufs: core: Fix a race condition related to device commands scsi: hisi_sas: Fix I/O errors caused by hardware port ID changes scsi: hisi_sas: Enable force phy when SATA disk directly connected
2 parents ec4c6d1 + a1af6f1 commit 7adf8b1

18 files changed

+299
-67
lines changed

Documentation/ABI/testing/sysfs-driver-ufs

+32
Original file line numberDiff line numberDiff line change
@@ -1604,3 +1604,35 @@ Description:
16041604
prevent the UFS from frequently performing clock gating/ungating.
16051605

16061606
The attribute is read/write.
1607+
1608+
What: /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
1609+
What: /sys/bus/platform/devices/*.ufs/device_lvl_exception_count
1610+
Date: March 2025
1611+
Contact: Bao D. Nguyen <[email protected]>
1612+
Description:
1613+
This attribute is applicable to ufs devices compliant to the
1614+
JEDEC specifications version 4.1 or later. The
1615+
device_lvl_exception_count is a counter indicating the number of
1616+
times the device level exceptions have occurred since the last
1617+
time this variable is reset. Writing a 0 value to this
1618+
attribute will reset the device_lvl_exception_count. If the
1619+
device_lvl_exception_count reads a positive value, the user
1620+
application should read the device_lvl_exception_id attribute to
1621+
know more information about the exception.
1622+
1623+
The attribute is read/write.
1624+
1625+
What: /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id
1626+
What: /sys/bus/platform/devices/*.ufs/device_lvl_exception_id
1627+
Date: March 2025
1628+
Contact: Bao D. Nguyen <[email protected]>
1629+
Description:
1630+
Reading the device_lvl_exception_id returns the
1631+
qDeviceLevelExceptionID attribute of the ufs device JEDEC
1632+
specification version 4.1. The definition of the
1633+
qDeviceLevelExceptionID is the ufs device vendor specific
1634+
implementation. Refer to the device manufacturer datasheet for
1635+
more information on the meaning of the qDeviceLevelExceptionID
1636+
attribute value.
1637+
1638+
The attribute is read only.

drivers/scsi/hisi_sas/hisi_sas_main.c

+20
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,28 @@ static void hisi_sas_phyup_work_common(struct work_struct *work,
935935
container_of(work, typeof(*phy), works[event]);
936936
struct hisi_hba *hisi_hba = phy->hisi_hba;
937937
struct asd_sas_phy *sas_phy = &phy->sas_phy;
938+
struct asd_sas_port *sas_port = sas_phy->port;
939+
struct hisi_sas_port *port = phy->port;
940+
struct device *dev = hisi_hba->dev;
941+
struct domain_device *port_dev;
938942
int phy_no = sas_phy->id;
939943

944+
if (!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags) &&
945+
sas_port && port && (port->id != phy->port_id)) {
946+
dev_info(dev, "phy%d's hw port id changed from %d to %llu\n",
947+
phy_no, port->id, phy->port_id);
948+
port_dev = sas_port->port_dev;
949+
if (port_dev && !dev_is_expander(port_dev->dev_type)) {
950+
/*
951+
* Set the device state to gone to block
952+
* sending IO to the device.
953+
*/
954+
set_bit(SAS_DEV_GONE, &port_dev->state);
955+
hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
956+
return;
957+
}
958+
}
959+
940960
phy->wait_phyup_cnt = 0;
941961
if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP)
942962
hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no);

drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -2501,17 +2501,22 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
25012501
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
25022502
struct sas_ata_task *ata_task = &task->ata_task;
25032503
struct sas_tmf_task *tmf = slot->tmf;
2504+
int phy_id;
25042505
u8 *buf_cmd;
25052506
int has_data = 0, hdr_tag = 0;
25062507
u32 dw0, dw1 = 0, dw2 = 0;
25072508

25082509
/* create header */
25092510
/* dw0 */
25102511
dw0 = port->id << CMD_HDR_PORT_OFF;
2511-
if (parent_dev && dev_is_expander(parent_dev->dev_type))
2512+
if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
25122513
dw0 |= 3 << CMD_HDR_CMD_OFF;
2513-
else
2514+
} else {
2515+
phy_id = device->phy->identify.phy_identifier;
2516+
dw0 |= (1U << phy_id) << CMD_HDR_PHY_ID_OFF;
2517+
dw0 |= CMD_HDR_FORCE_PHY_MSK;
25142518
dw0 |= 4 << CMD_HDR_CMD_OFF;
2519+
}
25152520

25162521
if (tmf && ata_task->force_phy) {
25172522
dw0 |= CMD_HDR_FORCE_PHY_MSK;

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@
359359
#define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
360360
#define CMD_HDR_TLR_CTRL_OFF 6
361361
#define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF)
362+
#define CMD_HDR_PHY_ID_OFF 8
363+
#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF)
364+
#define CMD_HDR_FORCE_PHY_OFF 17
365+
#define CMD_HDR_FORCE_PHY_MSK (0x1U << CMD_HDR_FORCE_PHY_OFF)
362366
#define CMD_HDR_PORT_OFF 18
363367
#define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF)
364368
#define CMD_HDR_PRIORITY_OFF 27
@@ -1429,15 +1433,21 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
14291433
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
14301434
struct asd_sas_port *sas_port = device->port;
14311435
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
1436+
int phy_id;
14321437
u8 *buf_cmd;
14331438
int has_data = 0, hdr_tag = 0;
14341439
u32 dw1 = 0, dw2 = 0;
14351440

14361441
hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
1437-
if (parent_dev && dev_is_expander(parent_dev->dev_type))
1442+
if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
14381443
hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
1439-
else
1444+
} else {
1445+
phy_id = device->phy->identify.phy_identifier;
1446+
hdr->dw0 |= cpu_to_le32((1U << phy_id)
1447+
<< CMD_HDR_PHY_ID_OFF);
1448+
hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
14401449
hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF);
1450+
}
14411451

14421452
switch (task->data_dir) {
14431453
case DMA_TO_DEVICE:

drivers/scsi/megaraid/megaraid_sas.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
/*
2424
* MegaRAID SAS Driver meta data
2525
*/
26-
#define MEGASAS_VERSION "07.727.03.00-rc1"
27-
#define MEGASAS_RELDATE "Oct 03, 2023"
26+
#define MEGASAS_VERSION "07.734.00.00-rc1"
27+
#define MEGASAS_RELDATE "Apr 03, 2025"
2828

2929
#define MEGASAS_MSIX_NAME_LEN 32
3030

drivers/scsi/megaraid/megaraid_sas_base.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -2103,6 +2103,9 @@ static int megasas_sdev_configure(struct scsi_device *sdev,
21032103
/* This sdev property may change post OCR */
21042104
megasas_set_dynamic_target_properties(sdev, lim, is_target_prop);
21052105

2106+
if (!MEGASAS_IS_LOGICAL(sdev))
2107+
sdev->no_vpd_size = 1;
2108+
21062109
mutex_unlock(&instance->reset_mutex);
21072110

21082111
return 0;
@@ -3662,8 +3665,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
36623665

36633666
case MFI_STAT_SCSI_IO_FAILED:
36643667
case MFI_STAT_LD_INIT_IN_PROGRESS:
3665-
cmd->scmd->result =
3666-
(DID_ERROR << 16) | hdr->scsi_status;
3668+
if (hdr->scsi_status == 0xf0)
3669+
cmd->scmd->result = (DID_ERROR << 16) | SAM_STAT_CHECK_CONDITION;
3670+
else
3671+
cmd->scmd->result = (DID_ERROR << 16) | hdr->scsi_status;
36673672
break;
36683673

36693674
case MFI_STAT_SCSI_DONE_WITH_ERROR:

drivers/scsi/megaraid/megaraid_sas_fusion.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,10 @@ map_cmd_status(struct fusion_context *fusion,
20432043

20442044
case MFI_STAT_SCSI_IO_FAILED:
20452045
case MFI_STAT_LD_INIT_IN_PROGRESS:
2046-
scmd->result = (DID_ERROR << 16) | ext_status;
2046+
if (ext_status == 0xf0)
2047+
scmd->result = (DID_ERROR << 16) | SAM_STAT_CHECK_CONDITION;
2048+
else
2049+
scmd->result = (DID_ERROR << 16) | ext_status;
20472050
break;
20482051

20492052
case MFI_STAT_SCSI_DONE_WITH_ERROR:

drivers/scsi/pm8001/pm8001_sas.c

+1
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)
766766
spin_lock_irqsave(&pm8001_ha->lock, flags);
767767
}
768768
PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id);
769+
pm8001_ha->phy[pm8001_dev->attached_phy].phy_attached = 0;
769770
pm8001_free_dev(pm8001_dev);
770771
} else {
771772
pm8001_dbg(pm8001_ha, DISC, "Found dev has gone.\n");

drivers/scsi/scsi_transport_iscsi.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -3182,11 +3182,14 @@ iscsi_set_host_param(struct iscsi_transport *transport,
31823182
}
31833183

31843184
/* see similar check in iscsi_if_set_param() */
3185-
if (strlen(data) > ev->u.set_host_param.len)
3186-
return -EINVAL;
3185+
if (strlen(data) > ev->u.set_host_param.len) {
3186+
err = -EINVAL;
3187+
goto out;
3188+
}
31873189

31883190
err = transport->set_host_param(shost, ev->u.set_host_param.param,
31893191
data, ev->u.set_host_param.len);
3192+
out:
31903193
scsi_host_put(shost);
31913194
return err;
31923195
}

drivers/scsi/scsi_transport_srp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ static void srp_reconnect_work(struct work_struct *work)
388388
"reconnect attempt %d failed (%d)\n",
389389
++rport->failed_reconnects, res);
390390
delay = rport->reconnect_delay *
391-
min(100, max(1, rport->failed_reconnects - 10));
391+
clamp(rport->failed_reconnects - 10, 1, 100);
392392
if (delay > 0)
393393
queue_delayed_work(system_long_wq,
394394
&rport->reconnect_work, delay * HZ);

drivers/scsi/smartpqi/smartpqi_init.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/bcd.h>
2020
#include <linux/reboot.h>
2121
#include <linux/cciss_ioctl.h>
22+
#include <linux/crash_dump.h>
2223
#include <scsi/scsi_host.h>
2324
#include <scsi/scsi_cmnd.h>
2425
#include <scsi/scsi_device.h>
@@ -5246,7 +5247,7 @@ static void pqi_calculate_io_resources(struct pqi_ctrl_info *ctrl_info)
52465247
ctrl_info->error_buffer_length =
52475248
ctrl_info->max_io_slots * PQI_ERROR_BUFFER_ELEMENT_LENGTH;
52485249

5249-
if (reset_devices)
5250+
if (is_kdump_kernel())
52505251
max_transfer_size = min(ctrl_info->max_transfer_size,
52515252
PQI_MAX_TRANSFER_SIZE_KDUMP);
52525253
else
@@ -5275,7 +5276,7 @@ static void pqi_calculate_queue_resources(struct pqi_ctrl_info *ctrl_info)
52755276
u16 num_elements_per_iq;
52765277
u16 num_elements_per_oq;
52775278

5278-
if (reset_devices) {
5279+
if (is_kdump_kernel()) {
52795280
num_queue_groups = 1;
52805281
} else {
52815282
int num_cpus;
@@ -8288,12 +8289,12 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
82888289
u32 product_id;
82898290

82908291
if (reset_devices) {
8291-
if (pqi_is_fw_triage_supported(ctrl_info)) {
8292+
if (is_kdump_kernel() && pqi_is_fw_triage_supported(ctrl_info)) {
82928293
rc = sis_wait_for_fw_triage_completion(ctrl_info);
82938294
if (rc)
82948295
return rc;
82958296
}
8296-
if (sis_is_ctrl_logging_supported(ctrl_info)) {
8297+
if (is_kdump_kernel() && sis_is_ctrl_logging_supported(ctrl_info)) {
82978298
sis_notify_kdump(ctrl_info);
82988299
rc = sis_wait_for_ctrl_logging_completion(ctrl_info);
82998300
if (rc)
@@ -8344,7 +8345,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
83448345
ctrl_info->product_id = (u8)product_id;
83458346
ctrl_info->product_revision = (u8)(product_id >> 8);
83468347

8347-
if (reset_devices) {
8348+
if (is_kdump_kernel()) {
83488349
if (ctrl_info->max_outstanding_requests >
83498350
PQI_MAX_OUTSTANDING_REQUESTS_KDUMP)
83508351
ctrl_info->max_outstanding_requests =
@@ -8480,7 +8481,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
84808481
if (rc)
84818482
return rc;
84828483

8483-
if (ctrl_info->ctrl_logging_supported && !reset_devices) {
8484+
if (ctrl_info->ctrl_logging_supported && !is_kdump_kernel()) {
84848485
pqi_host_setup_buffer(ctrl_info, &ctrl_info->ctrl_log_memory, PQI_CTRL_LOG_TOTAL_SIZE, PQI_CTRL_LOG_MIN_SIZE);
84858486
pqi_host_memory_update(ctrl_info, &ctrl_info->ctrl_log_memory, PQI_VENDOR_GENERAL_CTRL_LOG_MEMORY_UPDATE);
84868487
}

drivers/ufs/core/ufs-sysfs.c

+54
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,56 @@ static ssize_t critical_health_show(struct device *dev,
466466
return sysfs_emit(buf, "%d\n", hba->critical_health_count);
467467
}
468468

469+
static ssize_t device_lvl_exception_count_show(struct device *dev,
470+
struct device_attribute *attr,
471+
char *buf)
472+
{
473+
struct ufs_hba *hba = dev_get_drvdata(dev);
474+
475+
if (hba->dev_info.wspecversion < 0x410)
476+
return -EOPNOTSUPP;
477+
478+
return sysfs_emit(buf, "%u\n", atomic_read(&hba->dev_lvl_exception_count));
479+
}
480+
481+
static ssize_t device_lvl_exception_count_store(struct device *dev,
482+
struct device_attribute *attr,
483+
const char *buf, size_t count)
484+
{
485+
struct ufs_hba *hba = dev_get_drvdata(dev);
486+
unsigned int value;
487+
488+
if (kstrtouint(buf, 0, &value))
489+
return -EINVAL;
490+
491+
/* the only supported usecase is to reset the dev_lvl_exception_count */
492+
if (value)
493+
return -EINVAL;
494+
495+
atomic_set(&hba->dev_lvl_exception_count, 0);
496+
497+
return count;
498+
}
499+
500+
static ssize_t device_lvl_exception_id_show(struct device *dev,
501+
struct device_attribute *attr,
502+
char *buf)
503+
{
504+
struct ufs_hba *hba = dev_get_drvdata(dev);
505+
u64 exception_id;
506+
int err;
507+
508+
ufshcd_rpm_get_sync(hba);
509+
err = ufshcd_read_device_lvl_exception_id(hba, &exception_id);
510+
ufshcd_rpm_put_sync(hba);
511+
512+
if (err)
513+
return err;
514+
515+
hba->dev_lvl_exception_id = exception_id;
516+
return sysfs_emit(buf, "%llu\n", exception_id);
517+
}
518+
469519
static DEVICE_ATTR_RW(rpm_lvl);
470520
static DEVICE_ATTR_RO(rpm_target_dev_state);
471521
static DEVICE_ATTR_RO(rpm_target_link_state);
@@ -479,6 +529,8 @@ static DEVICE_ATTR_RW(wb_flush_threshold);
479529
static DEVICE_ATTR_RW(rtc_update_ms);
480530
static DEVICE_ATTR_RW(pm_qos_enable);
481531
static DEVICE_ATTR_RO(critical_health);
532+
static DEVICE_ATTR_RW(device_lvl_exception_count);
533+
static DEVICE_ATTR_RO(device_lvl_exception_id);
482534

483535
static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
484536
&dev_attr_rpm_lvl.attr,
@@ -494,6 +546,8 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
494546
&dev_attr_rtc_update_ms.attr,
495547
&dev_attr_pm_qos_enable.attr,
496548
&dev_attr_critical_health.attr,
549+
&dev_attr_device_lvl_exception_count.attr,
550+
&dev_attr_device_lvl_exception_id.attr,
497551
NULL
498552
};
499553

drivers/ufs/core/ufshcd-priv.h

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
9494
enum query_opcode desc_op);
9595

9696
int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
97+
int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id);
9798

9899
/* Wrapper functions for safely calling variant operations */
99100
static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)

0 commit comments

Comments
 (0)