diff options
author | Grant Grundler <grundler@google.com> | 2010-08-17 13:56:53 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2010-10-21 20:21:03 -0400 |
commit | 295124dce4ddfd40b1f12d3ffd2779673e87c701 (patch) | |
tree | cccdc9d6270fbc72b9147050232c627f7ddee23b | |
parent | 1aadf5c3bbbbb0db09dcb5aa26c61326e0d3e9e7 (diff) |
[libata] support for > 512 byte sectors (e.g. 4K Native)
This change enables my x86 machine to recognize and talk to a
"Native 4K" SATA device.
When I started working on this, I didn't know Matthew Wilcox had
posted a similar patch 2 years ago:
http://git.kernel.org/?p=linux/kernel/git/willy/ata.git;a=shortlog;h=refs/heads/ata-large-sectors
Gwendal Grignou pointed me at the the above code and small portions of
this patch include Matthew's work. That's why Mathew is first on the
"Signed-off-by:". I've NOT included his use of a bitmap to determine
512 vs Native for ATA command block size - just used a simple table.
And bugs are almost certainly mine.
Lastly, the patch has been tested with a native 4K 'Engineering
Sample' drive provided by Hitachi GST.
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Signed-off-by: Grant Grundler <grundler@google.com>
Reviewed-by: Gwendal Grignou <gwendal@google.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/libata-scsi.c | 96 | ||||
-rw-r--r-- | include/linux/ata.h | 46 |
2 files changed, 105 insertions, 37 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index c16f5c15173..f1c0118c6d4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include "libata.h" | 53 | #include "libata.h" |
54 | #include "libata-transport.h" | 54 | #include "libata-transport.h" |
55 | 55 | ||
56 | #define SECTOR_SIZE 512 | ||
57 | #define ATA_SCSI_RBUF_SIZE 4096 | 56 | #define ATA_SCSI_RBUF_SIZE 4096 |
58 | 57 | ||
59 | static DEFINE_SPINLOCK(ata_scsi_rbuf_lock); | 58 | static DEFINE_SPINLOCK(ata_scsi_rbuf_lock); |
@@ -503,7 +502,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
503 | memset(scsi_cmd, 0, sizeof(scsi_cmd)); | 502 | memset(scsi_cmd, 0, sizeof(scsi_cmd)); |
504 | 503 | ||
505 | if (args[3]) { | 504 | if (args[3]) { |
506 | argsize = SECTOR_SIZE * args[3]; | 505 | argsize = ATA_SECT_SIZE * args[3]; |
507 | argbuf = kmalloc(argsize, GFP_KERNEL); | 506 | argbuf = kmalloc(argsize, GFP_KERNEL); |
508 | if (argbuf == NULL) { | 507 | if (argbuf == NULL) { |
509 | rc = -ENOMEM; | 508 | rc = -ENOMEM; |
@@ -1137,8 +1136,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, | |||
1137 | blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); | 1136 | blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); |
1138 | } else { | 1137 | } else { |
1139 | /* ATA devices must be sector aligned */ | 1138 | /* ATA devices must be sector aligned */ |
1139 | sdev->sector_size = ata_id_logical_sector_size(dev->id); | ||
1140 | blk_queue_update_dma_alignment(sdev->request_queue, | 1140 | blk_queue_update_dma_alignment(sdev->request_queue, |
1141 | ATA_SECT_SIZE - 1); | 1141 | sdev->sector_size - 1); |
1142 | sdev->manage_start_stop = 1; | 1142 | sdev->manage_start_stop = 1; |
1143 | } | 1143 | } |
1144 | 1144 | ||
@@ -1153,6 +1153,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, | |||
1153 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); | 1153 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | dev->sdev = sdev; | ||
1156 | return 0; | 1157 | return 0; |
1157 | } | 1158 | } |
1158 | 1159 | ||
@@ -1683,7 +1684,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) | |||
1683 | goto nothing_to_do; | 1684 | goto nothing_to_do; |
1684 | 1685 | ||
1685 | qc->flags |= ATA_QCFLAG_IO; | 1686 | qc->flags |= ATA_QCFLAG_IO; |
1686 | qc->nbytes = n_block * ATA_SECT_SIZE; | 1687 | qc->nbytes = n_block * scmd->device->sector_size; |
1687 | 1688 | ||
1688 | rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, | 1689 | rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, |
1689 | qc->tag); | 1690 | qc->tag); |
@@ -2110,7 +2111,7 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf) | |||
2110 | 2111 | ||
2111 | static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) | 2112 | static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) |
2112 | { | 2113 | { |
2113 | u32 min_io_sectors; | 2114 | u16 min_io_sectors; |
2114 | 2115 | ||
2115 | rbuf[1] = 0xb0; | 2116 | rbuf[1] = 0xb0; |
2116 | rbuf[3] = 0x3c; /* required VPD size with unmap support */ | 2117 | rbuf[3] = 0x3c; /* required VPD size with unmap support */ |
@@ -2122,10 +2123,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) | |||
2122 | * logical than physical sector size we need to figure out what the | 2123 | * logical than physical sector size we need to figure out what the |
2123 | * latter is. | 2124 | * latter is. |
2124 | */ | 2125 | */ |
2125 | if (ata_id_has_large_logical_sectors(args->id)) | 2126 | min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id); |
2126 | min_io_sectors = ata_id_logical_per_physical_sectors(args->id); | ||
2127 | else | ||
2128 | min_io_sectors = 1; | ||
2129 | put_unaligned_be16(min_io_sectors, &rbuf[6]); | 2127 | put_unaligned_be16(min_io_sectors, &rbuf[6]); |
2130 | 2128 | ||
2131 | /* | 2129 | /* |
@@ -2384,21 +2382,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) | |||
2384 | { | 2382 | { |
2385 | struct ata_device *dev = args->dev; | 2383 | struct ata_device *dev = args->dev; |
2386 | u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */ | 2384 | u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */ |
2387 | u8 log_per_phys = 0; | 2385 | u32 sector_size; /* physical sector size in bytes */ |
2388 | u16 lowest_aligned = 0; | 2386 | u8 log2_per_phys; |
2389 | u16 word_106 = dev->id[106]; | 2387 | u16 lowest_aligned; |
2390 | u16 word_209 = dev->id[209]; | 2388 | |
2391 | 2389 | sector_size = ata_id_logical_sector_size(dev->id); | |
2392 | if ((word_106 & 0xc000) == 0x4000) { | 2390 | log2_per_phys = ata_id_log2_per_physical_sector(dev->id); |
2393 | /* Number and offset of logical sectors per physical sector */ | 2391 | lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys); |
2394 | if (word_106 & (1 << 13)) | ||
2395 | log_per_phys = word_106 & 0xf; | ||
2396 | if ((word_209 & 0xc000) == 0x4000) { | ||
2397 | u16 first = dev->id[209] & 0x3fff; | ||
2398 | if (first > 0) | ||
2399 | lowest_aligned = (1 << log_per_phys) - first; | ||
2400 | } | ||
2401 | } | ||
2402 | 2392 | ||
2403 | VPRINTK("ENTER\n"); | 2393 | VPRINTK("ENTER\n"); |
2404 | 2394 | ||
@@ -2413,8 +2403,10 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) | |||
2413 | rbuf[3] = last_lba; | 2403 | rbuf[3] = last_lba; |
2414 | 2404 | ||
2415 | /* sector size */ | 2405 | /* sector size */ |
2416 | rbuf[6] = ATA_SECT_SIZE >> 8; | 2406 | rbuf[4] = sector_size >> (8 * 3); |
2417 | rbuf[7] = ATA_SECT_SIZE & 0xff; | 2407 | rbuf[5] = sector_size >> (8 * 2); |
2408 | rbuf[6] = sector_size >> (8 * 1); | ||
2409 | rbuf[7] = sector_size; | ||
2418 | } else { | 2410 | } else { |
2419 | /* sector count, 64-bit */ | 2411 | /* sector count, 64-bit */ |
2420 | rbuf[0] = last_lba >> (8 * 7); | 2412 | rbuf[0] = last_lba >> (8 * 7); |
@@ -2427,11 +2419,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) | |||
2427 | rbuf[7] = last_lba; | 2419 | rbuf[7] = last_lba; |
2428 | 2420 | ||
2429 | /* sector size */ | 2421 | /* sector size */ |
2430 | rbuf[10] = ATA_SECT_SIZE >> 8; | 2422 | rbuf[ 8] = sector_size >> (8 * 3); |
2431 | rbuf[11] = ATA_SECT_SIZE & 0xff; | 2423 | rbuf[ 9] = sector_size >> (8 * 2); |
2424 | rbuf[10] = sector_size >> (8 * 1); | ||
2425 | rbuf[11] = sector_size; | ||
2432 | 2426 | ||
2433 | rbuf[12] = 0; | 2427 | rbuf[12] = 0; |
2434 | rbuf[13] = log_per_phys; | 2428 | rbuf[13] = log2_per_phys; |
2435 | rbuf[14] = (lowest_aligned >> 8) & 0x3f; | 2429 | rbuf[14] = (lowest_aligned >> 8) & 0x3f; |
2436 | rbuf[15] = lowest_aligned; | 2430 | rbuf[15] = lowest_aligned; |
2437 | 2431 | ||
@@ -2875,9 +2869,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
2875 | tf->device = dev->devno ? | 2869 | tf->device = dev->devno ? |
2876 | tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; | 2870 | tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; |
2877 | 2871 | ||
2878 | /* READ/WRITE LONG use a non-standard sect_size */ | ||
2879 | qc->sect_size = ATA_SECT_SIZE; | ||
2880 | switch (tf->command) { | 2872 | switch (tf->command) { |
2873 | /* READ/WRITE LONG use a non-standard sect_size */ | ||
2881 | case ATA_CMD_READ_LONG: | 2874 | case ATA_CMD_READ_LONG: |
2882 | case ATA_CMD_READ_LONG_ONCE: | 2875 | case ATA_CMD_READ_LONG_ONCE: |
2883 | case ATA_CMD_WRITE_LONG: | 2876 | case ATA_CMD_WRITE_LONG: |
@@ -2885,6 +2878,45 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
2885 | if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) | 2878 | if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) |
2886 | goto invalid_fld; | 2879 | goto invalid_fld; |
2887 | qc->sect_size = scsi_bufflen(scmd); | 2880 | qc->sect_size = scsi_bufflen(scmd); |
2881 | break; | ||
2882 | |||
2883 | /* commands using reported Logical Block size (e.g. 512 or 4K) */ | ||
2884 | case ATA_CMD_CFA_WRITE_NE: | ||
2885 | case ATA_CMD_CFA_TRANS_SECT: | ||
2886 | case ATA_CMD_CFA_WRITE_MULT_NE: | ||
2887 | /* XXX: case ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE: */ | ||
2888 | case ATA_CMD_READ: | ||
2889 | case ATA_CMD_READ_EXT: | ||
2890 | case ATA_CMD_READ_QUEUED: | ||
2891 | /* XXX: case ATA_CMD_READ_QUEUED_EXT: */ | ||
2892 | case ATA_CMD_FPDMA_READ: | ||
2893 | case ATA_CMD_READ_MULTI: | ||
2894 | case ATA_CMD_READ_MULTI_EXT: | ||
2895 | case ATA_CMD_PIO_READ: | ||
2896 | case ATA_CMD_PIO_READ_EXT: | ||
2897 | case ATA_CMD_READ_STREAM_DMA_EXT: | ||
2898 | case ATA_CMD_READ_STREAM_EXT: | ||
2899 | case ATA_CMD_VERIFY: | ||
2900 | case ATA_CMD_VERIFY_EXT: | ||
2901 | case ATA_CMD_WRITE: | ||
2902 | case ATA_CMD_WRITE_EXT: | ||
2903 | case ATA_CMD_WRITE_FUA_EXT: | ||
2904 | case ATA_CMD_WRITE_QUEUED: | ||
2905 | case ATA_CMD_WRITE_QUEUED_FUA_EXT: | ||
2906 | case ATA_CMD_FPDMA_WRITE: | ||
2907 | case ATA_CMD_WRITE_MULTI: | ||
2908 | case ATA_CMD_WRITE_MULTI_EXT: | ||
2909 | case ATA_CMD_WRITE_MULTI_FUA_EXT: | ||
2910 | case ATA_CMD_PIO_WRITE: | ||
2911 | case ATA_CMD_PIO_WRITE_EXT: | ||
2912 | case ATA_CMD_WRITE_STREAM_DMA_EXT: | ||
2913 | case ATA_CMD_WRITE_STREAM_EXT: | ||
2914 | qc->sect_size = scmd->device->sector_size; | ||
2915 | break; | ||
2916 | |||
2917 | /* Everything else uses 512 byte "sectors" */ | ||
2918 | default: | ||
2919 | qc->sect_size = ATA_SECT_SIZE; | ||
2888 | } | 2920 | } |
2889 | 2921 | ||
2890 | /* | 2922 | /* |
@@ -3380,6 +3412,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) | |||
3380 | if (!IS_ERR(sdev)) { | 3412 | if (!IS_ERR(sdev)) { |
3381 | dev->sdev = sdev; | 3413 | dev->sdev = sdev; |
3382 | scsi_device_put(sdev); | 3414 | scsi_device_put(sdev); |
3415 | } else { | ||
3416 | dev->sdev = NULL; | ||
3383 | } | 3417 | } |
3384 | } | 3418 | } |
3385 | } | 3419 | } |
diff --git a/include/linux/ata.h b/include/linux/ata.h index fe6e681a9d7..0c4929fa34d 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -89,6 +89,7 @@ enum { | |||
89 | ATA_ID_SPG = 98, | 89 | ATA_ID_SPG = 98, |
90 | ATA_ID_LBA_CAPACITY_2 = 100, | 90 | ATA_ID_LBA_CAPACITY_2 = 100, |
91 | ATA_ID_SECTOR_SIZE = 106, | 91 | ATA_ID_SECTOR_SIZE = 106, |
92 | ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */ | ||
92 | ATA_ID_LAST_LUN = 126, | 93 | ATA_ID_LAST_LUN = 126, |
93 | ATA_ID_DLF = 128, | 94 | ATA_ID_DLF = 128, |
94 | ATA_ID_CSFO = 129, | 95 | ATA_ID_CSFO = 129, |
@@ -640,16 +641,49 @@ static inline int ata_id_flush_ext_enabled(const u16 *id) | |||
640 | return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400; | 641 | return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400; |
641 | } | 642 | } |
642 | 643 | ||
643 | static inline int ata_id_has_large_logical_sectors(const u16 *id) | 644 | static inline u32 ata_id_logical_sector_size(const u16 *id) |
644 | { | 645 | { |
645 | if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000) | 646 | /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128. |
646 | return 0; | 647 | * IDENTIFY DEVICE data, word 117-118. |
647 | return id[ATA_ID_SECTOR_SIZE] & (1 << 13); | 648 | * 0xd000 ignores bit 13 (logical:physical > 1) |
649 | */ | ||
650 | if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000) | ||
651 | return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16) | ||
652 | + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ; | ||
653 | return ATA_SECT_SIZE; | ||
654 | } | ||
655 | |||
656 | static inline u8 ata_id_log2_per_physical_sector(const u16 *id) | ||
657 | { | ||
658 | /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128. | ||
659 | * IDENTIFY DEVICE data, word 106. | ||
660 | * 0xe000 ignores bit 12 (logical sector > 512 bytes) | ||
661 | */ | ||
662 | if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000) | ||
663 | return (id[ATA_ID_SECTOR_SIZE] & 0xf); | ||
664 | return 0; | ||
648 | } | 665 | } |
649 | 666 | ||
650 | static inline u16 ata_id_logical_per_physical_sectors(const u16 *id) | 667 | /* Offset of logical sectors relative to physical sectors. |
668 | * | ||
669 | * If device has more than one logical sector per physical sector | ||
670 | * (aka 512 byte emulation), vendors might offset the "sector 0" address | ||
671 | * so sector 63 is "naturally aligned" - e.g. FAT partition table. | ||
672 | * This avoids Read/Mod/Write penalties when using FAT partition table | ||
673 | * and updating "well aligned" (FS perspective) physical sectors on every | ||
674 | * transaction. | ||
675 | */ | ||
676 | static inline u16 ata_id_logical_sector_offset(const u16 *id, | ||
677 | u8 log2_per_phys) | ||
651 | { | 678 | { |
652 | return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf); | 679 | u16 word_209 = id[209]; |
680 | |||
681 | if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) { | ||
682 | u16 first = word_209 & 0x3fff; | ||
683 | if (first > 0) | ||
684 | return (1 << log2_per_phys) - first; | ||
685 | } | ||
686 | return 0; | ||
653 | } | 687 | } |
654 | 688 | ||
655 | static inline int ata_id_has_lba48(const u16 *id) | 689 | static inline int ata_id_has_lba48(const u16 *id) |