summaryrefslogtreecommitdiff
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c544
1 files changed, 180 insertions, 364 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 15795394b0a8..3ce43920e459 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -49,7 +49,11 @@
#include "libata.h"
-#define SECTOR_SIZE 512
+#define SECTOR_SIZE 512
+#define ATA_SCSI_RBUF_SIZE 4096
+
+static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
+static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
@@ -131,10 +135,11 @@ static const char *ata_scsi_lpm_get(enum link_pm policy)
return NULL;
}
-static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
- const char *buf, size_t count)
+static ssize_t ata_scsi_lpm_put(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ata_port *ap = ata_shost_to_port(shost);
enum link_pm policy = 0;
int i;
@@ -162,9 +167,9 @@ static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
}
static ssize_t
-ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
+ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ata_port *ap = ata_shost_to_port(shost);
const char *policy =
ata_scsi_lpm_get(ap->pm_policy);
@@ -174,9 +179,16 @@ ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
return snprintf(buf, 23, "%s\n", policy);
}
-CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
ata_scsi_lpm_show, ata_scsi_lpm_put);
-EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
+EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
+
+static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+ scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
+}
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
@@ -1631,53 +1643,48 @@ defer:
/**
* ata_scsi_rbuf_get - Map response buffer.
- * @cmd: SCSI command containing buffer to be mapped.
- * @buf_out: Pointer to mapped area.
+ * @flags: unsigned long variable to store irq enable status
+ * @copy_in: copy in from user buffer
*
- * Maps buffer contained within SCSI command @cmd.
+ * Prepare buffer for simulated SCSI commands.
*
* LOCKING:
- * spin_lock_irqsave(host lock)
+ * spin_lock_irqsave(ata_scsi_rbuf_lock) on success
*
* RETURNS:
- * Length of response buffer.
+ * Pointer to response buffer.
*/
-
-static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
+static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
+ unsigned long *flags)
{
- u8 *buf;
- unsigned int buflen;
+ spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);
- struct scatterlist *sg = scsi_sglist(cmd);
-
- if (sg) {
- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
- buflen = sg->length;
- } else {
- buf = NULL;
- buflen = 0;
- }
-
- *buf_out = buf;
- return buflen;
+ memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
+ if (copy_in)
+ sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+ ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+ return ata_scsi_rbuf;
}
/**
* ata_scsi_rbuf_put - Unmap response buffer.
* @cmd: SCSI command containing buffer to be unmapped.
- * @buf: buffer to unmap
+ * @copy_out: copy out result
+ * @flags: @flags passed to ata_scsi_rbuf_get()
*
- * Unmaps response buffer contained within @cmd.
+ * Returns rbuf buffer. The result is copied to @cmd's buffer if
+ * @copy_back is true.
*
* LOCKING:
- * spin_lock_irqsave(host lock)
+ * Unlocks ata_scsi_rbuf_lock.
*/
-
-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
+ unsigned long *flags)
{
- struct scatterlist *sg = scsi_sglist(cmd);
- if (sg)
- kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ if (copy_out)
+ sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+ ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+ spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
}
/**
@@ -1695,24 +1702,17 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
- unsigned int (*actor) (struct ata_scsi_args *args,
- u8 *rbuf, unsigned int buflen))
+static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+ unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
{
u8 *rbuf;
- unsigned int buflen, rc;
+ unsigned int rc;
struct scsi_cmnd *cmd = args->cmd;
unsigned long flags;
- local_irq_save(flags);
-
- buflen = ata_scsi_rbuf_get(cmd, &rbuf);
- memset(rbuf, 0, buflen);
- rc = actor(args, rbuf, buflen);
- ata_scsi_rbuf_put(cmd, rbuf);
-
- local_irq_restore(flags);
+ rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
+ rc = actor(args, rbuf);
+ ata_scsi_rbuf_put(cmd, rc == 0, &flags);
if (rc == 0)
cmd->result = SAM_STAT_GOOD;
@@ -1720,26 +1720,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
}
/**
- * ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
- * @idx: byte index into SCSI response buffer
- * @val: value to set
- *
- * To be used by SCSI command simulator functions. This macros
- * expects two local variables, u8 *rbuf and unsigned int buflen,
- * are in scope.
- *
- * LOCKING:
- * None.
- */
-#define ATA_SCSI_RBUF_SET(idx, val) do { \
- if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
- } while (0)
-
-/**
* ata_scsiop_inq_std - Simulate INQUIRY command
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Returns standard device identification data associated
* with non-VPD INQUIRY command output.
@@ -1747,10 +1730,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
{
+ const u8 versions[] = {
+ 0x60, /* SAM-3 (no version claimed) */
+
+ 0x03,
+ 0x20, /* SBC-2 (no version claimed) */
+
+ 0x02,
+ 0x60 /* SPC-3 (no version claimed) */
+ };
u8 hdr[] = {
TYPE_DISK,
0,
@@ -1759,35 +1749,21 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
95 - 4
};
+ VPRINTK("ENTER\n");
+
/* set scsi removeable (RMB) bit per ata bit */
if (ata_id_removeable(args->id))
hdr[1] |= (1 << 7);
- VPRINTK("ENTER\n");
-
memcpy(rbuf, hdr, sizeof(hdr));
+ memcpy(&rbuf[8], "ATA ", 8);
+ ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+ ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
- if (buflen > 35) {
- memcpy(&rbuf[8], "ATA ", 8);
- ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
- ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
- if (rbuf[32] == 0 || rbuf[32] == ' ')
- memcpy(&rbuf[32], "n/a ", 4);
- }
-
- if (buflen > 63) {
- const u8 versions[] = {
- 0x60, /* SAM-3 (no version claimed) */
-
- 0x03,
- 0x20, /* SBC-2 (no version claimed) */
+ if (rbuf[32] == 0 || rbuf[32] == ' ')
+ memcpy(&rbuf[32], "n/a ", 4);
- 0x02,
- 0x60 /* SPC-3 (no version claimed) */
- };
-
- memcpy(rbuf + 59, versions, sizeof(versions));
- }
+ memcpy(rbuf + 59, versions, sizeof(versions));
return 0;
}
@@ -1796,27 +1772,22 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Returns list of inquiry VPD pages available.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
{
const u8 pages[] = {
0x00, /* page 0x00, this page */
0x80, /* page 0x80, unit serial no page */
0x83 /* page 0x83, device ident page */
};
- rbuf[3] = sizeof(pages); /* number of supported VPD pages */
-
- if (buflen > 6)
- memcpy(rbuf + 4, pages, sizeof(pages));
+ rbuf[3] = sizeof(pages); /* number of supported VPD pages */
+ memcpy(rbuf + 4, pages, sizeof(pages));
return 0;
}
@@ -1824,16 +1795,13 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Returns ATA device serial number.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
{
const u8 hdr[] = {
0,
@@ -1841,12 +1809,10 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
0,
ATA_ID_SERNO_LEN, /* page len */
};
- memcpy(rbuf, hdr, sizeof(hdr));
-
- if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
- ata_id_string(args->id, (unsigned char *) &rbuf[4],
- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+ memcpy(rbuf, hdr, sizeof(hdr));
+ ata_id_string(args->id, (unsigned char *) &rbuf[4],
+ ATA_ID_SERNO, ATA_ID_SERNO_LEN);
return 0;
}
@@ -1854,7 +1820,6 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Yields two logical unit device identification designators:
* - vendor specific ASCII containing the ATA serial number
@@ -1864,41 +1829,37 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
{
- int num;
const int sat_model_serial_desc_len = 68;
+ int num;
rbuf[1] = 0x83; /* this page code */
num = 4;
- if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
- /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
- rbuf[num + 0] = 2;
- rbuf[num + 3] = ATA_ID_SERNO_LEN;
- num += 4;
- ata_id_string(args->id, (unsigned char *) rbuf + num,
- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
- num += ATA_ID_SERNO_LEN;
- }
- if (buflen > (sat_model_serial_desc_len + num + 3)) {
- /* SAT defined lu model and serial numbers descriptor */
- /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
- rbuf[num + 0] = 2;
- rbuf[num + 1] = 1;
- rbuf[num + 3] = sat_model_serial_desc_len;
- num += 4;
- memcpy(rbuf + num, "ATA ", 8);
- num += 8;
- ata_id_string(args->id, (unsigned char *) rbuf + num,
- ATA_ID_PROD, ATA_ID_PROD_LEN);
- num += ATA_ID_PROD_LEN;
- ata_id_string(args->id, (unsigned char *) rbuf + num,
- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
- num += ATA_ID_SERNO_LEN;
- }
+ /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
+ rbuf[num + 0] = 2;
+ rbuf[num + 3] = ATA_ID_SERNO_LEN;
+ num += 4;
+ ata_id_string(args->id, (unsigned char *) rbuf + num,
+ ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+ num += ATA_ID_SERNO_LEN;
+
+ /* SAT defined lu model and serial numbers descriptor */
+ /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
+ rbuf[num + 0] = 2;
+ rbuf[num + 1] = 1;
+ rbuf[num + 3] = sat_model_serial_desc_len;
+ num += 4;
+ memcpy(rbuf + num, "ATA ", 8);
+ num += 8;
+ ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
+ ATA_ID_PROD_LEN);
+ num += ATA_ID_PROD_LEN;
+ ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
+ ATA_ID_SERNO_LEN);
+ num += ATA_ID_SERNO_LEN;
+
rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
return 0;
}
@@ -1907,35 +1868,26 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Yields SAT-specified ATA VPD page.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
{
- u8 pbuf[60];
struct ata_taskfile tf;
- unsigned int i;
- if (!buflen)
- return 0;
-
- memset(&pbuf, 0, sizeof(pbuf));
memset(&tf, 0, sizeof(tf));
- pbuf[1] = 0x89; /* our page code */
- pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
- pbuf[3] = (0x238 & 0xff);
+ rbuf[1] = 0x89; /* our page code */
+ rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
+ rbuf[3] = (0x238 & 0xff);
- memcpy(&pbuf[8], "linux ", 8);
- memcpy(&pbuf[16], "libata ", 16);
- memcpy(&pbuf[32], DRV_VERSION, 4);
- ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
+ memcpy(&rbuf[8], "linux ", 8);
+ memcpy(&rbuf[16], "libata ", 16);
+ memcpy(&rbuf[32], DRV_VERSION, 4);
+ ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
/* we don't store the ATA device signature, so we fake it */
@@ -1943,19 +1895,12 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
tf.lbal = 0x1;
tf.nsect = 0x1;
- ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */
- pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
+ ata_tf_to_fis(&tf, 0, 1, &rbuf[36]); /* TODO: PMP? */
+ rbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
- pbuf[56] = ATA_CMD_ID_ATA;
+ rbuf[56] = ATA_CMD_ID_ATA;
- i = min(buflen, 60U);
- memcpy(rbuf, &pbuf[0], i);
- buflen -= i;
-
- if (!buflen)
- return 0;
-
- memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
+ memcpy(&rbuf[60], &args->id[0], 512);
return 0;
}
@@ -1963,7 +1908,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* No operation. Simply returns success to caller, to indicate
* that the caller should successfully complete this SCSI command.
@@ -1971,47 +1915,16 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
{
VPRINTK("ENTER\n");
return 0;
}
/**
- * ata_msense_push - Push data onto MODE SENSE data output buffer
- * @ptr_io: (input/output) Location to store more output data
- * @last: End of output data buffer
- * @buf: Pointer to BLOB being added to output buffer
- * @buflen: Length of BLOB
- *
- * Store MODE SENSE data on an output buffer.
- *
- * LOCKING:
- * None.
- */
-
-static void ata_msense_push(u8 **ptr_io, const u8 *last,
- const u8 *buf, unsigned int buflen)
-{
- u8 *ptr = *ptr_io;
-
- if ((ptr + buflen - 1) > last)
- return;
-
- memcpy(ptr, buf, buflen);
-
- ptr += buflen;
-
- *ptr_io = ptr;
-}
-
-/**
* ata_msense_caching - Simulate MODE SENSE caching info page
* @id: device IDENTIFY data
- * @ptr_io: (input/output) Location to store more output data
- * @last: End of output data buffer
+ * @buf: output buffer
*
* Generate a caching info page, which conditionally indicates
* write caching to the SCSI layer, depending on device
@@ -2020,58 +1933,43 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
* LOCKING:
* None.
*/
-
-static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
- const u8 *last)
+static unsigned int ata_msense_caching(u16 *id, u8 *buf)
{
- u8 page[CACHE_MPAGE_LEN];
-
- memcpy(page, def_cache_mpage, sizeof(page));
+ memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
if (ata_id_wcache_enabled(id))
- page[2] |= (1 << 2); /* write cache enable */
+ buf[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id))
- page[12] |= (1 << 5); /* disable read ahead */
-
- ata_msense_push(ptr_io, last, page, sizeof(page));
- return sizeof(page);
+ buf[12] |= (1 << 5); /* disable read ahead */
+ return sizeof(def_cache_mpage);
}
/**
* ata_msense_ctl_mode - Simulate MODE SENSE control mode page
- * @dev: Device associated with this MODE SENSE command
- * @ptr_io: (input/output) Location to store more output data
- * @last: End of output data buffer
+ * @buf: output buffer
*
* Generate a generic MODE SENSE control mode page.
*
* LOCKING:
* None.
*/
-
-static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
+static unsigned int ata_msense_ctl_mode(u8 *buf)
{
- ata_msense_push(ptr_io, last, def_control_mpage,
- sizeof(def_control_mpage));
+ memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
return sizeof(def_control_mpage);
}
/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
- * @dev: Device associated with this MODE SENSE command
- * @ptr_io: (input/output) Location to store more output data
- * @last: End of output data buffer
+ * @bufp: output buffer
*
* Generate a generic MODE SENSE r/w error recovery page.
*
* LOCKING:
* None.
*/
-
-static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
+static unsigned int ata_msense_rw_recovery(u8 *buf)
{
-
- ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
- sizeof(def_rw_recovery_mpage));
+ memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
return sizeof(def_rw_recovery_mpage);
}
@@ -2103,7 +2001,6 @@ static int ata_dev_supports_fua(u16 *id)
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Simulate MODE SENSE commands. Assume this is invoked for direct
* access devices (e.g. disks) only. There should be no block
@@ -2112,19 +2009,17 @@ static int ata_dev_supports_fua(u16 *id)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
{
struct ata_device *dev = args->dev;
- u8 *scsicmd = args->cmd->cmnd, *p, *last;
+ u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */
0,
0, 0x2, 0x0 /* block length: 512 bytes */
};
u8 pg, spg;
- unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+ unsigned int ebd, page_control, six_byte;
u8 dpofua;
VPRINTK("ENTER\n");
@@ -2147,17 +2042,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
goto invalid_fld;
}
- if (six_byte) {
- output_len = 4 + (ebd ? 8 : 0);
- alloc_len = scsicmd[4];
- } else {
- output_len = 8 + (ebd ? 8 : 0);
- alloc_len = (scsicmd[7] << 8) + scsicmd[8];
- }
- minlen = (alloc_len < buflen) ? alloc_len : buflen;
-
- p = rbuf + output_len;
- last = rbuf + minlen - 1;
+ if (six_byte)
+ p += 4 + (ebd ? 8 : 0);
+ else
+ p += 8 + (ebd ? 8 : 0);
pg = scsicmd[2] & 0x3f;
spg = scsicmd[3];
@@ -2170,61 +2058,48 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
switch(pg) {
case RW_RECOVERY_MPAGE:
- output_len += ata_msense_rw_recovery(&p, last);
+ p += ata_msense_rw_recovery(p);
break;
case CACHE_MPAGE:
- output_len += ata_msense_caching(args->id, &p, last);
+ p += ata_msense_caching(args->id, p);
break;
- case CONTROL_MPAGE: {
- output_len += ata_msense_ctl_mode(&p, last);
+ case CONTROL_MPAGE:
+ p += ata_msense_ctl_mode(p);
break;
- }
case ALL_MPAGES:
- output_len += ata_msense_rw_recovery(&p, last);
- output_len += ata_msense_caching(args->id, &p, last);
- output_len += ata_msense_ctl_mode(&p, last);
+ p += ata_msense_rw_recovery(p);
+ p += ata_msense_caching(args->id, p);
+ p += ata_msense_ctl_mode(p);
break;
default: /* invalid page code */
goto invalid_fld;
}
- if (minlen < 1)
- return 0;
-
dpofua = 0;
if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
(!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
dpofua = 1 << 4;
if (six_byte) {
- output_len--;
- rbuf[0] = output_len;
- if (minlen > 2)
- rbuf[2] |= dpofua;
+ rbuf[0] = p - rbuf - 1;
+ rbuf[2] |= dpofua;
if (ebd) {
- if (minlen > 3)
- rbuf[3] = sizeof(sat_blk_desc);
- if (minlen > 11)
- memcpy(rbuf + 4, sat_blk_desc,
- sizeof(sat_blk_desc));
+ rbuf[3] = sizeof(sat_blk_desc);
+ memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
}
} else {
- output_len -= 2;
+ unsigned int output_len = p - rbuf - 2;
+
rbuf[0] = output_len >> 8;
- if (minlen > 1)
- rbuf[1] = output_len;
- if (minlen > 3)
- rbuf[3] |= dpofua;
+ rbuf[1] = output_len;
+ rbuf[3] |= dpofua;
if (ebd) {
- if (minlen > 7)
- rbuf[7] = sizeof(sat_blk_desc);
- if (minlen > 15)
- memcpy(rbuf + 8, sat_blk_desc,
- sizeof(sat_blk_desc));
+ rbuf[7] = sizeof(sat_blk_desc);
+ memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
}
}
return 0;
@@ -2244,15 +2119,13 @@ saving_not_supp:
* ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Simulate READ CAPACITY commands.
*
* LOCKING:
* None.
*/
-unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
{
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
@@ -2263,28 +2136,28 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
last_lba = 0xffffffff;
/* sector count, 32-bit */
- ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3));
- ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2));
- ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1));
- ATA_SCSI_RBUF_SET(3, last_lba);
+ rbuf[0] = last_lba >> (8 * 3);
+ rbuf[1] = last_lba >> (8 * 2);
+ rbuf[2] = last_lba >> (8 * 1);
+ rbuf[3] = last_lba;
/* sector size */
- ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
- ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
+ rbuf[6] = ATA_SECT_SIZE >> 8;
+ rbuf[7] = ATA_SECT_SIZE & 0xff;
} else {
/* sector count, 64-bit */
- ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
- ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6));
- ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5));
- ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4));
- ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3));
- ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2));
- ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1));
- ATA_SCSI_RBUF_SET(7, last_lba);
+ rbuf[0] = last_lba >> (8 * 7);
+ rbuf[1] = last_lba >> (8 * 6);
+ rbuf[2] = last_lba >> (8 * 5);
+ rbuf[3] = last_lba >> (8 * 4);
+ rbuf[4] = last_lba >> (8 * 3);
+ rbuf[5] = last_lba >> (8 * 2);
+ rbuf[6] = last_lba >> (8 * 1);
+ rbuf[7] = last_lba;
/* sector size */
- ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
- ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
+ rbuf[10] = ATA_SECT_SIZE >> 8;
+ rbuf[11] = ATA_SECT_SIZE & 0xff;
}
return 0;
@@ -2294,16 +2167,13 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_report_luns - Simulate REPORT LUNS command
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- * @buflen: Response buffer length.
*
* Simulate REPORT LUNS command.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-
-unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
{
VPRINTK("ENTER\n");
rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
@@ -2311,57 +2181,6 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
return 0;
}
-/**
- * ata_scsi_set_sense - Set SCSI sense data and status
- * @cmd: SCSI request to be handled
- * @sk: SCSI-defined sense key
- * @asc: SCSI-defined additional sense code
- * @ascq: SCSI-defined additional sense code qualifier
- *
- * Helper function that builds a valid fixed format, current
- * response code and the given sense key (sk), additional sense
- * code (asc) and additional sense code qualifier (ascq) with
- * a SCSI command status of %SAM_STAT_CHECK_CONDITION and
- * DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
- *
- * LOCKING:
- * Not required
- */
-
-void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
-{
- cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
- cmd->sense_buffer[0] = 0x70; /* fixed format, current */
- cmd->sense_buffer[2] = sk;
- cmd->sense_buffer[7] = 18 - 8; /* additional sense length */
- cmd->sense_buffer[12] = asc;
- cmd->sense_buffer[13] = ascq;
-}
-
-/**
- * ata_scsi_badcmd - End a SCSI request with an error
- * @cmd: SCSI request to be handled
- * @done: SCSI command completion function
- * @asc: SCSI-defined additional sense code
- * @ascq: SCSI-defined additional sense code qualifier
- *
- * Helper function that completes a SCSI command with
- * %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
- * and the specified additional sense codes.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- */
-
-void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
-{
- DPRINTK("ENTER\n");
- ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
-
- done(cmd);
-}
-
static void atapi_sense_complete(struct ata_queued_cmd *qc)
{
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
@@ -2393,7 +2212,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
/* FIXME: is this needed? */
memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
- ap->ops->tf_read(ap, &qc->tf);
+#ifdef CONFIG_ATA_SFF
+ if (ap->ops->sff_tf_read)
+ ap->ops->sff_tf_read(ap, &qc->tf);
+#endif
/* fill these in, for the case where they are -not- overwritten */
cmd->sense_buffer[0] = 0x70;
@@ -2485,13 +2307,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
u8 *scsicmd = cmd->cmnd;
if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
- u8 *buf = NULL;
- unsigned int buflen;
unsigned long flags;
+ u8 *buf;
- local_irq_save(flags);
-
- buflen = ata_scsi_rbuf_get(cmd, &buf);
+ buf = ata_scsi_rbuf_get(cmd, true, &flags);
/* ATAPI devices typically report zero for their SCSI version,
* and sometimes deviate from the spec WRT response data
@@ -2506,9 +2325,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
buf[3] = 0x32;
}
- ata_scsi_rbuf_put(cmd, buf);
-
- local_irq_restore(flags);
+ ata_scsi_rbuf_put(cmd, true, &flags);
}
cmd->result = SAM_STAT_GOOD;
@@ -2615,7 +2432,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
{
- if (ap->nr_pmp_links == 0) {
+ if (!sata_pmp_attached(ap)) {
if (likely(devno < ata_link_max_devices(&ap->link)))
return &ap->link.device[devno];
} else {
@@ -2632,7 +2449,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
int devno;
/* skip commands not addressed to targets we simulate */
- if (ap->nr_pmp_links == 0) {
+ if (!sata_pmp_attached(ap)) {
if (unlikely(scsidev->channel || scsidev->lun))
return NULL;
devno = scsidev->id;
@@ -3490,7 +3307,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
if (lun != SCAN_WILD_CARD && lun)
return -EINVAL;
- if (ap->nr_pmp_links == 0) {
+ if (!sata_pmp_attached(ap)) {
if (channel != SCAN_WILD_CARD && channel)
return -EINVAL;
devno = id;
@@ -3507,8 +3324,8 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
ata_port_for_each_link(link, ap) {
struct ata_eh_info *ehi = &link->eh_info;
- ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
- ehi->action |= ATA_EH_SOFTRESET;
+ ehi->probe_mask |= ATA_ALL_DEVICES;
+ ehi->action |= ATA_EH_RESET;
}
} else {
struct ata_device *dev = ata_find_dev(ap, devno);
@@ -3516,8 +3333,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
if (dev) {
struct ata_eh_info *ehi = &dev->link->eh_info;
ehi->probe_mask |= 1 << dev->devno;
- ehi->action |= ATA_EH_SOFTRESET;
- ehi->flags |= ATA_EHI_RESUME_LINK;
+ ehi->action |= ATA_EH_RESET;
} else
rc = -EINVAL;
}