mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
Merge patch series "NCQ Priority sysfs sttributes for libsas"
Igor Pylypiv <ipylypiv@google.com> says: This patch series adds ncq_prio_supported and ncq_prio_enable sysfs attributes for libsas managed SATA devices. Existing libata sysfs attributes cannot be used directly because the ata_port location is different for libsas. Link: https://lore.kernel.org/r/20240307214418.3812290-1-ipylypiv@google.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
commit
e595ae7d07
@ -848,80 +848,143 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
|
||||
ata_scsi_lpm_show, ata_scsi_lpm_store);
|
||||
EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
|
||||
|
||||
/**
|
||||
* ata_ncq_prio_supported - Check if device supports NCQ Priority
|
||||
* @ap: ATA port of the target device
|
||||
* @sdev: SCSI device
|
||||
* @supported: Address of a boolean to store the result
|
||||
*
|
||||
* Helper to check if device supports NCQ Priority feature.
|
||||
*
|
||||
* Context: Any context. Takes and releases @ap->lock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - OK. Status is stored into @supported
|
||||
* * %-ENODEV - Failed to find the ATA device
|
||||
*/
|
||||
int ata_ncq_prio_supported(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool *supported)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (!dev)
|
||||
rc = -ENODEV;
|
||||
else
|
||||
*supported = dev->flags & ATA_DFLAG_NCQ_PRIO;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_ncq_prio_supported);
|
||||
|
||||
static ssize_t ata_ncq_prio_supported_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct ata_device *dev;
|
||||
bool ncq_prio_supported;
|
||||
int rc = 0;
|
||||
bool supported;
|
||||
int rc;
|
||||
|
||||
spin_lock_irq(ap->lock);
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (!dev)
|
||||
rc = -ENODEV;
|
||||
else
|
||||
ncq_prio_supported = dev->flags & ATA_DFLAG_NCQ_PRIO;
|
||||
spin_unlock_irq(ap->lock);
|
||||
rc = ata_ncq_prio_supported(ap, sdev, &supported);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc ? rc : sysfs_emit(buf, "%u\n", ncq_prio_supported);
|
||||
return sysfs_emit(buf, "%d\n", supported);
|
||||
}
|
||||
|
||||
DEVICE_ATTR(ncq_prio_supported, S_IRUGO, ata_ncq_prio_supported_show, NULL);
|
||||
EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_supported);
|
||||
|
||||
/**
|
||||
* ata_ncq_prio_enabled - Check if NCQ Priority is enabled
|
||||
* @ap: ATA port of the target device
|
||||
* @sdev: SCSI device
|
||||
* @enabled: Address of a boolean to store the result
|
||||
*
|
||||
* Helper to check if NCQ Priority feature is enabled.
|
||||
*
|
||||
* Context: Any context. Takes and releases @ap->lock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - OK. Status is stored into @enabled
|
||||
* * %-ENODEV - Failed to find the ATA device
|
||||
*/
|
||||
int ata_ncq_prio_enabled(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool *enabled)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (!dev)
|
||||
rc = -ENODEV;
|
||||
else
|
||||
*enabled = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_ncq_prio_enabled);
|
||||
|
||||
static ssize_t ata_ncq_prio_enable_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct ata_device *dev;
|
||||
bool ncq_prio_enable;
|
||||
int rc = 0;
|
||||
bool enabled;
|
||||
int rc;
|
||||
|
||||
spin_lock_irq(ap->lock);
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (!dev)
|
||||
rc = -ENODEV;
|
||||
else
|
||||
ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED;
|
||||
spin_unlock_irq(ap->lock);
|
||||
|
||||
return rc ? rc : sysfs_emit(buf, "%u\n", ncq_prio_enable);
|
||||
}
|
||||
|
||||
static ssize_t ata_ncq_prio_enable_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct ata_port *ap;
|
||||
struct ata_device *dev;
|
||||
long int input;
|
||||
int rc = 0;
|
||||
|
||||
rc = kstrtol(buf, 10, &input);
|
||||
rc = ata_ncq_prio_enabled(ap, sdev, &enabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
if ((input < 0) || (input > 1))
|
||||
return -EINVAL;
|
||||
|
||||
ap = ata_shost_to_port(sdev->host);
|
||||
return sysfs_emit(buf, "%d\n", enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_ncq_prio_enable - Enable/disable NCQ Priority
|
||||
* @ap: ATA port of the target device
|
||||
* @sdev: SCSI device
|
||||
* @enable: true - enable NCQ Priority, false - disable NCQ Priority
|
||||
*
|
||||
* Helper to enable/disable NCQ Priority feature.
|
||||
*
|
||||
* Context: Any context. Takes and releases @ap->lock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - OK. Status is stored into @enabled
|
||||
* * %-ENODEV - Failed to find the ATA device
|
||||
* * %-EINVAL - NCQ Priority is not supported or CDL is enabled
|
||||
*/
|
||||
int ata_ncq_prio_enable(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool enable)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (unlikely(!dev))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irq(ap->lock);
|
||||
if (!dev) {
|
||||
rc = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) {
|
||||
rc = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (input) {
|
||||
if (enable) {
|
||||
if (dev->flags & ATA_DFLAG_CDL_ENABLED) {
|
||||
ata_dev_err(dev,
|
||||
"CDL must be disabled to enable NCQ priority\n");
|
||||
@ -934,9 +997,30 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device,
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irq(ap->lock);
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
return rc ? rc : len;
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_ncq_prio_enable);
|
||||
|
||||
static ssize_t ata_ncq_prio_enable_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
bool enable;
|
||||
int rc;
|
||||
|
||||
rc = kstrtobool(buf, &enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = ata_ncq_prio_enable(ap, sdev, enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <scsi/sas_ata.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include "aic94xx.h"
|
||||
@ -34,6 +35,7 @@ MODULE_PARM_DESC(use_msi, "\n"
|
||||
static struct scsi_transport_template *aic94xx_transport_template;
|
||||
static int asd_scan_finished(struct Scsi_Host *, unsigned long);
|
||||
static void asd_scan_start(struct Scsi_Host *);
|
||||
static const struct attribute_group *asd_sdev_groups[];
|
||||
|
||||
static const struct scsi_host_template aic94xx_sht = {
|
||||
.module = THIS_MODULE,
|
||||
@ -60,6 +62,7 @@ static const struct scsi_host_template aic94xx_sht = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.track_queue_depth = 1,
|
||||
.sdev_groups = asd_sdev_groups,
|
||||
};
|
||||
|
||||
static int asd_map_memio(struct asd_ha_struct *asd_ha)
|
||||
@ -951,6 +954,11 @@ static void asd_remove_driver_attrs(struct device_driver *driver)
|
||||
driver_remove_file(driver, &driver_attr_version);
|
||||
}
|
||||
|
||||
static const struct attribute_group *asd_sdev_groups[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct sas_domain_function_template aic94xx_transport_functions = {
|
||||
.lldd_dev_found = asd_dev_found,
|
||||
.lldd_dev_gone = asd_dev_gone,
|
||||
|
@ -3544,6 +3544,11 @@ static struct attribute *host_v2_hw_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(host_v2_hw);
|
||||
|
||||
static const struct attribute_group *sdev_groups_v2_hw[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void map_queues_v2_hw(struct Scsi_Host *shost)
|
||||
{
|
||||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||
@ -3585,6 +3590,7 @@ static const struct scsi_host_template sht_v2_hw = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.shost_groups = host_v2_hw_groups,
|
||||
.sdev_groups = sdev_groups_v2_hw,
|
||||
.host_reset = hisi_sas_host_reset,
|
||||
.map_queues = map_queues_v2_hw,
|
||||
.host_tagset = 1,
|
||||
|
@ -2929,6 +2929,11 @@ static struct attribute *host_v3_hw_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(host_v3_hw);
|
||||
|
||||
static const struct attribute_group *sdev_groups_v3_hw[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define HISI_SAS_DEBUGFS_REG(x) {#x, x}
|
||||
|
||||
struct hisi_sas_debugfs_reg_lu {
|
||||
@ -3340,6 +3345,7 @@ static const struct scsi_host_template sht_v3_hw = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.shost_groups = host_v3_hw_groups,
|
||||
.sdev_groups = sdev_groups_v3_hw,
|
||||
.tag_alloc_policy = BLK_TAG_ALLOC_RR,
|
||||
.host_reset = hisi_sas_host_reset,
|
||||
.host_tagset = 1,
|
||||
|
@ -149,6 +149,11 @@ static struct attribute *isci_host_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(isci_host);
|
||||
|
||||
static const struct attribute_group *isci_sdev_groups[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct scsi_host_template isci_sht = {
|
||||
|
||||
.module = THIS_MODULE,
|
||||
@ -176,6 +181,7 @@ static const struct scsi_host_template isci_sht = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.shost_groups = isci_host_groups,
|
||||
.sdev_groups = isci_sdev_groups,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
|
@ -964,3 +964,85 @@ int sas_execute_ata_cmd(struct domain_device *device, u8 *fis, int force_phy_id)
|
||||
force_phy_id, &tmf_task);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sas_execute_ata_cmd);
|
||||
|
||||
static ssize_t sas_ncq_prio_supported_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct domain_device *ddev = sdev_to_domain_dev(sdev);
|
||||
bool supported;
|
||||
int rc;
|
||||
|
||||
rc = ata_ncq_prio_supported(ddev->sata_dev.ap, sdev, &supported);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", supported);
|
||||
}
|
||||
|
||||
DEVICE_ATTR(ncq_prio_supported, S_IRUGO, sas_ncq_prio_supported_show, NULL);
|
||||
|
||||
static ssize_t sas_ncq_prio_enable_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct domain_device *ddev = sdev_to_domain_dev(sdev);
|
||||
bool enabled;
|
||||
int rc;
|
||||
|
||||
rc = ata_ncq_prio_enabled(ddev->sata_dev.ap, sdev, &enabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", enabled);
|
||||
}
|
||||
|
||||
static ssize_t sas_ncq_prio_enable_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(device);
|
||||
struct domain_device *ddev = sdev_to_domain_dev(sdev);
|
||||
bool enable;
|
||||
int rc;
|
||||
|
||||
rc = kstrtobool(buf, &enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = ata_ncq_prio_enable(ddev->sata_dev.ap, sdev, enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR,
|
||||
sas_ncq_prio_enable_show, sas_ncq_prio_enable_store);
|
||||
|
||||
static struct attribute *sas_ata_sdev_attrs[] = {
|
||||
&dev_attr_ncq_prio_supported.attr,
|
||||
&dev_attr_ncq_prio_enable.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static umode_t sas_ata_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);
|
||||
struct domain_device *ddev = sdev_to_domain_dev(sdev);
|
||||
|
||||
if (!dev_is_sata(ddev))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
const struct attribute_group sas_ata_sdev_attr_group = {
|
||||
.attrs = sas_ata_sdev_attrs,
|
||||
.is_visible = sas_ata_attr_is_visible,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sas_ata_sdev_attr_group);
|
||||
|
@ -26,6 +26,7 @@ static const struct mvs_chip_info mvs_chips[] = {
|
||||
};
|
||||
|
||||
static const struct attribute_group *mvst_host_groups[];
|
||||
static const struct attribute_group *mvst_sdev_groups[];
|
||||
|
||||
#define SOC_SAS_NUM 2
|
||||
|
||||
@ -53,6 +54,7 @@ static const struct scsi_host_template mvs_sht = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.shost_groups = mvst_host_groups,
|
||||
.sdev_groups = mvst_sdev_groups,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
@ -779,6 +781,11 @@ static struct attribute *mvst_host_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(mvst_host);
|
||||
|
||||
static const struct attribute_group *mvst_sdev_groups[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
module_init(mvs_init);
|
||||
module_exit(mvs_exit);
|
||||
|
||||
|
@ -1039,3 +1039,8 @@ const struct attribute_group *pm8001_host_groups[] = {
|
||||
&pm8001_host_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct attribute_group *pm8001_sdev_groups[] = {
|
||||
&sas_ata_sdev_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
@ -134,6 +134,7 @@ static const struct scsi_host_template pm8001_sht = {
|
||||
.compat_ioctl = sas_ioctl,
|
||||
#endif
|
||||
.shost_groups = pm8001_host_groups,
|
||||
.sdev_groups = pm8001_sdev_groups,
|
||||
.track_queue_depth = 1,
|
||||
.cmd_per_lun = 32,
|
||||
.map_queues = pm8001_map_queues,
|
||||
|
@ -717,6 +717,7 @@ int pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha);
|
||||
void pm8001_free_dev(struct pm8001_device *pm8001_dev);
|
||||
/* ctl shared API */
|
||||
extern const struct attribute_group *pm8001_host_groups[];
|
||||
extern const struct attribute_group *pm8001_sdev_groups[];
|
||||
|
||||
#define PM8001_INVALID_TAG ((u32)-1)
|
||||
|
||||
|
@ -1157,6 +1157,12 @@ extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
||||
int queue_depth);
|
||||
extern int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
|
||||
int queue_depth);
|
||||
extern int ata_ncq_prio_supported(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool *supported);
|
||||
extern int ata_ncq_prio_enabled(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool *enabled);
|
||||
extern int ata_ncq_prio_enable(struct ata_port *ap, struct scsi_device *sdev,
|
||||
bool enable);
|
||||
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
||||
extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
|
||||
extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
|
||||
|
@ -39,6 +39,9 @@ int smp_ata_check_ready_type(struct ata_link *link);
|
||||
int sas_discover_sata(struct domain_device *dev);
|
||||
int sas_ata_add_dev(struct domain_device *parent, struct ex_phy *phy,
|
||||
struct domain_device *child, int phy_id);
|
||||
|
||||
extern const struct attribute_group sas_ata_sdev_attr_group;
|
||||
|
||||
#else
|
||||
|
||||
static inline void sas_ata_disabled_notice(void)
|
||||
@ -123,6 +126,9 @@ static inline int sas_ata_add_dev(struct domain_device *parent, struct ex_phy *p
|
||||
sas_ata_disabled_notice();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#define sas_ata_sdev_attr_group ((struct attribute_group) {})
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SAS_ATA_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user