summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-24 02:53:39 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-24 02:53:39 +0200
commite4f7bdc2ec0d0dcc27f7d70db27a620dfdc1f697 (patch)
treeb034d89f25c2403ca17eaa356cb37c2d1cb3b803 /drivers/scsi
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmo... (diff)
parentlibata: support host-aware and host-managed ZAC devices (diff)
downloadlinux-e4f7bdc2ec0d0dcc27f7d70db27a620dfdc1f697.tar.xz
linux-e4f7bdc2ec0d0dcc27f7d70db27a620dfdc1f697.zip
Merge branch 'for-4.7-zac' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata ZAC support from Tejun Heo: "This contains Zone ATA Command support for Shingled Magnetic Recording devices. In addition to sending the new commands down to the device, as ZAC commands depend on getting a lot of responses from the device, piping up responses is beefed up too. However, it doesn't involve changes to libata core mechanism or its interaction with upper layers, so I'm not expecting too many fallouts. Kudos to Hannes for driving SMR support" * 'for-4.7-zac' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: (28 commits) libata: support host-aware and host-managed ZAC devices libata: support device-managed ZAC devices libata: NCQ encapsulation for ZAC MANAGEMENT OUT libata: Implement ZBC OUT translation libata: implement ZBC IN translation libata: fixup ZAC device disabling libata-scsi: Generate sense code for disabled devices libata-trace: decode subcommands libata: Check log page directory before accessing pages libata: Add command definitions for NCQ Encapsulation for READ LOG DMA EXT libata: Separate out ata_dev_config_ncq_send_recv() libata/libsas: Define ATA_CMD_NCQ_NON_DATA libsas: enable FPDMA SEND/RECEIVE libata: do not attempt to retrieve sense code twice libata-scsi: Set information sense field for invalid parameter libata-scsi: set bit pointer for sense code information libata-scsi: Set field pointer in sense code scsi: add scsi_set_sense_field_pointer() libata: Implement control mode page to select sense format libata-scsi: generate correct ATA pass-through sense ...
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c3
-rw-r--r--drivers/scsi/isci/request.c5
-rw-r--r--drivers/scsi/libsas/sas_ata.c7
-rw-r--r--drivers/scsi/mvsas/mv_sas.c5
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c5
-rw-r--r--drivers/scsi/scsi_common.c53
-rw-r--r--drivers/scsi/scsi_error.c3
7 files changed, 75 insertions, 6 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index bbe98ecea0bc..bd20c5488768 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1630,6 +1630,9 @@ static u8 get_ata_protocol(u8 cmd, int direction)
switch (cmd) {
case ATA_CMD_FPDMA_WRITE:
case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_FPDMA_RECV:
+ case ATA_CMD_FPDMA_SEND:
+ case ATA_CMD_NCQ_NON_DATA:
return SATA_PROTOCOL_FPDMA;
case ATA_CMD_ID_ATA:
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index cfd0084f1cd2..b709d2b20880 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -3169,7 +3169,10 @@ static enum sci_status isci_request_stp_request_construct(struct isci_request *i
status = sci_io_request_construct_basic_sata(ireq);
if (qc && (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
- qc->tf.command == ATA_CMD_FPDMA_READ)) {
+ qc->tf.command == ATA_CMD_FPDMA_READ ||
+ qc->tf.command == ATA_CMD_FPDMA_RECV ||
+ qc->tf.command == ATA_CMD_FPDMA_SEND ||
+ qc->tf.command == ATA_CMD_NCQ_NON_DATA)) {
fis->sector_count = qc->tag << 3;
ireq->tc->type.stp.ncq_tag = qc->tag;
}
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 9c706d8c1441..935c43095109 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -205,7 +205,10 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
task->task_done = sas_ata_task_done;
if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
- qc->tf.command == ATA_CMD_FPDMA_READ) {
+ qc->tf.command == ATA_CMD_FPDMA_READ ||
+ qc->tf.command == ATA_CMD_FPDMA_RECV ||
+ qc->tf.command == ATA_CMD_FPDMA_SEND ||
+ qc->tf.command == ATA_CMD_NCQ_NON_DATA) {
/* Need to zero out the tag libata assigned us */
qc->tf.nsect = 0;
}
@@ -548,7 +551,7 @@ static struct ata_port_operations sas_sata_ops = {
static struct ata_port_info sata_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ |
- ATA_FLAG_SAS_HOST,
+ ATA_FLAG_SAS_HOST | ATA_FLAG_FPDMA_AUX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 83cd3ea2df41..5b9fcff6cd94 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -429,7 +429,10 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
if (qc) {
if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
- qc->tf.command == ATA_CMD_FPDMA_READ) {
+ qc->tf.command == ATA_CMD_FPDMA_READ ||
+ qc->tf.command == ATA_CMD_FPDMA_RECV ||
+ qc->tf.command == ATA_CMD_FPDMA_SEND ||
+ qc->tf.command == ATA_CMD_NCQ_NON_DATA) {
*tag = qc->tag;
return 1;
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 949198c01ced..dc33dfa8f994 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -280,7 +280,10 @@ u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag)
struct ata_queued_cmd *qc = task->uldd_task;
if (qc) {
if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
- qc->tf.command == ATA_CMD_FPDMA_READ) {
+ qc->tf.command == ATA_CMD_FPDMA_READ ||
+ qc->tf.command == ATA_CMD_FPDMA_RECV ||
+ qc->tf.command == ATA_CMD_FPDMA_SEND ||
+ qc->tf.command == ATA_CMD_NCQ_NON_DATA) {
*tag = qc->tag;
return 1;
}
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c
index ce79de822e46..b1383a71400e 100644
--- a/drivers/scsi/scsi_common.c
+++ b/drivers/scsi/scsi_common.c
@@ -293,3 +293,56 @@ int scsi_set_sense_information(u8 *buf, int buf_len, u64 info)
return 0;
}
EXPORT_SYMBOL(scsi_set_sense_information);
+
+/**
+ * scsi_set_sense_field_pointer - set the field pointer sense key
+ * specific information in a formatted sense data buffer
+ * @buf: Where to build sense data
+ * @buf_len: buffer length
+ * @fp: field pointer to be set
+ * @bp: bit pointer to be set
+ * @cd: command/data bit
+ *
+ * Return value:
+ * 0 on success or EINVAL for invalid sense buffer length
+ */
+int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd)
+{
+ u8 *ucp, len;
+
+ if ((buf[0] & 0x7f) == 0x72) {
+ len = buf[7];
+ ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2);
+ if (!ucp) {
+ buf[7] = len + 8;
+ ucp = buf + 8 + len;
+ }
+
+ if (buf_len < len + 8)
+ /* Not enough room for info */
+ return -EINVAL;
+
+ ucp[0] = 2;
+ ucp[1] = 6;
+ ucp[4] = 0x80; /* Valid bit */
+ if (cd)
+ ucp[4] |= 0x40;
+ if (bp < 0x8)
+ ucp[4] |= 0x8 | bp;
+ put_unaligned_be16(fp, &ucp[5]);
+ } else if ((buf[0] & 0x7f) == 0x70) {
+ len = buf[7];
+ if (len < 18)
+ buf[7] = 18;
+
+ buf[15] = 0x80;
+ if (cd)
+ buf[15] |= 0x40;
+ if (bp < 0x8)
+ buf[15] |= 0x8 | bp;
+ put_unaligned_be16(fp, &buf[16]);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(scsi_set_sense_field_pointer);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 984ddcb4786d..a8b610eaa0ca 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -452,7 +452,7 @@ static void scsi_report_sense(struct scsi_device *sdev,
* When a deferred error is detected the current command has
* not been executed and needs retrying.
*/
-static int scsi_check_sense(struct scsi_cmnd *scmd)
+int scsi_check_sense(struct scsi_cmnd *scmd)
{
struct scsi_device *sdev = scmd->device;
struct scsi_sense_hdr sshdr;
@@ -602,6 +602,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
return SUCCESS;
}
}
+EXPORT_SYMBOL_GPL(scsi_check_sense);
static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
{