Commit e595ae7d authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

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: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 5fcc60dc c65c4360
Loading
Loading
Loading
Loading
+122 −38
Original line number Diff line number Diff line
@@ -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);

static ssize_t ata_ncq_prio_supported_show(struct device *device,
					   struct device_attribute *attr,
					   char *buf)
/**
 *	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 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;
	unsigned long flags;
	int rc = 0;

	spin_lock_irq(ap->lock);
	spin_lock_irqsave(ap->lock, flags);
	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);
		*supported = dev->flags & ATA_DFLAG_NCQ_PRIO;
	spin_unlock_irqrestore(ap->lock, flags);

	return rc ? rc : sysfs_emit(buf, "%u\n", ncq_prio_supported);
	return rc;
}
EXPORT_SYMBOL_GPL(ata_ncq_prio_supported);

DEVICE_ATTR(ncq_prio_supported, S_IRUGO, ata_ncq_prio_supported_show, NULL);
EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_supported);

static ssize_t ata_ncq_prio_enable_show(struct device *device,
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);
	bool supported;
	int rc;

	rc = ata_ncq_prio_supported(ap, sdev, &supported);
	if (rc)
		return rc;

	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;
	bool ncq_prio_enable;
	unsigned long flags;
	int rc = 0;

	spin_lock_irq(ap->lock);
	spin_lock_irqsave(ap->lock, flags);
	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);
		*enabled = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED;
	spin_unlock_irqrestore(ap->lock, flags);

	return rc ? rc : sysfs_emit(buf, "%u\n", ncq_prio_enable);
	return rc;
}
EXPORT_SYMBOL_GPL(ata_ncq_prio_enabled);

static ssize_t ata_ncq_prio_enable_store(struct device *device,
static ssize_t ata_ncq_prio_enable_show(struct device *device,
					struct device_attribute *attr,
					 const char *buf, size_t len)
					char *buf)
{
	struct scsi_device *sdev = to_scsi_device(device);
	struct ata_port *ap;
	struct ata_device *dev;
	long int input;
	int rc = 0;
	struct ata_port *ap = ata_shost_to_port(sdev->host);
	bool enabled;
	int rc;

	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);
	dev = ata_scsi_find_dev(ap, sdev);
	if (unlikely(!dev))
		return  -ENODEV;
	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);

	spin_lock_irq(ap->lock);
	dev = ata_scsi_find_dev(ap, sdev);
	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;
}
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 rc ? rc : len;
	return len;
}

DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR,
+8 −0
Original line number Diff line number Diff line
@@ -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,
+6 −0
Original line number Diff line number Diff line
@@ -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,
+6 −0
Original line number Diff line number Diff line
@@ -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,
+6 −0
Original line number Diff line number Diff line
@@ -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,
};

Loading