diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
| -rw-r--r-- | drivers/ata/libata-sff.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 0b299b0f8172..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 | ||
