X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Flibata-scsi.c;h=628191bfd990a56e039611e8332bafda0ce07c92;hb=d62e54abca1146981fc9f98f85ff398a113a22c2;hp=ccedb4536977af454a6c95a613fefc4a292d3e83;hpb=d04cdb64212eb5ae6a98026a97dda626e40e8e9a;p=linux-2.6 diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ccedb45369..628191bfd9 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -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 *)) @@ -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 " @@ -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,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 */ @@ -1130,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; @@ -1269,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; @@ -1289,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)) @@ -1542,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) @@ -1593,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) @@ -1612,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)); @@ -1621,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. @@ -1650,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) @@ -1668,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; } @@ -2356,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 */ @@ -2397,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. @@ -2553,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 @@ -2587,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;