Commit da0697bd authored by Scott Teel's avatar Scott Teel Committed by James Bottomley

[SCSI] hpsa: allow user to disable accelerated i/o path

Allow SSD Smart Path for a controller to be disabled by
the user, regardless of settings in controller firmware
or array configuration.

To disable:     echo 0 > /sys/class/scsi_host/host<id>/acciopath_status
To re-enable:   echo 1 > /sys/class/scsi_host/host<id>/acciopath_status
To check state: cat /sys/class/scsi_host/host<id>/acciopath_status
Signed-off-by: default avatarScott Teel <scott.teel@hp.com>
Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6b80b18f
...@@ -11,3 +11,19 @@ Description: ...@@ -11,3 +11,19 @@ Description:
guaranteed. The 'isci_id' attribute unambiguously identifies guaranteed. The 'isci_id' attribute unambiguously identifies
the controller index: '0' for the first controller, the controller index: '0' for the first controller,
'1' for the second. '1' for the second.
What: /sys/class/scsi_host/hostX/acciopath_status
Date: November 2013
Contact: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Description: This file contains the current status of the "SSD Smart Path"
feature of HP Smart Array RAID controllers using the hpsa
driver. SSD Smart Path, when enabled permits the driver to
send i/o requests directly to physical devices that are part
of a logical drive, bypassing the controllers firmware RAID
stack for a performance advantage when possible. A value of
'1' indicates the feature is enabled, and the controller may
use the direct i/o path to physical devices. A value of zero
means the feature is disabled and the controller may not use
the direct i/o path to physical devices. This setting is
controller wide, affecting all configured logical drives on the
controller. This file is readable and writable.
...@@ -287,6 +287,30 @@ static int check_for_busy(struct ctlr_info *h, struct CommandList *c) ...@@ -287,6 +287,30 @@ static int check_for_busy(struct ctlr_info *h, struct CommandList *c)
return 1; return 1;
} }
static ssize_t host_store_hp_ssd_smart_path_status(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int status, len;
struct ctlr_info *h;
struct Scsi_Host *shost = class_to_shost(dev);
char tmpbuf[10];
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
len = count > sizeof(tmpbuf) - 1 ? sizeof(tmpbuf) - 1 : count;
strncpy(tmpbuf, buf, len);
tmpbuf[len] = '\0';
if (sscanf(tmpbuf, "%d", &status) != 1)
return -EINVAL;
h = shost_to_hba(shost);
h->acciopath_status = !!status;
dev_warn(&h->pdev->dev,
"hpsa: HP SSD Smart Path %s via sysfs update.\n",
h->acciopath_status ? "enabled" : "disabled");
return count;
}
static ssize_t host_store_rescan(struct device *dev, static ssize_t host_store_rescan(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -334,6 +358,17 @@ static ssize_t host_show_transport_mode(struct device *dev, ...@@ -334,6 +358,17 @@ static ssize_t host_show_transport_mode(struct device *dev,
"performant" : "simple"); "performant" : "simple");
} }
static ssize_t host_show_hp_ssd_smart_path_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ctlr_info *h;
struct Scsi_Host *shost = class_to_shost(dev);
h = shost_to_hba(shost);
return snprintf(buf, 30, "HP SSD Smart Path %s\n",
(h->acciopath_status == 1) ? "enabled" : "disabled");
}
/* List of controllers which cannot be hard reset on kexec with reset_devices */ /* List of controllers which cannot be hard reset on kexec with reset_devices */
static u32 unresettable_controller[] = { static u32 unresettable_controller[] = {
0x324a103C, /* Smart Array P712m */ 0x324a103C, /* Smart Array P712m */
...@@ -546,6 +581,9 @@ static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); ...@@ -546,6 +581,9 @@ static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO, static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO,
host_show_hp_ssd_smart_path_enabled, NULL); host_show_hp_ssd_smart_path_enabled, NULL);
static DEVICE_ATTR(hp_ssd_smart_path_status, S_IWUSR|S_IRUGO|S_IROTH,
host_show_hp_ssd_smart_path_status,
host_store_hp_ssd_smart_path_status);
static DEVICE_ATTR(firmware_revision, S_IRUGO, static DEVICE_ATTR(firmware_revision, S_IRUGO,
host_show_firmware_revision, NULL); host_show_firmware_revision, NULL);
static DEVICE_ATTR(commands_outstanding, S_IRUGO, static DEVICE_ATTR(commands_outstanding, S_IRUGO,
...@@ -569,6 +607,7 @@ static struct device_attribute *hpsa_shost_attrs[] = { ...@@ -569,6 +607,7 @@ static struct device_attribute *hpsa_shost_attrs[] = {
&dev_attr_commands_outstanding, &dev_attr_commands_outstanding,
&dev_attr_transport_mode, &dev_attr_transport_mode,
&dev_attr_resettable, &dev_attr_resettable,
&dev_attr_hp_ssd_smart_path_status,
NULL, NULL,
}; };
...@@ -3341,7 +3380,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd, ...@@ -3341,7 +3380,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
* Retries always go down the normal I/O path. * Retries always go down the normal I/O path.
*/ */
if (likely(cmd->retries == 0 && if (likely(cmd->retries == 0 &&
cmd->request->cmd_type == REQ_TYPE_FS)) { cmd->request->cmd_type == REQ_TYPE_FS &&
h->acciopath_status)) {
if (dev->offload_enabled) { if (dev->offload_enabled) {
rc = hpsa_scsi_ioaccel_raid_map(h, c); rc = hpsa_scsi_ioaccel_raid_map(h, c);
if (rc == 0) if (rc == 0)
...@@ -6326,6 +6366,9 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -6326,6 +6366,9 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto reinit_after_soft_reset; goto reinit_after_soft_reset;
} }
/* Enable Accelerated IO path at driver layer */
h->acciopath_status = 1;
/* Turn the interrupts on so we can service requests */ /* Turn the interrupts on so we can service requests */
h->access.set_intr_mask(h, HPSA_INTR_ON); h->access.set_intr_mask(h, HPSA_INTR_ON);
......
...@@ -181,6 +181,7 @@ struct ctlr_info { ...@@ -181,6 +181,7 @@ struct ctlr_info {
#define HPSATMF_LOG_QRY_TSET (1 << 24) #define HPSATMF_LOG_QRY_TSET (1 << 24)
#define HPSATMF_LOG_QRY_ASYNC (1 << 25) #define HPSATMF_LOG_QRY_ASYNC (1 << 25)
u32 events; u32 events;
int acciopath_status;
}; };
#define HPSA_ABORT_MSG 0 #define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1 #define HPSA_DEVICE_RESET_MSG 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment