SCSI fixes on 20240614

Three obvious driver fixes.  The two core fixes are to disable Command
 Duration Limits by default to fix an inconsistency in SATA and some
 USB devices.  The other is to change the default read size for block
 zero to follow the device preference (some USB bridges preferring 16
 byte commands don't have a translation for READ(10) and thus don't
 scan properly).
 
 Signed-off-by: James E.J. Bottomley <James.Bottomley@HansenParntership.com>
 -----BEGIN PGP SIGNATURE-----
 
 iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCZmw2AiYcamFtZXMuYm90
 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishUaKAQCeqrej
 +QoCHTaK7IJ8a5o8RmipBzU20GYG3+qew2Yu+QD+OvhSeGFLupgKuRYKemi+MI4r
 /19hMZ0N774tCWr/BDw=
 =0Al8
 -----END PGP SIGNATURE-----

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Three obvious driver fixes and two core fixes.

  The two core fixes are to disable Command Duration Limits by default
  to fix an inconsistency in SATA and some USB devices. The other is to
  change the default read size for block zero to follow the device
  preference (some USB bridges preferring 16 byte commands don't have a
  translation for READ(10) and thus don't scan properly)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: mpi3mr: Fix ATA NCQ priority support
  scsi: ufs: core: Quiesce request queues before checking pending cmds
  scsi: core: Disable CDL by default
  scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
  scsi: sd: Use READ(16) when reading block zero on large capacity disks
This commit is contained in:
Linus Torvalds 2024-06-14 10:25:29 -07:00
commit 0b320c8601
10 changed files with 130 additions and 36 deletions

View file

@ -2163,10 +2163,72 @@ persistent_id_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(persistent_id);
/**
* sas_ncq_prio_supported_show - Indicate if device supports NCQ priority
* @dev: pointer to embedded device
* @attr: sas_ncq_prio_supported attribute descriptor
* @buf: the buffer returned
*
* A sysfs 'read-only' sdev attribute, only works with SATA devices
*/
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 DEVICE_ATTR_RO(sas_ncq_prio_supported);
/**
* sas_ncq_prio_enable_show - send prioritized io commands to device
* @dev: pointer to embedded device
* @attr: sas_ncq_prio_enable attribute descriptor
* @buf: the buffer returned
*
* A sysfs 'read/write' sdev attribute, only works with SATA devices
*/
static ssize_t
sas_ncq_prio_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata;
if (!sdev_priv_data)
return 0;
return sysfs_emit(buf, "%d\n", sdev_priv_data->ncq_prio_enable);
}
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 mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata;
bool ncq_prio_enable = 0;
if (kstrtobool(buf, &ncq_prio_enable))
return -EINVAL;
if (!sas_ata_ncq_prio_supported(sdev))
return -EINVAL;
sdev_priv_data->ncq_prio_enable = ncq_prio_enable;
return strlen(buf);
}
static DEVICE_ATTR_RW(sas_ncq_prio_enable);
static struct attribute *mpi3mr_dev_attrs[] = {
&dev_attr_sas_address.attr,
&dev_attr_device_handle.attr,
&dev_attr_persistent_id.attr,
&dev_attr_sas_ncq_prio_supported.attr,
&dev_attr_sas_ncq_prio_enable.attr,
NULL,
};

View file

@ -8512,6 +8512,12 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
if (ioc->facts.MaxDevHandle % 8)
ioc->pd_handles_sz++;
/*
* pd_handles_sz should have, at least, the minimal room for
* set_bit()/test_bit(), otherwise out-of-memory touch may occur.
*/
ioc->pd_handles_sz = ALIGN(ioc->pd_handles_sz, sizeof(unsigned long));
ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
GFP_KERNEL);
if (!ioc->pd_handles) {
@ -8529,6 +8535,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle / 8);
if (ioc->facts.MaxDevHandle % 8)
ioc->pend_os_device_add_sz++;
/*
* pend_os_device_add_sz should have, at least, the minimal room for
* set_bit()/test_bit(), otherwise out-of-memory may occur.
*/
ioc->pend_os_device_add_sz = ALIGN(ioc->pend_os_device_add_sz,
sizeof(unsigned long));
ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
GFP_KERNEL);
if (!ioc->pend_os_device_add) {
@ -8820,6 +8833,12 @@ _base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc)
if (ioc->facts.MaxDevHandle % 8)
pd_handles_sz++;
/*
* pd_handles should have, at least, the minimal room for
* set_bit()/test_bit(), otherwise out-of-memory touch may
* occur.
*/
pd_handles_sz = ALIGN(pd_handles_sz, sizeof(unsigned long));
pd_handles = krealloc(ioc->pd_handles, pd_handles_sz,
GFP_KERNEL);
if (!pd_handles) {

View file

@ -2048,9 +2048,6 @@ void
mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
struct _raid_device *raid_device, Mpi25SCSIIORequest_t *mpi_request);
/* NCQ Prio Handling Check */
bool scsih_ncq_prio_supp(struct scsi_device *sdev);
void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_init_debugfs(void);

View file

@ -4088,7 +4088,7 @@ sas_ncq_prio_supported_show(struct device *dev,
{
struct scsi_device *sdev = to_scsi_device(dev);
return sysfs_emit(buf, "%d\n", scsih_ncq_prio_supp(sdev));
return sysfs_emit(buf, "%d\n", sas_ata_ncq_prio_supported(sdev));
}
static DEVICE_ATTR_RO(sas_ncq_prio_supported);
@ -4123,7 +4123,7 @@ sas_ncq_prio_enable_store(struct device *dev,
if (kstrtobool(buf, &ncq_prio_enable))
return -EINVAL;
if (!scsih_ncq_prio_supp(sdev))
if (!sas_ata_ncq_prio_supported(sdev))
return -EINVAL;
sas_device_priv_data->ncq_prio_enable = ncq_prio_enable;

View file

@ -12571,29 +12571,6 @@ scsih_pci_mmio_enabled(struct pci_dev *pdev)
return PCI_ERS_RESULT_RECOVERED;
}
/**
* scsih_ncq_prio_supp - Check for NCQ command priority support
* @sdev: scsi device struct
*
* This is called when a user indicates they would like to enable
* ncq command priorities. This works only on SATA devices.
*/
bool scsih_ncq_prio_supp(struct scsi_device *sdev)
{
struct scsi_vpd *vpd;
bool ncq_prio_supp = false;
rcu_read_lock();
vpd = rcu_dereference(sdev->vpd_pg89);
if (!vpd || vpd->len < 214)
goto out;
ncq_prio_supp = (vpd->data[213] >> 4) & 1;
out:
rcu_read_unlock();
return ncq_prio_supp;
}
/*
* The pci device ids are defined in mpi/mpi2_cnfg.h.
*/

View file

@ -673,6 +673,13 @@ void scsi_cdl_check(struct scsi_device *sdev)
sdev->use_10_for_rw = 0;
sdev->cdl_supported = 1;
/*
* If the device supports CDL, make sure that the current drive
* feature status is consistent with the user controlled
* cdl_enable state.
*/
scsi_cdl_enable(sdev, sdev->cdl_enable);
} else {
sdev->cdl_supported = 0;
}

View file

@ -416,6 +416,29 @@ unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
}
EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);
/**
* sas_ata_ncq_prio_supported - Check for ATA NCQ command priority support
* @sdev: SCSI device
*
* Check if an ATA device supports NCQ priority using VPD page 89h (ATA
* Information). Since this VPD page is implemented only for ATA devices,
* this function always returns false for SCSI devices.
*/
bool sas_ata_ncq_prio_supported(struct scsi_device *sdev)
{
struct scsi_vpd *vpd;
bool ncq_prio_supported = false;
rcu_read_lock();
vpd = rcu_dereference(sdev->vpd_pg89);
if (vpd && vpd->len >= 214)
ncq_prio_supported = (vpd->data[213] >> 4) & 1;
rcu_read_unlock();
return ncq_prio_supported;
}
EXPORT_SYMBOL_GPL(sas_ata_ncq_prio_supported);
/*
* SAS Phy attributes
*/

View file

@ -3565,16 +3565,23 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
static void sd_read_block_zero(struct scsi_disk *sdkp)
{
unsigned int buf_len = sdkp->device->sector_size;
char *buffer, cmd[10] = { };
struct scsi_device *sdev = sdkp->device;
unsigned int buf_len = sdev->sector_size;
u8 *buffer, cmd[16] = { };
buffer = kmalloc(buf_len, GFP_KERNEL);
if (!buffer)
return;
cmd[0] = READ_10;
put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */
put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */
if (sdev->use_16_for_rw) {
cmd[0] = READ_16;
put_unaligned_be64(0, &cmd[2]); /* Logical block address 0 */
put_unaligned_be32(1, &cmd[10]);/* Transfer 1 logical block */
} else {
cmd[0] = READ_10;
put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */
put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */
}
scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len,
SD_TIMEOUT, sdkp->max_retries, NULL);

View file

@ -1366,7 +1366,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
* make sure that there are no outstanding requests when
* clock scaling is in progress
*/
ufshcd_scsi_block_requests(hba);
blk_mq_quiesce_tagset(&hba->host->tag_set);
mutex_lock(&hba->wb_mutex);
down_write(&hba->clk_scaling_lock);
@ -1375,7 +1375,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
ret = -EBUSY;
up_write(&hba->clk_scaling_lock);
mutex_unlock(&hba->wb_mutex);
ufshcd_scsi_unblock_requests(hba);
blk_mq_unquiesce_tagset(&hba->host->tag_set);
goto out;
}
@ -1396,7 +1396,7 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool sc
mutex_unlock(&hba->wb_mutex);
ufshcd_scsi_unblock_requests(hba);
blk_mq_unquiesce_tagset(&hba->host->tag_set);
ufshcd_release(hba);
}

View file

@ -200,6 +200,8 @@ unsigned int sas_is_tlr_enabled(struct scsi_device *);
void sas_disable_tlr(struct scsi_device *);
void sas_enable_tlr(struct scsi_device *);
bool sas_ata_ncq_prio_supported(struct scsi_device *sdev);
extern struct sas_rphy *sas_end_device_alloc(struct sas_port *);
extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type);
void sas_rphy_free(struct sas_rphy *);