diff options
| -rw-r--r-- | drivers/scsi/libata-core.c | 31 | ||||
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 32 | ||||
| -rw-r--r-- | drivers/scsi/libata.h | 4 | ||||
| -rw-r--r-- | include/linux/ata.h | 6 | ||||
| -rw-r--r-- | include/linux/libata.h | 3 |
5 files changed, 61 insertions, 15 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9ea102587914..bdfb0a88cd6f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = { | |||
| 562 | ATA_CMD_WRITE_MULTI, | 562 | ATA_CMD_WRITE_MULTI, |
| 563 | ATA_CMD_READ_MULTI_EXT, | 563 | ATA_CMD_READ_MULTI_EXT, |
| 564 | ATA_CMD_WRITE_MULTI_EXT, | 564 | ATA_CMD_WRITE_MULTI_EXT, |
| 565 | 0, | ||
| 566 | 0, | ||
| 567 | 0, | ||
| 568 | ATA_CMD_WRITE_MULTI_FUA_EXT, | ||
| 565 | /* pio */ | 569 | /* pio */ |
| 566 | ATA_CMD_PIO_READ, | 570 | ATA_CMD_PIO_READ, |
| 567 | ATA_CMD_PIO_WRITE, | 571 | ATA_CMD_PIO_WRITE, |
| 568 | ATA_CMD_PIO_READ_EXT, | 572 | ATA_CMD_PIO_READ_EXT, |
| 569 | ATA_CMD_PIO_WRITE_EXT, | 573 | ATA_CMD_PIO_WRITE_EXT, |
| 574 | 0, | ||
| 575 | 0, | ||
| 576 | 0, | ||
| 577 | 0, | ||
| 570 | /* dma */ | 578 | /* dma */ |
| 571 | ATA_CMD_READ, | 579 | ATA_CMD_READ, |
| 572 | ATA_CMD_WRITE, | 580 | ATA_CMD_WRITE, |
| 573 | ATA_CMD_READ_EXT, | 581 | ATA_CMD_READ_EXT, |
| 574 | ATA_CMD_WRITE_EXT | 582 | ATA_CMD_WRITE_EXT, |
| 583 | 0, | ||
| 584 | 0, | ||
| 585 | 0, | ||
| 586 | ATA_CMD_WRITE_FUA_EXT | ||
| 575 | }; | 587 | }; |
| 576 | 588 | ||
| 577 | /** | 589 | /** |
| @@ -584,25 +596,32 @@ static const u8 ata_rw_cmds[] = { | |||
| 584 | * LOCKING: | 596 | * LOCKING: |
| 585 | * caller. | 597 | * caller. |
| 586 | */ | 598 | */ |
| 587 | void ata_rwcmd_protocol(struct ata_queued_cmd *qc) | 599 | int ata_rwcmd_protocol(struct ata_queued_cmd *qc) |
| 588 | { | 600 | { |
| 589 | struct ata_taskfile *tf = &qc->tf; | 601 | struct ata_taskfile *tf = &qc->tf; |
| 590 | struct ata_device *dev = qc->dev; | 602 | struct ata_device *dev = qc->dev; |
| 603 | u8 cmd; | ||
| 591 | 604 | ||
| 592 | int index, lba48, write; | 605 | int index, fua, lba48, write; |
| 593 | 606 | ||
| 607 | fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0; | ||
| 594 | lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; | 608 | lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; |
| 595 | write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; | 609 | write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; |
| 596 | 610 | ||
| 597 | if (dev->flags & ATA_DFLAG_PIO) { | 611 | if (dev->flags & ATA_DFLAG_PIO) { |
| 598 | tf->protocol = ATA_PROT_PIO; | 612 | tf->protocol = ATA_PROT_PIO; |
| 599 | index = dev->multi_count ? 0 : 4; | 613 | index = dev->multi_count ? 0 : 8; |
| 600 | } else { | 614 | } else { |
| 601 | tf->protocol = ATA_PROT_DMA; | 615 | tf->protocol = ATA_PROT_DMA; |
| 602 | index = 8; | 616 | index = 16; |
| 603 | } | 617 | } |
| 604 | 618 | ||
| 605 | tf->command = ata_rw_cmds[index + lba48 + write]; | 619 | cmd = ata_rw_cmds[index + fua + lba48 + write]; |
| 620 | if (cmd) { | ||
| 621 | tf->command = cmd; | ||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | return -1; | ||
| 606 | } | 625 | } |
| 607 | 626 | ||
| 608 | static const char * const xfer_mode_str[] = { | 627 | static const char * const xfer_mode_str[] = { |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index e0439be4b573..2c644cbb6e9c 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
| @@ -1080,11 +1080,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
| 1080 | scsicmd[0] == WRITE_16) | 1080 | scsicmd[0] == WRITE_16) |
| 1081 | tf->flags |= ATA_TFLAG_WRITE; | 1081 | tf->flags |= ATA_TFLAG_WRITE; |
| 1082 | 1082 | ||
| 1083 | /* Calculate the SCSI LBA and transfer length. */ | 1083 | /* Calculate the SCSI LBA, transfer length and FUA. */ |
| 1084 | switch (scsicmd[0]) { | 1084 | switch (scsicmd[0]) { |
| 1085 | case READ_10: | 1085 | case READ_10: |
| 1086 | case WRITE_10: | 1086 | case WRITE_10: |
| 1087 | scsi_10_lba_len(scsicmd, &block, &n_block); | 1087 | scsi_10_lba_len(scsicmd, &block, &n_block); |
| 1088 | if (unlikely(scsicmd[1] & (1 << 3))) | ||
| 1089 | tf->flags |= ATA_TFLAG_FUA; | ||
| 1088 | break; | 1090 | break; |
| 1089 | case READ_6: | 1091 | case READ_6: |
| 1090 | case WRITE_6: | 1092 | case WRITE_6: |
| @@ -1099,6 +1101,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
| 1099 | case READ_16: | 1101 | case READ_16: |
| 1100 | case WRITE_16: | 1102 | case WRITE_16: |
| 1101 | scsi_16_lba_len(scsicmd, &block, &n_block); | 1103 | scsi_16_lba_len(scsicmd, &block, &n_block); |
| 1104 | if (unlikely(scsicmd[1] & (1 << 3))) | ||
| 1105 | tf->flags |= ATA_TFLAG_FUA; | ||
| 1102 | break; | 1106 | break; |
| 1103 | default: | 1107 | default: |
| 1104 | DPRINTK("no-byte command\n"); | 1108 | DPRINTK("no-byte command\n"); |
| @@ -1142,7 +1146,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
| 1142 | tf->device |= (block >> 24) & 0xf; | 1146 | tf->device |= (block >> 24) & 0xf; |
| 1143 | } | 1147 | } |
| 1144 | 1148 | ||
| 1145 | ata_rwcmd_protocol(qc); | 1149 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) |
| 1150 | goto invalid_fld; | ||
| 1146 | 1151 | ||
| 1147 | qc->nsect = n_block; | 1152 | qc->nsect = n_block; |
| 1148 | tf->nsect = n_block & 0xff; | 1153 | tf->nsect = n_block & 0xff; |
| @@ -1160,7 +1165,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
| 1160 | if ((block >> 28) || (n_block > 256)) | 1165 | if ((block >> 28) || (n_block > 256)) |
| 1161 | goto out_of_range; | 1166 | goto out_of_range; |
| 1162 | 1167 | ||
| 1163 | ata_rwcmd_protocol(qc); | 1168 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) |
| 1169 | goto invalid_fld; | ||
| 1164 | 1170 | ||
| 1165 | /* Convert LBA to CHS */ | 1171 | /* Convert LBA to CHS */ |
| 1166 | track = (u32)block / dev->sectors; | 1172 | track = (u32)block / dev->sectors; |
| @@ -1695,6 +1701,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) | |||
| 1695 | unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | 1701 | unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, |
| 1696 | unsigned int buflen) | 1702 | unsigned int buflen) |
| 1697 | { | 1703 | { |
| 1704 | struct ata_device *dev = args->dev; | ||
| 1698 | u8 *scsicmd = args->cmd->cmnd, *p, *last; | 1705 | u8 *scsicmd = args->cmd->cmnd, *p, *last; |
| 1699 | const u8 sat_blk_desc[] = { | 1706 | const u8 sat_blk_desc[] = { |
| 1700 | 0, 0, 0, 0, /* number of blocks: sat unspecified */ | 1707 | 0, 0, 0, 0, /* number of blocks: sat unspecified */ |
| @@ -1703,6 +1710,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
| 1703 | }; | 1710 | }; |
| 1704 | u8 pg, spg; | 1711 | u8 pg, spg; |
| 1705 | unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; | 1712 | unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; |
| 1713 | u8 dpofua; | ||
| 1706 | 1714 | ||
| 1707 | VPRINTK("ENTER\n"); | 1715 | VPRINTK("ENTER\n"); |
| 1708 | 1716 | ||
| @@ -1771,9 +1779,17 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
| 1771 | 1779 | ||
| 1772 | if (minlen < 1) | 1780 | if (minlen < 1) |
| 1773 | return 0; | 1781 | return 0; |
| 1782 | |||
| 1783 | dpofua = 0; | ||
| 1784 | if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && | ||
| 1785 | (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) | ||
| 1786 | dpofua = 1 << 4; | ||
| 1787 | |||
| 1774 | if (six_byte) { | 1788 | if (six_byte) { |
| 1775 | output_len--; | 1789 | output_len--; |
| 1776 | rbuf[0] = output_len; | 1790 | rbuf[0] = output_len; |
| 1791 | if (minlen > 2) | ||
| 1792 | rbuf[2] |= dpofua; | ||
| 1777 | if (ebd) { | 1793 | if (ebd) { |
| 1778 | if (minlen > 3) | 1794 | if (minlen > 3) |
| 1779 | rbuf[3] = sizeof(sat_blk_desc); | 1795 | rbuf[3] = sizeof(sat_blk_desc); |
| @@ -1786,6 +1802,8 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
| 1786 | rbuf[0] = output_len >> 8; | 1802 | rbuf[0] = output_len >> 8; |
| 1787 | if (minlen > 1) | 1803 | if (minlen > 1) |
| 1788 | rbuf[1] = output_len; | 1804 | rbuf[1] = output_len; |
| 1805 | if (minlen > 3) | ||
| 1806 | rbuf[3] |= dpofua; | ||
| 1789 | if (ebd) { | 1807 | if (ebd) { |
| 1790 | if (minlen > 7) | 1808 | if (minlen > 7) |
| 1791 | rbuf[7] = sizeof(sat_blk_desc); | 1809 | rbuf[7] = sizeof(sat_blk_desc); |
| @@ -2446,7 +2464,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
| 2446 | if (xlat_func) | 2464 | if (xlat_func) |
| 2447 | ata_scsi_translate(ap, dev, cmd, done, xlat_func); | 2465 | ata_scsi_translate(ap, dev, cmd, done, xlat_func); |
| 2448 | else | 2466 | else |
| 2449 | ata_scsi_simulate(dev->id, cmd, done); | 2467 | ata_scsi_simulate(ap, dev, cmd, done); |
| 2450 | } else | 2468 | } else |
| 2451 | ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); | 2469 | ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); |
| 2452 | 2470 | ||
| @@ -2469,14 +2487,16 @@ out_unlock: | |||
| 2469 | * spin_lock_irqsave(host_set lock) | 2487 | * spin_lock_irqsave(host_set lock) |
| 2470 | */ | 2488 | */ |
| 2471 | 2489 | ||
| 2472 | void ata_scsi_simulate(u16 *id, | 2490 | void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, |
| 2473 | struct scsi_cmnd *cmd, | 2491 | struct scsi_cmnd *cmd, |
| 2474 | void (*done)(struct scsi_cmnd *)) | 2492 | void (*done)(struct scsi_cmnd *)) |
| 2475 | { | 2493 | { |
| 2476 | struct ata_scsi_args args; | 2494 | struct ata_scsi_args args; |
| 2477 | const u8 *scsicmd = cmd->cmnd; | 2495 | const u8 *scsicmd = cmd->cmnd; |
| 2478 | 2496 | ||
| 2479 | args.id = id; | 2497 | args.ap = ap; |
| 2498 | args.dev = dev; | ||
| 2499 | args.id = dev->id; | ||
| 2480 | args.cmd = cmd; | 2500 | args.cmd = cmd; |
| 2481 | args.done = done; | 2501 | args.done = done; |
| 2482 | 2502 | ||
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 251e53bdc6e0..e03ce48b7b4b 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #define DRV_VERSION "1.20" /* must be exactly four chars */ | 32 | #define DRV_VERSION "1.20" /* must be exactly four chars */ |
| 33 | 33 | ||
| 34 | struct ata_scsi_args { | 34 | struct ata_scsi_args { |
| 35 | struct ata_port *ap; | ||
| 36 | struct ata_device *dev; | ||
| 35 | u16 *id; | 37 | u16 *id; |
| 36 | struct scsi_cmnd *cmd; | 38 | struct scsi_cmnd *cmd; |
| 37 | void (*done)(struct scsi_cmnd *); | 39 | void (*done)(struct scsi_cmnd *); |
| @@ -41,7 +43,7 @@ struct ata_scsi_args { | |||
| 41 | extern int atapi_enabled; | 43 | extern int atapi_enabled; |
| 42 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, | 44 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, |
| 43 | struct ata_device *dev); | 45 | struct ata_device *dev); |
| 44 | extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc); | 46 | extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); |
| 45 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 47 | extern void ata_qc_free(struct ata_queued_cmd *qc); |
| 46 | extern int ata_qc_issue(struct ata_queued_cmd *qc); | 48 | extern int ata_qc_issue(struct ata_queued_cmd *qc); |
| 47 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); | 49 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); |
diff --git a/include/linux/ata.h b/include/linux/ata.h index d2873b732bb1..f63dad4165b1 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
| @@ -129,6 +129,7 @@ enum { | |||
| 129 | ATA_CMD_READ_EXT = 0x25, | 129 | ATA_CMD_READ_EXT = 0x25, |
| 130 | ATA_CMD_WRITE = 0xCA, | 130 | ATA_CMD_WRITE = 0xCA, |
| 131 | ATA_CMD_WRITE_EXT = 0x35, | 131 | ATA_CMD_WRITE_EXT = 0x35, |
| 132 | ATA_CMD_WRITE_FUA_EXT = 0x3D, | ||
| 132 | ATA_CMD_PIO_READ = 0x20, | 133 | ATA_CMD_PIO_READ = 0x20, |
| 133 | ATA_CMD_PIO_READ_EXT = 0x24, | 134 | ATA_CMD_PIO_READ_EXT = 0x24, |
| 134 | ATA_CMD_PIO_WRITE = 0x30, | 135 | ATA_CMD_PIO_WRITE = 0x30, |
| @@ -137,6 +138,7 @@ enum { | |||
| 137 | ATA_CMD_READ_MULTI_EXT = 0x29, | 138 | ATA_CMD_READ_MULTI_EXT = 0x29, |
| 138 | ATA_CMD_WRITE_MULTI = 0xC5, | 139 | ATA_CMD_WRITE_MULTI = 0xC5, |
| 139 | ATA_CMD_WRITE_MULTI_EXT = 0x39, | 140 | ATA_CMD_WRITE_MULTI_EXT = 0x39, |
| 141 | ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE, | ||
| 140 | ATA_CMD_SET_FEATURES = 0xEF, | 142 | ATA_CMD_SET_FEATURES = 0xEF, |
| 141 | ATA_CMD_PACKET = 0xA0, | 143 | ATA_CMD_PACKET = 0xA0, |
| 142 | ATA_CMD_VERIFY = 0x40, | 144 | ATA_CMD_VERIFY = 0x40, |
| @@ -192,6 +194,7 @@ enum { | |||
| 192 | ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ | 194 | ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ |
| 193 | ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ | 195 | ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ |
| 194 | ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ | 196 | ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ |
| 197 | ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ | ||
| 195 | }; | 198 | }; |
| 196 | 199 | ||
| 197 | enum ata_tf_protocols { | 200 | enum ata_tf_protocols { |
| @@ -245,7 +248,8 @@ struct ata_taskfile { | |||
| 245 | #define ata_id_is_sata(id) ((id)[93] == 0) | 248 | #define ata_id_is_sata(id) ((id)[93] == 0) |
| 246 | #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) | 249 | #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) |
| 247 | #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) | 250 | #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) |
| 248 | #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) | 251 | #define ata_id_has_fua(id) ((id)[84] & (1 << 6)) |
| 252 | #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) | ||
| 249 | #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) | 253 | #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) |
| 250 | #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) | 254 | #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) |
| 251 | #define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) | 255 | #define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) |
diff --git a/include/linux/libata.h b/include/linux/libata.h index e828e172ccbf..6db2c0845731 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -480,7 +480,8 @@ extern u8 ata_bmdma_status(struct ata_port *ap); | |||
| 480 | extern void ata_bmdma_irq_clear(struct ata_port *ap); | 480 | extern void ata_bmdma_irq_clear(struct ata_port *ap); |
| 481 | extern void ata_qc_complete(struct ata_queued_cmd *qc); | 481 | extern void ata_qc_complete(struct ata_queued_cmd *qc); |
| 482 | extern void ata_eng_timeout(struct ata_port *ap); | 482 | extern void ata_eng_timeout(struct ata_port *ap); |
| 483 | extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, | 483 | extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, |
| 484 | struct scsi_cmnd *cmd, | ||
| 484 | void (*done)(struct scsi_cmnd *)); | 485 | void (*done)(struct scsi_cmnd *)); |
| 485 | extern int ata_std_bios_param(struct scsi_device *sdev, | 486 | extern int ata_std_bios_param(struct scsi_device *sdev, |
| 486 | struct block_device *bdev, | 487 | struct block_device *bdev, |
