aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2c9745a74d50..39cedd949ed4 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4994,7 +4994,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
4994 4994
4995/** 4995/**
4996 * ata_data_xfer - Transfer data by PIO 4996 * ata_data_xfer - Transfer data by PIO
4997 * @adev: device to target 4997 * @dev: device to target
4998 * @buf: data buffer 4998 * @buf: data buffer
4999 * @buflen: buffer length 4999 * @buflen: buffer length
5000 * @write_data: read/write 5000 * @write_data: read/write
@@ -5003,37 +5003,44 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
5003 * 5003 *
5004 * LOCKING: 5004 * LOCKING:
5005 * Inherited from caller. 5005 * Inherited from caller.
5006 *
5007 * RETURNS:
5008 * Bytes consumed.
5006 */ 5009 */
5007void ata_data_xfer(struct ata_device *adev, unsigned char *buf, 5010unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
5008 unsigned int buflen, int write_data) 5011 unsigned int buflen, int rw)
5009{ 5012{
5010 struct ata_port *ap = adev->link->ap; 5013 struct ata_port *ap = dev->link->ap;
5014 void __iomem *data_addr = ap->ioaddr.data_addr;
5011 unsigned int words = buflen >> 1; 5015 unsigned int words = buflen >> 1;
5012 5016
5013 /* Transfer multiple of 2 bytes */ 5017 /* Transfer multiple of 2 bytes */
5014 if (write_data) 5018 if (rw == READ)
5015 iowrite16_rep(ap->ioaddr.data_addr, buf, words); 5019 ioread16_rep(data_addr, buf, words);
5016 else 5020 else
5017 ioread16_rep(ap->ioaddr.data_addr, buf, words); 5021 iowrite16_rep(data_addr, buf, words);
5018 5022
5019 /* Transfer trailing 1 byte, if any. */ 5023 /* Transfer trailing 1 byte, if any. */
5020 if (unlikely(buflen & 0x01)) { 5024 if (unlikely(buflen & 0x01)) {
5021 u16 align_buf[1] = { 0 }; 5025 u16 align_buf[1] = { 0 };
5022 unsigned char *trailing_buf = buf + buflen - 1; 5026 unsigned char *trailing_buf = buf + buflen - 1;
5023 5027
5024 if (write_data) { 5028 if (rw == READ) {
5025 memcpy(align_buf, trailing_buf, 1); 5029 align_buf[0] = cpu_to_le16(ioread16(data_addr));
5026 iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
5027 } else {
5028 align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
5029 memcpy(trailing_buf, align_buf, 1); 5030 memcpy(trailing_buf, align_buf, 1);
5031 } else {
5032 memcpy(align_buf, trailing_buf, 1);
5033 iowrite16(le16_to_cpu(align_buf[0]), data_addr);
5030 } 5034 }
5035 words++;
5031 } 5036 }
5037
5038 return words << 1;
5032} 5039}
5033 5040
5034/** 5041/**
5035 * ata_data_xfer_noirq - Transfer data by PIO 5042 * ata_data_xfer_noirq - Transfer data by PIO
5036 * @adev: device to target 5043 * @dev: device to target
5037 * @buf: data buffer 5044 * @buf: data buffer
5038 * @buflen: buffer length 5045 * @buflen: buffer length
5039 * @write_data: read/write 5046 * @write_data: read/write
@@ -5043,14 +5050,21 @@ void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
5043 * 5050 *
5044 * LOCKING: 5051 * LOCKING:
5045 * Inherited from caller. 5052 * Inherited from caller.
5053 *
5054 * RETURNS:
5055 * Bytes consumed.
5046 */ 5056 */
5047void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, 5057unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
5048 unsigned int buflen, int write_data) 5058 unsigned int buflen, int rw)
5049{ 5059{
5050 unsigned long flags; 5060 unsigned long flags;
5061 unsigned int consumed;
5062
5051 local_irq_save(flags); 5063 local_irq_save(flags);
5052 ata_data_xfer(adev, buf, buflen, write_data); 5064 consumed = ata_data_xfer(dev, buf, buflen, rw);
5053 local_irq_restore(flags); 5065 local_irq_restore(flags);
5066
5067 return consumed;
5054} 5068}
5055 5069
5056 5070