Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: mpi3mr: Fix ATA NCQ priority support

The function mpi3mr_qcmd() of the mpi3mr driver is able to indicate to
the HBA if a read or write command directed at an ATA device should be
translated to an NCQ read/write command with the high prioiryt bit set
when the request uses the RT priority class and the user has enabled NCQ
priority through sysfs.

However, unlike the mpt3sas driver, the mpi3mr driver does not define
the sas_ncq_prio_supported and sas_ncq_prio_enable sysfs attributes, so
the ncq_prio_enable field of struct mpi3mr_sdev_priv_data is never
actually set and NCQ Priority cannot ever be used.

Fix this by defining these missing atributes to allow a user to check if
an ATA device supports NCQ priority and to enable/disable the use of NCQ
priority. To do this, lift the function scsih_ncq_prio_supp() out of the
mpt3sas driver and make it the generic SCSI SAS transport function
sas_ata_ncq_prio_supported(). Nothing in that function is hardware
specific, so this function can be used in both the mpt3sas driver and
the mpi3mr driver.

Reported-by: Scott McCoy <scott.mccoy@wdc.com>
Fixes: 023ab2a9b4ed ("scsi: mpi3mr: Add support for queue command processing")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20240611083435.92961-1-dlemoal@kernel.org
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Damien Le Moal and committed by
Martin K. Petersen
90e6f089 77691af4

+89 -28
+62
drivers/scsi/mpi3mr/mpi3mr_app.c
··· 2163 2163 } 2164 2164 static DEVICE_ATTR_RO(persistent_id); 2165 2165 2166 + /** 2167 + * sas_ncq_prio_supported_show - Indicate if device supports NCQ priority 2168 + * @dev: pointer to embedded device 2169 + * @attr: sas_ncq_prio_supported attribute descriptor 2170 + * @buf: the buffer returned 2171 + * 2172 + * A sysfs 'read-only' sdev attribute, only works with SATA devices 2173 + */ 2174 + static ssize_t 2175 + sas_ncq_prio_supported_show(struct device *dev, 2176 + struct device_attribute *attr, char *buf) 2177 + { 2178 + struct scsi_device *sdev = to_scsi_device(dev); 2179 + 2180 + return sysfs_emit(buf, "%d\n", sas_ata_ncq_prio_supported(sdev)); 2181 + } 2182 + static DEVICE_ATTR_RO(sas_ncq_prio_supported); 2183 + 2184 + /** 2185 + * sas_ncq_prio_enable_show - send prioritized io commands to device 2186 + * @dev: pointer to embedded device 2187 + * @attr: sas_ncq_prio_enable attribute descriptor 2188 + * @buf: the buffer returned 2189 + * 2190 + * A sysfs 'read/write' sdev attribute, only works with SATA devices 2191 + */ 2192 + static ssize_t 2193 + sas_ncq_prio_enable_show(struct device *dev, 2194 + struct device_attribute *attr, char *buf) 2195 + { 2196 + struct scsi_device *sdev = to_scsi_device(dev); 2197 + struct mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata; 2198 + 2199 + if (!sdev_priv_data) 2200 + return 0; 2201 + 2202 + return sysfs_emit(buf, "%d\n", sdev_priv_data->ncq_prio_enable); 2203 + } 2204 + 2205 + static ssize_t 2206 + sas_ncq_prio_enable_store(struct device *dev, 2207 + struct device_attribute *attr, 2208 + const char *buf, size_t count) 2209 + { 2210 + struct scsi_device *sdev = to_scsi_device(dev); 2211 + struct mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata; 2212 + bool ncq_prio_enable = 0; 2213 + 2214 + if (kstrtobool(buf, &ncq_prio_enable)) 2215 + return -EINVAL; 2216 + 2217 + if (!sas_ata_ncq_prio_supported(sdev)) 2218 + return -EINVAL; 2219 + 2220 + sdev_priv_data->ncq_prio_enable = ncq_prio_enable; 2221 + 2222 + return strlen(buf); 2223 + } 2224 + static DEVICE_ATTR_RW(sas_ncq_prio_enable); 2225 + 2166 2226 static struct attribute *mpi3mr_dev_attrs[] = { 2167 2227 &dev_attr_sas_address.attr, 2168 2228 &dev_attr_device_handle.attr, 2169 2229 &dev_attr_persistent_id.attr, 2230 + &dev_attr_sas_ncq_prio_supported.attr, 2231 + &dev_attr_sas_ncq_prio_enable.attr, 2170 2232 NULL, 2171 2233 }; 2172 2234
-3
drivers/scsi/mpt3sas/mpt3sas_base.h
··· 2048 2048 mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, 2049 2049 struct _raid_device *raid_device, Mpi25SCSIIORequest_t *mpi_request); 2050 2050 2051 - /* NCQ Prio Handling Check */ 2052 - bool scsih_ncq_prio_supp(struct scsi_device *sdev); 2053 - 2054 2051 void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc); 2055 2052 void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc); 2056 2053 void mpt3sas_init_debugfs(void);
+2 -2
drivers/scsi/mpt3sas/mpt3sas_ctl.c
··· 4088 4088 { 4089 4089 struct scsi_device *sdev = to_scsi_device(dev); 4090 4090 4091 - return sysfs_emit(buf, "%d\n", scsih_ncq_prio_supp(sdev)); 4091 + return sysfs_emit(buf, "%d\n", sas_ata_ncq_prio_supported(sdev)); 4092 4092 } 4093 4093 static DEVICE_ATTR_RO(sas_ncq_prio_supported); 4094 4094 ··· 4123 4123 if (kstrtobool(buf, &ncq_prio_enable)) 4124 4124 return -EINVAL; 4125 4125 4126 - if (!scsih_ncq_prio_supp(sdev)) 4126 + if (!sas_ata_ncq_prio_supported(sdev)) 4127 4127 return -EINVAL; 4128 4128 4129 4129 sas_device_priv_data->ncq_prio_enable = ncq_prio_enable;
-23
drivers/scsi/mpt3sas/mpt3sas_scsih.c
··· 12571 12571 return PCI_ERS_RESULT_RECOVERED; 12572 12572 } 12573 12573 12574 - /** 12575 - * scsih_ncq_prio_supp - Check for NCQ command priority support 12576 - * @sdev: scsi device struct 12577 - * 12578 - * This is called when a user indicates they would like to enable 12579 - * ncq command priorities. This works only on SATA devices. 12580 - */ 12581 - bool scsih_ncq_prio_supp(struct scsi_device *sdev) 12582 - { 12583 - struct scsi_vpd *vpd; 12584 - bool ncq_prio_supp = false; 12585 - 12586 - rcu_read_lock(); 12587 - vpd = rcu_dereference(sdev->vpd_pg89); 12588 - if (!vpd || vpd->len < 214) 12589 - goto out; 12590 - 12591 - ncq_prio_supp = (vpd->data[213] >> 4) & 1; 12592 - out: 12593 - rcu_read_unlock(); 12594 - 12595 - return ncq_prio_supp; 12596 - } 12597 12574 /* 12598 12575 * The pci device ids are defined in mpi/mpi2_cnfg.h. 12599 12576 */
+23
drivers/scsi/scsi_transport_sas.c
··· 416 416 } 417 417 EXPORT_SYMBOL_GPL(sas_is_tlr_enabled); 418 418 419 + /** 420 + * sas_ata_ncq_prio_supported - Check for ATA NCQ command priority support 421 + * @sdev: SCSI device 422 + * 423 + * Check if an ATA device supports NCQ priority using VPD page 89h (ATA 424 + * Information). Since this VPD page is implemented only for ATA devices, 425 + * this function always returns false for SCSI devices. 426 + */ 427 + bool sas_ata_ncq_prio_supported(struct scsi_device *sdev) 428 + { 429 + struct scsi_vpd *vpd; 430 + bool ncq_prio_supported = false; 431 + 432 + rcu_read_lock(); 433 + vpd = rcu_dereference(sdev->vpd_pg89); 434 + if (vpd && vpd->len >= 214) 435 + ncq_prio_supported = (vpd->data[213] >> 4) & 1; 436 + rcu_read_unlock(); 437 + 438 + return ncq_prio_supported; 439 + } 440 + EXPORT_SYMBOL_GPL(sas_ata_ncq_prio_supported); 441 + 419 442 /* 420 443 * SAS Phy attributes 421 444 */
+2
include/scsi/scsi_transport_sas.h
··· 200 200 void sas_disable_tlr(struct scsi_device *); 201 201 void sas_enable_tlr(struct scsi_device *); 202 202 203 + bool sas_ata_ncq_prio_supported(struct scsi_device *sdev); 204 + 203 205 extern struct sas_rphy *sas_end_device_alloc(struct sas_port *); 204 206 extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type); 205 207 void sas_rphy_free(struct sas_rphy *);