diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 0eae9b453556..714cb046b594 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -773,18 +773,32 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf, | |||
773 | else | 773 | else |
774 | iowrite32_rep(data_addr, buf, words); | 774 | iowrite32_rep(data_addr, buf, words); |
775 | 775 | ||
776 | /* Transfer trailing bytes, if any */ | ||
776 | if (unlikely(slop)) { | 777 | if (unlikely(slop)) { |
777 | __le32 pad; | 778 | unsigned char pad[4]; |
779 | |||
780 | /* Point buf to the tail of buffer */ | ||
781 | buf += buflen - slop; | ||
782 | |||
783 | /* | ||
784 | * Use io*_rep() accessors here as well to avoid pointlessly | ||
785 | * swapping bytes to and fro on the big endian machines... | ||
786 | */ | ||
778 | if (rw == READ) { | 787 | if (rw == READ) { |
779 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); | 788 | if (slop < 3) |
780 | memcpy(buf + buflen - slop, &pad, slop); | 789 | ioread16_rep(data_addr, pad, 1); |
790 | else | ||
791 | ioread32_rep(data_addr, pad, 1); | ||
792 | memcpy(buf, pad, slop); | ||
781 | } else { | 793 | } else { |
782 | memcpy(&pad, buf + buflen - slop, slop); | 794 | memcpy(pad, buf, slop); |
783 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | 795 | if (slop < 3) |
796 | iowrite16_rep(data_addr, pad, 1); | ||
797 | else | ||
798 | iowrite32_rep(data_addr, pad, 1); | ||
784 | } | 799 | } |
785 | words++; | ||
786 | } | 800 | } |
787 | return words << 2; | 801 | return (buflen + 1) & ~1; |
788 | } | 802 | } |
789 | EXPORT_SYMBOL_GPL(ata_sff_data_xfer32); | 803 | EXPORT_SYMBOL_GPL(ata_sff_data_xfer32); |
790 | 804 | ||
@@ -1013,9 +1027,12 @@ next_sg: | |||
1013 | qc->cursg_ofs = 0; | 1027 | qc->cursg_ofs = 0; |
1014 | } | 1028 | } |
1015 | 1029 | ||
1016 | /* consumed can be larger than count only for the last transfer */ | 1030 | /* |
1017 | WARN_ON_ONCE(qc->cursg && count != consumed); | 1031 | * There used to be a WARN_ON_ONCE(qc->cursg && count != consumed); |
1018 | 1032 | * Unfortunately __atapi_pio_bytes doesn't know enough to do the WARN | |
1033 | * check correctly as it doesn't know if it is the last request being | ||
1034 | * made. Somebody should implement a proper sanity check. | ||
1035 | */ | ||
1019 | if (bytes) | 1036 | if (bytes) |
1020 | goto next_sg; | 1037 | goto next_sg; |
1021 | return 0; | 1038 | return 0; |
@@ -1319,7 +1336,7 @@ fsm_start: | |||
1319 | * condition. Mark hint. | 1336 | * condition. Mark hint. |
1320 | */ | 1337 | */ |
1321 | ata_ehi_push_desc(ehi, "ST-ATA: " | 1338 | ata_ehi_push_desc(ehi, "ST-ATA: " |
1322 | "DRQ=1 with device error, " | 1339 | "DRQ=0 without device error, " |
1323 | "dev_stat 0x%X", status); | 1340 | "dev_stat 0x%X", status); |
1324 | qc->err_mask |= AC_ERR_HSM | | 1341 | qc->err_mask |= AC_ERR_HSM | |
1325 | AC_ERR_NODEV_HINT; | 1342 | AC_ERR_NODEV_HINT; |
@@ -1355,6 +1372,16 @@ fsm_start: | |||
1355 | qc->err_mask |= AC_ERR_HSM; | 1372 | qc->err_mask |= AC_ERR_HSM; |
1356 | } | 1373 | } |
1357 | 1374 | ||
1375 | /* There are oddball controllers with | ||
1376 | * status register stuck at 0x7f and | ||
1377 | * lbal/m/h at zero which makes it | ||
1378 | * pass all other presence detection | ||
1379 | * mechanisms we have. Set NODEV_HINT | ||
1380 | * for it. Kernel bz#7241. | ||
1381 | */ | ||
1382 | if (status == 0x7f) | ||
1383 | qc->err_mask |= AC_ERR_NODEV_HINT; | ||
1384 | |||
1358 | /* ata_pio_sectors() might change the | 1385 | /* ata_pio_sectors() might change the |
1359 | * state to HSM_ST_LAST. so, the state | 1386 | * state to HSM_ST_LAST. so, the state |
1360 | * is changed after ata_pio_sectors(). | 1387 | * is changed after ata_pio_sectors(). |