summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ipr.c85
-rw-r--r--drivers/scsi/ipr.h3
2 files changed, 88 insertions, 0 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index a9a464c728dd..3128407b407d 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -498,6 +498,10 @@ struct ipr_error_table_t ipr_error_table[] = {
"4061: Multipath redundancy level got better"},
{0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
"4060: Multipath redundancy level got worse"},
+ {0x06808100, 0, IPR_DEFAULT_LOG_LEVEL,
+ "9083: Device raw mode enabled"},
+ {0x06808200, 0, IPR_DEFAULT_LOG_LEVEL,
+ "9084: Device raw mode disabled"},
{0x07270000, 0, 0,
"Failure due to other device"},
{0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -4496,11 +4500,83 @@ static struct device_attribute ipr_resource_type_attr = {
.show = ipr_show_resource_type
};
+/**
+ * ipr_show_raw_mode - Show the adapter's raw mode
+ * @dev: class device struct
+ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_raw_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+ struct ipr_resource_entry *res;
+ unsigned long lock_flags = 0;
+ ssize_t len;
+
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ res = (struct ipr_resource_entry *)sdev->hostdata;
+ if (res)
+ len = snprintf(buf, PAGE_SIZE, "%d\n", res->raw_mode);
+ else
+ len = -ENXIO;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return len;
+}
+
+/**
+ * ipr_store_raw_mode - Change the adapter's raw mode
+ * @dev: class device struct
+ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+static ssize_t ipr_store_raw_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+ struct ipr_resource_entry *res;
+ unsigned long lock_flags = 0;
+ ssize_t len;
+
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ res = (struct ipr_resource_entry *)sdev->hostdata;
+ if (res) {
+ if (ioa_cfg->sis64 && ipr_is_af_dasd_device(res)) {
+ res->raw_mode = simple_strtoul(buf, NULL, 10);
+ len = strlen(buf);
+ if (res->sdev)
+ sdev_printk(KERN_INFO, res->sdev, "raw mode is %s\n",
+ res->raw_mode ? "enabled" : "disabled");
+ } else
+ len = -EINVAL;
+ } else
+ len = -ENXIO;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return len;
+}
+
+static struct device_attribute ipr_raw_mode_attr = {
+ .attr = {
+ .name = "raw_mode",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .show = ipr_show_raw_mode,
+ .store = ipr_store_raw_mode
+};
+
static struct device_attribute *ipr_dev_attrs[] = {
&ipr_adapter_handle_attr,
&ipr_resource_path_attr,
&ipr_device_id_attr,
&ipr_resource_type_attr,
+ &ipr_raw_mode_attr,
NULL,
};
@@ -6152,6 +6228,13 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
break;
case IPR_IOASC_NR_INIT_CMD_REQUIRED:
break;
+ case IPR_IOASC_IR_NON_OPTIMIZED:
+ if (res->raw_mode) {
+ res->raw_mode = 0;
+ scsi_cmd->result |= (DID_IMM_RETRY << 16);
+ } else
+ scsi_cmd->result |= (DID_ERROR << 16);
+ break;
default:
if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR)
scsi_cmd->result |= (DID_ERROR << 16);
@@ -6291,6 +6374,8 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
(!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) {
ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
}
+ if (res->raw_mode && ipr_is_af_dasd_device(res))
+ ioarcb->cmd_pkt.request_type = IPR_RQTYPE_PIPE;
if (ioa_cfg->sis64)
rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index f7d0e375e4f6..8d7547ffa953 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -138,6 +138,7 @@
#define IPR_IOASC_BUS_WAS_RESET 0x06290000
#define IPR_IOASC_BUS_WAS_RESET_BY_OTHER 0x06298000
#define IPR_IOASC_ABORTED_CMD_TERM_BY_HOST 0x0B5A0000
+#define IPR_IOASC_IR_NON_OPTIMIZED 0x05258200
#define IPR_FIRST_DRIVER_IOASC 0x10000000
#define IPR_IOASC_IOA_WAS_RESET 0x10000001
@@ -521,6 +522,7 @@ struct ipr_cmd_pkt {
#define IPR_RQTYPE_IOACMD 0x01
#define IPR_RQTYPE_HCAM 0x02
#define IPR_RQTYPE_ATA_PASSTHRU 0x04
+#define IPR_RQTYPE_PIPE 0x05
u8 reserved2;
@@ -1274,6 +1276,7 @@ struct ipr_resource_entry {
u8 del_from_ml:1;
u8 resetting_device:1;
u8 reset_occurred:1;
+ u8 raw_mode:1;
u32 bus; /* AKA channel */
u32 target; /* AKA id */