aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r--drivers/scsi/libata-scsi.c213
1 files changed, 119 insertions, 94 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index bd9f2176f79..628191bfd99 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -256,7 +256,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[14] = args[0];
/* Good values for timeout and retries? Values below
- from scsi_ioctl_send_command() for default case... */
+ from scsi_ioctl_send_command() for default case... */
if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
(10*HZ), 5))
rc = -EIO;
@@ -267,20 +267,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
{
- struct ata_port *ap;
- struct ata_device *dev;
int val = -EINVAL, rc = -EINVAL;
- ap = (struct ata_port *) &scsidev->host->hostdata[0];
- if (!ap)
- goto out;
-
- dev = ata_scsi_find_dev(ap, scsidev);
- if (!dev) {
- rc = -ENODEV;
- goto out;
- }
-
switch (cmd) {
case ATA_IOC_GET_IO32:
val = 0;
@@ -309,7 +297,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
break;
}
-out:
return rc;
}
@@ -414,12 +401,12 @@ int ata_scsi_device_resume(struct scsi_device *sdev)
return ata_device_resume(ap, dev);
}
-int ata_scsi_device_suspend(struct scsi_device *sdev)
+int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
{
struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
struct ata_device *dev = &ap->device[sdev->id];
- return ata_device_suspend(ap, dev);
+ return ata_device_suspend(ap, dev, state);
}
/**
@@ -438,7 +425,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev)
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
u8 *ascq)
{
int i;
@@ -495,7 +482,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
/* Look for drv_err */
for (i = 0; sense_table[i][0] != 0xFF; i++) {
/* Look for best matches first */
- if ((sense_table[i][0] & drv_err) ==
+ if ((sense_table[i][0] & drv_err) ==
sense_table[i][0]) {
*sk = sense_table[i][1];
*asc = sense_table[i][2];
@@ -518,16 +505,14 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
}
}
/* No error? Undecoded? */
- printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
+ printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
id, drv_stat);
- /* For our last chance pick, use medium read error because
- * it's much more common than an ATA drive telling you a write
- * has failed.
- */
- *sk = MEDIUM_ERROR;
- *asc = 0x11; /* "unrecovered read error" */
- *ascq = 0x04; /* "auto-reallocation failed" */
+ /* We need a sensible error return here, which is tricky, and one
+ that won't cause people to do things like return a disk wrongly */
+ *sk = ABORTED_COMMAND;
+ *asc = 0x00;
+ *ascq = 0x00;
translate_done:
printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
@@ -672,6 +657,41 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
}
}
+static void ata_scsi_sdev_config(struct scsi_device *sdev)
+{
+ sdev->use_10_for_rw = 1;
+ sdev->use_10_for_ms = 1;
+}
+
+static void ata_scsi_dev_config(struct scsi_device *sdev,
+ struct ata_device *dev)
+{
+ unsigned int max_sectors;
+
+ /* TODO: 2048 is an arbitrary number, not the
+ * hardware maximum. This should be increased to
+ * 65534 when Jens Axboe's patch for dynamically
+ * determining max_sectors is merged.
+ */
+ max_sectors = ATA_MAX_SECTORS;
+ if (dev->flags & ATA_DFLAG_LBA48)
+ max_sectors = 2048;
+ if (dev->max_sectors)
+ max_sectors = dev->max_sectors;
+
+ blk_queue_max_sectors(sdev->request_queue, max_sectors);
+
+ /*
+ * SATA DMA transfers must be multiples of 4 byte, so
+ * we need to pad ATAPI transfers using an extra sg.
+ * Decrement max hw segments accordingly.
+ */
+ if (dev->class == ATA_DEV_ATAPI) {
+ request_queue_t *q = sdev->request_queue;
+ blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
+ }
+}
+
/**
* ata_scsi_slave_config - Set SCSI device attributes
* @sdev: SCSI device to examine
@@ -686,41 +706,18 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
int ata_scsi_slave_config(struct scsi_device *sdev)
{
- sdev->use_10_for_rw = 1;
- sdev->use_10_for_ms = 1;
+ ata_scsi_sdev_config(sdev);
blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
if (sdev->id < ATA_MAX_DEVICES) {
struct ata_port *ap;
struct ata_device *dev;
- unsigned int max_sectors;
ap = (struct ata_port *) &sdev->host->hostdata[0];
dev = &ap->device[sdev->id];
- /* TODO: 2048 is an arbitrary number, not the
- * hardware maximum. This should be increased to
- * 65534 when Jens Axboe's patch for dynamically
- * determining max_sectors is merged.
- */
- max_sectors = ATA_MAX_SECTORS;
- if (dev->flags & ATA_DFLAG_LBA48)
- max_sectors = 2048;
- if (dev->max_sectors)
- max_sectors = dev->max_sectors;
-
- blk_queue_max_sectors(sdev->request_queue, max_sectors);
-
- /*
- * SATA DMA transfers must be multiples of 4 byte, so
- * we need to pad ATAPI transfers using an extra sg.
- * Decrement max hw segments accordingly.
- */
- if (dev->class == ATA_DEV_ATAPI) {
- request_queue_t *q = sdev->request_queue;
- blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
- }
+ ata_scsi_dev_config(sdev, dev);
}
return 0; /* scsi layer doesn't check return value, sigh */
@@ -1140,14 +1137,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
DPRINTK("block %u track %u cyl %u head %u sect %u\n",
(u32)block, track, cyl, head, sect);
-
- /* Check whether the converted CHS can fit.
- Cylinder: 0-65535
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
Head: 0-15
Sector: 1-255*/
- if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
goto out_of_range;
-
+
tf->command = ATA_CMD_VERIFY;
tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
tf->lbal = sect;
@@ -1279,7 +1276,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
tf->lbal = block & 0xff;
tf->device |= ATA_LBA;
- } else {
+ } else {
/* CHS */
u32 sect, head, cyl, track;
@@ -1299,8 +1296,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
DPRINTK("block %u track %u cyl %u head %u sect %u\n",
(u32)block, track, cyl, head, sect);
- /* Check whether the converted CHS can fit.
- Cylinder: 0-65535
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
Head: 0-15
Sector: 1-255*/
if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
@@ -1552,7 +1549,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* @buflen: Response buffer length.
*
* Returns standard device identification data associated
- * with non-EVPD INQUIRY command output.
+ * with non-VPD INQUIRY command output.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -1603,12 +1600,12 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
}
/**
- * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages
+ * 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 EVPD pages available.
+ * Returns list of inquiry VPD pages available.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -1622,7 +1619,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
0x80, /* page 0x80, unit serial no page */
0x83 /* page 0x83, device ident page */
};
- rbuf[3] = sizeof(pages); /* number of supported EVPD pages */
+ rbuf[3] = sizeof(pages); /* number of supported VPD pages */
if (buflen > 6)
memcpy(rbuf + 4, pages, sizeof(pages));
@@ -1631,7 +1628,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
}
/**
- * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number
+ * 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.
@@ -1660,16 +1657,16 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
return 0;
}
-static const char * const inq_83_str = "Linux ATA-SCSI simulator";
-
/**
- * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
+ * 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.
*
- * Returns device identification. Currently hardcoded to
- * return "Linux ATA-SCSI simulator".
+ * Yields two logical unit device identification designators:
+ * - vendor specific ASCII containing the ATA serial number
+ * - SAT defined "t10 vendor id based" containing ASCII vendor
+ * name ("ATA "), model and serial numbers.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -1678,16 +1675,39 @@ static const char * const inq_83_str = "Linux ATA-SCSI simulator";
unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
- rbuf[1] = 0x83; /* this page code */
- rbuf[3] = 4 + strlen(inq_83_str); /* page len */
+ int num;
+ const int sat_model_serial_desc_len = 68;
+ const int ata_model_byte_len = 40;
- /* our one and only identification descriptor (vendor-specific) */
- if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) {
- rbuf[4 + 0] = 2; /* code set: ASCII */
- rbuf[4 + 3] = strlen(inq_83_str);
- memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str));
+ rbuf[1] = 0x83; /* this page code */
+ num = 4;
+
+ if (buflen > (ATA_SERNO_LEN + num + 3)) {
+ /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
+ rbuf[num + 0] = 2;
+ rbuf[num + 3] = ATA_SERNO_LEN;
+ num += 4;
+ ata_id_string(args->id, (unsigned char *) rbuf + num,
+ ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+ num += ATA_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_OFS, ata_model_byte_len);
+ num += ata_model_byte_len;
+ ata_id_string(args->id, (unsigned char *) rbuf + num,
+ ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+ num += ATA_SERNO_LEN;
+ }
+ rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
return 0;
}
@@ -2366,9 +2386,6 @@ ata_scsi_map_proto(u8 byte1)
case 4: /* PIO Data-in */
case 5: /* PIO Data-out */
- if (byte1 & 0xe0) {
- return ATA_PROT_PIO_MULT;
- }
return ATA_PROT_PIO;
case 10: /* Device Reset */
@@ -2407,6 +2424,10 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
goto invalid_fld;
+ if (scsicmd[1] & 0xe0)
+ /* PIO multi not supported yet */
+ goto invalid_fld;
+
/*
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
@@ -2563,6 +2584,21 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
#endif
}
+static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap, struct ata_device *dev)
+{
+ if (dev->class == ATA_DEV_ATA) {
+ ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+ cmd->cmnd[0]);
+
+ if (xlat_func)
+ ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+ else
+ ata_scsi_simulate(ap, dev, cmd, done);
+ } else
+ ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+}
+
/**
* ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
* @cmd: SCSI command to be sent
@@ -2597,24 +2633,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
ata_scsi_dump_cdb(ap, cmd);
dev = ata_scsi_find_dev(ap, scsidev);
- if (unlikely(!dev)) {
+ if (likely(dev))
+ __ata_scsi_queuecmd(cmd, done, ap, dev);
+ else {
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
- goto out_unlock;
}
- if (dev->class == ATA_DEV_ATA) {
- ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
- cmd->cmnd[0]);
-
- if (xlat_func)
- ata_scsi_translate(ap, dev, cmd, done, xlat_func);
- else
- ata_scsi_simulate(ap, dev, cmd, done);
- } else
- ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
-
-out_unlock:
spin_unlock(&ap->host_set->lock);
spin_lock(shost->host_lock);
return 0;