diff options
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 443 |
1 files changed, 284 insertions, 159 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 59503c9ccac..53f5b0d9161 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -41,6 +41,7 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_device.h> #include <scsi/scsi_request.h> +#include <scsi/scsi_transport.h> #include <linux/libata.h> #include <linux/hdreg.h> #include <asm/uaccess.h> @@ -52,6 +53,7 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -92,6 +94,14 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { 0, 30 /* extended self test time, see 05-359r1 */ }; +/* + * libata transport template. libata doesn't do real transport stuff. + * It just needs the eh_timed_out hook. + */ +struct scsi_transport_template ata_scsi_transport_template = { + .eh_timed_out = ata_scsi_timed_out, +}; + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) @@ -151,7 +161,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) struct scsi_sense_hdr sshdr; enum dma_data_direction data_dir; - if (NULL == (void *)arg) + if (arg == NULL) return -EINVAL; if (copy_from_user(args, arg, sizeof(args))) @@ -201,7 +211,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) /* Need code to retrieve data from check condition? */ if ((argbuf) - && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) + && copy_to_user(arg + sizeof(args), argbuf, argsize)) rc = -EFAULT; error: if (argbuf) @@ -228,7 +238,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) u8 args[7]; struct scsi_sense_hdr sshdr; - if (NULL == (void *)arg) + if (arg == NULL) return -EINVAL; if (copy_from_user(args, arg, sizeof(args))) @@ -246,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; @@ -257,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; @@ -299,7 +297,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) break; } -out: return rc; } @@ -404,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); } /** @@ -428,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; @@ -485,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]; @@ -508,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 " @@ -553,7 +548,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) /* * Read the controller registers. */ - assert(NULL != qc->ap->ops->tf_read); + WARN_ON(qc->ap->ops->tf_read == NULL); qc->ap->ops->tf_read(qc->ap, tf); /* @@ -628,7 +623,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) /* * Read the controller registers. */ - assert(NULL != qc->ap->ops->tf_read); + WARN_ON(qc->ap->ops->tf_read == NULL); qc->ap->ops->tf_read(qc->ap, tf); /* @@ -662,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 @@ -676,8 +706,7 @@ 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); @@ -688,35 +717,54 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 1024 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. - */ - if ((dev->flags & ATA_DFLAG_LBA48) && - ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { - /* - * do not overwrite sdev->host->max_sectors, since - * other drives on this host may not support LBA48 - */ - blk_queue_max_sectors(sdev->request_queue, 2048); - } - - /* - * 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 */ } /** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret = EH_HANDLED; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + WARN_ON(qc->scsicmd != cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + +/** * ata_scsi_error - SCSI layer error handler callback * @host: SCSI host on which error occurred * @@ -732,23 +780,84 @@ int ata_scsi_slave_config(struct scsi_device *sdev) int ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap; + unsigned long flags; DPRINTK("ENTER\n"); ap = (struct ata_port *) &host->hostdata[0]; + + spin_lock_irqsave(&ap->host_set->lock, flags); + WARN_ON(ap->flags & ATA_FLAG_IN_EH); + ap->flags |= ATA_FLAG_IN_EH; + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_port_flush_task(ap); + ap->ops->eng_timeout(ap); - /* TODO: this is per-command; when queueing is supported - * this code will either change or move to a more - * appropriate place - */ - host->host_failed--; - INIT_LIST_HEAD(&host->eh_cmd_q); + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_IN_EH; + spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("EXIT\n"); return 0; } +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc->scsidone = ata_eh_scsidone; + __ata_qc_complete(qc); + WARN_ON(ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * This function might need to adjust scmd->retries for commands + * which get retried due to unrelated NCQ failures. + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + __ata_eh_qc_complete(qc); +} + /** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile @@ -985,9 +1094,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - if (dev->flags & ATA_DFLAG_LBA48) { - if (n_block > (64 * 1024)) - goto invalid_fld; + if (lba_28_ok(block, n_block)) { + /* use LBA28 */ + tf->command = ATA_CMD_VERIFY; + tf->device |= (block >> 24) & 0xf; + } else if (lba_48_ok(block, n_block)) { + if (!(dev->flags & ATA_DFLAG_LBA48)) + goto out_of_range; /* use LBA48 */ tf->flags |= ATA_TFLAG_LBA48; @@ -998,15 +1111,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; - } else { - if (n_block > 256) - goto invalid_fld; - - /* use LBA28 */ - tf->command = ATA_CMD_VERIFY; - - tf->device |= (block >> 24) & 0xf; - } + } else + /* request too large even for LBA48 */ + goto out_of_range; tf->nsect = n_block & 0xff; @@ -1019,8 +1126,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc /* CHS */ u32 sect, head, cyl, track; - if (n_block > 256) - goto invalid_fld; + if (!lba_28_ok(block, n_block)) + goto out_of_range; /* Convert LBA to CHS */ track = (u32)block / dev->sectors; @@ -1030,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; @@ -1139,9 +1246,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - if (dev->flags & ATA_DFLAG_LBA48) { - /* The request -may- be too large for LBA48. */ - if ((block >> 48) || (n_block > 65536)) + if (lba_28_ok(block, n_block)) { + /* use LBA28 */ + tf->device |= (block >> 24) & 0xf; + } else if (lba_48_ok(block, n_block)) { + if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; /* use LBA48 */ @@ -1152,15 +1261,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; - } else { - /* use LBA28 */ - - /* The request -may- be too large for LBA28. */ - if ((block >> 28) || (n_block > 256)) - goto out_of_range; - - tf->device |= (block >> 24) & 0xf; - } + } else + /* request too large even for LBA48 */ + goto out_of_range; if (unlikely(ata_rwcmd_protocol(qc) < 0)) goto invalid_fld; @@ -1173,12 +1276,12 @@ 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; /* The request -may- be too large for CHS addressing. */ - if ((block >> 28) || (n_block > 256)) + if (!lba_28_ok(block, n_block)) goto out_of_range; if (unlikely(ata_rwcmd_protocol(qc) < 0)) @@ -1193,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)) @@ -1225,7 +1328,7 @@ nothing_to_do: return 1; } -static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) +static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; @@ -1262,7 +1365,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** @@ -1328,8 +1431,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - if (ata_qc_issue(qc)) - goto err_did; + ata_qc_issue(qc); VPRINTK("EXIT\n"); return; @@ -1445,7 +1547,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) @@ -1472,8 +1574,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); + ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -1496,12 +1598,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) @@ -1515,7 +1617,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)); @@ -1524,7 +1626,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. @@ -1547,22 +1649,22 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, memcpy(rbuf, hdr, sizeof(hdr)); if (buflen > (ATA_SERNO_LEN + 4 - 1)) - ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + ata_id_string(args->id, (unsigned char *) &rbuf[4], + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); 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) @@ -1571,16 +1673,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; } @@ -1713,15 +1838,12 @@ static int ata_dev_supports_fua(u16 *id) if (!ata_id_has_fua(id)) return 0; - model[40] = '\0'; - fw[8] = '\0'; - - ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1); - ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1); + ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); + ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); - if (strncmp(model, "Maxtor", 6)) + if (strcmp(model, "Maxtor")) return 1; - if (strncmp(fw, "BANC1G10", 8)) + if (strcmp(fw, "BANC1G10")) return 1; return 0; /* blacklisted */ @@ -2015,7 +2137,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 done(cmd); } -static int atapi_sense_complete(struct ata_queued_cmd *qc) +static void atapi_sense_complete(struct ata_queued_cmd *qc) { if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) /* FIXME: not quite right; we don't want the @@ -2026,7 +2148,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_ata_desc_sense(qc); qc->scsidone(qc->scsicmd); - return 0; + ata_qc_free(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2056,7 +2178,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); qc->dma_dir = DMA_FROM_DEVICE; - memset(&qc->cdb, 0, ap->cdb_len); + memset(&qc->cdb, 0, qc->dev->cdb_len); qc->cdb[0] = REQUEST_SENSE; qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; @@ -2075,15 +2197,12 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->complete_fn = atapi_sense_complete; - if (ata_qc_issue(qc)) { - qc->err_mask |= AC_ERR_OTHER; - ata_qc_complete(qc); - } + ata_qc_issue(qc); DPRINTK("EXIT\n"); } -static int atapi_qc_complete(struct ata_queued_cmd *qc) +static void atapi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; unsigned int err_mask = qc->err_mask; @@ -2093,7 +2212,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) if (unlikely(err_mask & AC_ERR_DEV)) { cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); - return 1; + return; } else if (unlikely(err_mask)) @@ -2133,7 +2252,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) } qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** * atapi_xlat - Initialize PACKET taskfile @@ -2159,7 +2278,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) if (ata_check_atapi_dma(qc)) using_pio = 1; - memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); + memcpy(&qc->cdb, scsicmd, dev->cdb_len); qc->complete_fn = atapi_qc_complete; @@ -2263,9 +2382,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 */ @@ -2304,6 +2420,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. @@ -2460,6 +2580,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 @@ -2494,24 +2629,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; @@ -2519,7 +2643,8 @@ out_unlock: /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @id: current IDENTIFY data for target device. + * @ap: port the device is connected to + * @dev: the target device * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. * |