diff options
author | Tejun Heo <htejun@gmail.com> | 2007-12-05 02:43:07 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:14 -0500 |
commit | 55dba3120fbcbea6800f9a18503d25f73212a347 (patch) | |
tree | 1b23e606aad8bc58dbe68ca905c0658625fb176e | |
parent | ceb0c642624f634c5b4f46b0e22df19be87a2e53 (diff) |
libata: update ->data_xfer hook for ATAPI
Depending on how many bytes are transferred as a unit, PIO data
transfer may consume more bytes than requested. Knowing how much
data is consumed is necessary to determine how much is left for
draining. This patch update ->data_xfer such that it returns the
number of consumed bytes.
While at it, it also makes the following changes.
* s/adev/dev/
* use READ/WRITE constants for rw indication
* misc clean ups
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/libata-core.c | 46 | ||||
-rw-r--r-- | drivers/ata/pata_bf54x.c | 28 | ||||
-rw-r--r-- | drivers/ata/pata_ixp4xx_cf.c | 26 | ||||
-rw-r--r-- | drivers/ata/pata_legacy.c | 36 | ||||
-rw-r--r-- | drivers/ata/pata_qdi.c | 30 | ||||
-rw-r--r-- | drivers/ata/pata_scc.c | 30 | ||||
-rw-r--r-- | drivers/ata/pata_winbond.c | 28 | ||||
-rw-r--r-- | include/linux/libata.h | 11 |
8 files changed, 133 insertions, 102 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 | */ |
5007 | void ata_data_xfer(struct ata_device *adev, unsigned char *buf, | 5010 | unsigned 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 | */ |
5047 | void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, | 5057 | unsigned 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 | ||
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 7842cc487359..41cd921082ba 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c | |||
@@ -1167,34 +1167,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap) | |||
1167 | * Note: Original code is ata_data_xfer(). | 1167 | * Note: Original code is ata_data_xfer(). |
1168 | */ | 1168 | */ |
1169 | 1169 | ||
1170 | static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf, | 1170 | static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf, |
1171 | unsigned int buflen, int write_data) | 1171 | unsigned int buflen, int rw) |
1172 | { | 1172 | { |
1173 | struct ata_port *ap = adev->link->ap; | 1173 | struct ata_port *ap = dev->link->ap; |
1174 | unsigned int words = buflen >> 1; | ||
1175 | unsigned short *buf16 = (u16 *) buf; | ||
1176 | void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; | 1174 | void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; |
1175 | unsigned int words = buflen >> 1; | ||
1176 | unsigned short *buf16 = (u16 *)buf; | ||
1177 | 1177 | ||
1178 | /* Transfer multiple of 2 bytes */ | 1178 | /* Transfer multiple of 2 bytes */ |
1179 | if (write_data) { | 1179 | if (rw == READ) |
1180 | write_atapi_data(base, words, buf16); | ||
1181 | } else { | ||
1182 | read_atapi_data(base, words, buf16); | 1180 | read_atapi_data(base, words, buf16); |
1183 | } | 1181 | else |
1182 | write_atapi_data(base, words, buf16); | ||
1184 | 1183 | ||
1185 | /* Transfer trailing 1 byte, if any. */ | 1184 | /* Transfer trailing 1 byte, if any. */ |
1186 | if (unlikely(buflen & 0x01)) { | 1185 | if (unlikely(buflen & 0x01)) { |
1187 | unsigned short align_buf[1] = { 0 }; | 1186 | unsigned short align_buf[1] = { 0 }; |
1188 | unsigned char *trailing_buf = buf + buflen - 1; | 1187 | unsigned char *trailing_buf = buf + buflen - 1; |
1189 | 1188 | ||
1190 | if (write_data) { | 1189 | if (rw == READ) { |
1191 | memcpy(align_buf, trailing_buf, 1); | ||
1192 | write_atapi_data(base, 1, align_buf); | ||
1193 | } else { | ||
1194 | read_atapi_data(base, 1, align_buf); | 1190 | read_atapi_data(base, 1, align_buf); |
1195 | memcpy(trailing_buf, align_buf, 1); | 1191 | memcpy(trailing_buf, align_buf, 1); |
1192 | } else { | ||
1193 | memcpy(align_buf, trailing_buf, 1); | ||
1194 | write_atapi_data(base, 1, align_buf); | ||
1196 | } | 1195 | } |
1196 | words++; | ||
1197 | } | 1197 | } |
1198 | |||
1199 | return words << 1; | ||
1198 | } | 1200 | } |
1199 | 1201 | ||
1200 | /** | 1202 | /** |
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 120b5bfa7ce6..030878fedeb5 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c | |||
@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) | |||
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, | 45 | static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev, |
46 | unsigned int buflen, int write_data) | 46 | unsigned char *buf, unsigned int buflen, int rw) |
47 | { | 47 | { |
48 | unsigned int i; | 48 | unsigned int i; |
49 | unsigned int words = buflen >> 1; | 49 | unsigned int words = buflen >> 1; |
50 | u16 *buf16 = (u16 *) buf; | 50 | u16 *buf16 = (u16 *) buf; |
51 | struct ata_port *ap = adev->link->ap; | 51 | struct ata_port *ap = dev->link->ap; |
52 | void __iomem *mmio = ap->ioaddr.data_addr; | 52 | void __iomem *mmio = ap->ioaddr.data_addr; |
53 | struct ixp4xx_pata_data *data = ap->host->dev->platform_data; | 53 | struct ixp4xx_pata_data *data = ap->host->dev->platform_data; |
54 | 54 | ||
@@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, | |||
59 | udelay(100); | 59 | udelay(100); |
60 | 60 | ||
61 | /* Transfer multiple of 2 bytes */ | 61 | /* Transfer multiple of 2 bytes */ |
62 | if (write_data) { | 62 | if (rw == READ) |
63 | for (i = 0; i < words; i++) | ||
64 | writew(buf16[i], mmio); | ||
65 | } else { | ||
66 | for (i = 0; i < words; i++) | 63 | for (i = 0; i < words; i++) |
67 | buf16[i] = readw(mmio); | 64 | buf16[i] = readw(mmio); |
68 | } | 65 | else |
66 | for (i = 0; i < words; i++) | ||
67 | writew(buf16[i], mmio); | ||
69 | 68 | ||
70 | /* Transfer trailing 1 byte, if any. */ | 69 | /* Transfer trailing 1 byte, if any. */ |
71 | if (unlikely(buflen & 0x01)) { | 70 | if (unlikely(buflen & 0x01)) { |
72 | u16 align_buf[1] = { 0 }; | 71 | u16 align_buf[1] = { 0 }; |
73 | unsigned char *trailing_buf = buf + buflen - 1; | 72 | unsigned char *trailing_buf = buf + buflen - 1; |
74 | 73 | ||
75 | if (write_data) { | 74 | if (rw == READ) { |
76 | memcpy(align_buf, trailing_buf, 1); | ||
77 | writew(align_buf[0], mmio); | ||
78 | } else { | ||
79 | align_buf[0] = readw(mmio); | 75 | align_buf[0] = readw(mmio); |
80 | memcpy(trailing_buf, align_buf, 1); | 76 | memcpy(trailing_buf, align_buf, 1); |
77 | } else { | ||
78 | memcpy(align_buf, trailing_buf, 1); | ||
79 | writew(align_buf[0], mmio); | ||
81 | } | 80 | } |
81 | words++; | ||
82 | } | 82 | } |
83 | 83 | ||
84 | udelay(100); | 84 | udelay(100); |
85 | *data->cs0_cfg |= 0x01; | 85 | *data->cs0_cfg |= 0x01; |
86 | |||
87 | return words << 1; | ||
86 | } | 88 | } |
87 | 89 | ||
88 | static struct scsi_host_template ixp4xx_sht = { | 90 | static struct scsi_host_template ixp4xx_sht = { |
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 17159b5e1e43..dae85aa12e32 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c | |||
@@ -249,13 +249,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
249 | 249 | ||
250 | } | 250 | } |
251 | 251 | ||
252 | static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) | 252 | static unsigned int pdc_data_xfer_vlb(struct ata_device *dev, |
253 | unsigned char *buf, unsigned int buflen, int rw) | ||
253 | { | 254 | { |
254 | struct ata_port *ap = adev->link->ap; | ||
255 | int slop = buflen & 3; | ||
256 | unsigned long flags; | ||
257 | |||
258 | if (ata_id_has_dword_io(adev->id)) { | 255 | if (ata_id_has_dword_io(adev->id)) { |
256 | struct ata_port *ap = dev->link->ap; | ||
257 | int slop = buflen & 3; | ||
258 | unsigned long flags; | ||
259 | |||
259 | local_irq_save(flags); | 260 | local_irq_save(flags); |
260 | 261 | ||
261 | /* Perform the 32bit I/O synchronization sequence */ | 262 | /* Perform the 32bit I/O synchronization sequence */ |
@@ -264,26 +265,27 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig | |||
264 | ioread8(ap->ioaddr.nsect_addr); | 265 | ioread8(ap->ioaddr.nsect_addr); |
265 | 266 | ||
266 | /* Now the data */ | 267 | /* Now the data */ |
267 | 268 | if (rw == READ) | |
268 | if (write_data) | ||
269 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
270 | else | ||
271 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | 269 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); |
270 | else | ||
271 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
272 | 272 | ||
273 | if (unlikely(slop)) { | 273 | if (unlikely(slop)) { |
274 | __le32 pad = 0; | 274 | u32 pad; |
275 | if (write_data) { | 275 | if (rw == READ) { |
276 | memcpy(&pad, buf + buflen - slop, slop); | ||
277 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
278 | } else { | ||
279 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); | 276 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); |
280 | memcpy(buf + buflen - slop, &pad, slop); | 277 | memcpy(buf + buflen - slop, &pad, slop); |
278 | } else { | ||
279 | memcpy(&pad, buf + buflen - slop, slop); | ||
280 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
281 | } | 281 | } |
282 | buflen += 4 - slop; | ||
282 | } | 283 | } |
283 | local_irq_restore(flags); | 284 | local_irq_restore(flags); |
284 | } | 285 | } else |
285 | else | 286 | buflen = ata_data_xfer_noirq(dev, buf, buflen, rw); |
286 | ata_data_xfer_noirq(adev, buf, buflen, write_data); | 287 | |
288 | return buflen; | ||
287 | } | 289 | } |
288 | 290 | ||
289 | static struct ata_port_operations pdc20230_port_ops = { | 291 | static struct ata_port_operations pdc20230_port_ops = { |
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index a4c0e502cb42..9f308ed76cc8 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c | |||
@@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc) | |||
124 | return ata_qc_issue_prot(qc); | 124 | return ata_qc_issue_prot(qc); |
125 | } | 125 | } |
126 | 126 | ||
127 | static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) | 127 | static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf, |
128 | unsigned int buflen, int rw) | ||
128 | { | 129 | { |
129 | struct ata_port *ap = adev->link->ap; | 130 | if (ata_id_has_dword_io(dev->id)) { |
130 | int slop = buflen & 3; | 131 | struct ata_port *ap = dev->link->ap; |
132 | int slop = buflen & 3; | ||
131 | 133 | ||
132 | if (ata_id_has_dword_io(adev->id)) { | 134 | if (rw == READ) |
133 | if (write_data) | ||
134 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
135 | else | ||
136 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | 135 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); |
136 | else | ||
137 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
137 | 138 | ||
138 | if (unlikely(slop)) { | 139 | if (unlikely(slop)) { |
139 | __le32 pad = 0; | 140 | u32 pad; |
140 | if (write_data) { | 141 | if (rw == READ) { |
141 | memcpy(&pad, buf + buflen - slop, slop); | ||
142 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
143 | } else { | ||
144 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); | 142 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); |
145 | memcpy(buf + buflen - slop, &pad, slop); | 143 | memcpy(buf + buflen - slop, &pad, slop); |
144 | } else { | ||
145 | memcpy(&pad, buf + buflen - slop, slop); | ||
146 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
146 | } | 147 | } |
148 | buflen += 4 - slop; | ||
147 | } | 149 | } |
148 | } else | 150 | } else |
149 | ata_data_xfer(adev, buf, buflen, write_data); | 151 | buflen = ata_data_xfer(dev, buf, buflen, rw); |
152 | |||
153 | return buflen; | ||
150 | } | 154 | } |
151 | 155 | ||
152 | static struct scsi_host_template qdi_sht = { | 156 | static struct scsi_host_template qdi_sht = { |
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index ea2ef9fc15be..55055b27524c 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c | |||
@@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap) | |||
768 | 768 | ||
769 | /** | 769 | /** |
770 | * scc_data_xfer - Transfer data by PIO | 770 | * scc_data_xfer - Transfer data by PIO |
771 | * @adev: device for this I/O | 771 | * @dev: device for this I/O |
772 | * @buf: data buffer | 772 | * @buf: data buffer |
773 | * @buflen: buffer length | 773 | * @buflen: buffer length |
774 | * @write_data: read/write | 774 | * @rw: read/write |
775 | * | 775 | * |
776 | * Note: Original code is ata_data_xfer(). | 776 | * Note: Original code is ata_data_xfer(). |
777 | */ | 777 | */ |
778 | 778 | ||
779 | static void scc_data_xfer (struct ata_device *adev, unsigned char *buf, | 779 | static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf, |
780 | unsigned int buflen, int write_data) | 780 | unsigned int buflen, int rw) |
781 | { | 781 | { |
782 | struct ata_port *ap = adev->link->ap; | 782 | struct ata_port *ap = dev->link->ap; |
783 | unsigned int words = buflen >> 1; | 783 | unsigned int words = buflen >> 1; |
784 | unsigned int i; | 784 | unsigned int i; |
785 | u16 *buf16 = (u16 *) buf; | 785 | u16 *buf16 = (u16 *) buf; |
786 | void __iomem *mmio = ap->ioaddr.data_addr; | 786 | void __iomem *mmio = ap->ioaddr.data_addr; |
787 | 787 | ||
788 | /* Transfer multiple of 2 bytes */ | 788 | /* Transfer multiple of 2 bytes */ |
789 | if (write_data) { | 789 | if (rw == READ) |
790 | for (i = 0; i < words; i++) | ||
791 | out_be32(mmio, cpu_to_le16(buf16[i])); | ||
792 | } else { | ||
793 | for (i = 0; i < words; i++) | 790 | for (i = 0; i < words; i++) |
794 | buf16[i] = le16_to_cpu(in_be32(mmio)); | 791 | buf16[i] = le16_to_cpu(in_be32(mmio)); |
795 | } | 792 | else |
793 | for (i = 0; i < words; i++) | ||
794 | out_be32(mmio, cpu_to_le16(buf16[i])); | ||
796 | 795 | ||
797 | /* Transfer trailing 1 byte, if any. */ | 796 | /* Transfer trailing 1 byte, if any. */ |
798 | if (unlikely(buflen & 0x01)) { | 797 | if (unlikely(buflen & 0x01)) { |
799 | u16 align_buf[1] = { 0 }; | 798 | u16 align_buf[1] = { 0 }; |
800 | unsigned char *trailing_buf = buf + buflen - 1; | 799 | unsigned char *trailing_buf = buf + buflen - 1; |
801 | 800 | ||
802 | if (write_data) { | 801 | if (rw == READ) { |
803 | memcpy(align_buf, trailing_buf, 1); | ||
804 | out_be32(mmio, cpu_to_le16(align_buf[0])); | ||
805 | } else { | ||
806 | align_buf[0] = le16_to_cpu(in_be32(mmio)); | 802 | align_buf[0] = le16_to_cpu(in_be32(mmio)); |
807 | memcpy(trailing_buf, align_buf, 1); | 803 | memcpy(trailing_buf, align_buf, 1); |
804 | } else { | ||
805 | memcpy(align_buf, trailing_buf, 1); | ||
806 | out_be32(mmio, cpu_to_le16(align_buf[0])); | ||
808 | } | 807 | } |
808 | words++; | ||
809 | } | 809 | } |
810 | |||
811 | return words << 1; | ||
810 | } | 812 | } |
811 | 813 | ||
812 | /** | 814 | /** |
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 7116a9e7a8b2..7312e9182d69 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c | |||
@@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | 94 | ||
95 | static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) | 95 | static void winbond_data_xfer(struct ata_device *dev, unsigned char *buf, |
96 | unsigned int buflen, int rw) | ||
96 | { | 97 | { |
97 | struct ata_port *ap = adev->link->ap; | 98 | struct ata_port *ap = dev->link->ap; |
98 | int slop = buflen & 3; | 99 | int slop = buflen & 3; |
99 | 100 | ||
100 | if (ata_id_has_dword_io(adev->id)) { | 101 | if (ata_id_has_dword_io(dev->id)) { |
101 | if (write_data) | 102 | if (rw == READ) |
102 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
103 | else | ||
104 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | 103 | ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); |
104 | else | ||
105 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
105 | 106 | ||
106 | if (unlikely(slop)) { | 107 | if (unlikely(slop)) { |
107 | __le32 pad = 0; | 108 | u32 pad; |
108 | if (write_data) { | 109 | if (rw == READ) { |
109 | memcpy(&pad, buf + buflen - slop, slop); | ||
110 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
111 | } else { | ||
112 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); | 110 | pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); |
113 | memcpy(buf + buflen - slop, &pad, slop); | 111 | memcpy(buf + buflen - slop, &pad, slop); |
112 | } else { | ||
113 | memcpy(&pad, buf + buflen - slop, slop); | ||
114 | iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
114 | } | 115 | } |
116 | buflen += 4 - slop; | ||
115 | } | 117 | } |
116 | } else | 118 | } else |
117 | ata_data_xfer(adev, buf, buflen, write_data); | 119 | buflen = ata_data_xfer(dev, buf, buflen, rw); |
120 | |||
121 | return buflen; | ||
118 | } | 122 | } |
119 | 123 | ||
120 | static struct scsi_host_template winbond_sht = { | 124 | static struct scsi_host_template winbond_sht = { |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 03afcd63202d..7fa96cb4f6db 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -701,7 +701,8 @@ struct ata_port_operations { | |||
701 | void (*bmdma_setup) (struct ata_queued_cmd *qc); | 701 | void (*bmdma_setup) (struct ata_queued_cmd *qc); |
702 | void (*bmdma_start) (struct ata_queued_cmd *qc); | 702 | void (*bmdma_start) (struct ata_queued_cmd *qc); |
703 | 703 | ||
704 | void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); | 704 | unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf, |
705 | unsigned int buflen, int rw); | ||
705 | 706 | ||
706 | int (*qc_defer) (struct ata_queued_cmd *qc); | 707 | int (*qc_defer) (struct ata_queued_cmd *qc); |
707 | void (*qc_prep) (struct ata_queued_cmd *qc); | 708 | void (*qc_prep) (struct ata_queued_cmd *qc); |
@@ -881,10 +882,10 @@ extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) | |||
881 | extern int ata_port_start(struct ata_port *ap); | 882 | extern int ata_port_start(struct ata_port *ap); |
882 | extern int ata_sff_port_start(struct ata_port *ap); | 883 | extern int ata_sff_port_start(struct ata_port *ap); |
883 | extern irqreturn_t ata_interrupt(int irq, void *dev_instance); | 884 | extern irqreturn_t ata_interrupt(int irq, void *dev_instance); |
884 | extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf, | 885 | extern unsigned int ata_data_xfer(struct ata_device *dev, |
885 | unsigned int buflen, int write_data); | 886 | unsigned char *buf, unsigned int buflen, int rw); |
886 | extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, | 887 | extern unsigned int ata_data_xfer_noirq(struct ata_device *dev, |
887 | unsigned int buflen, int write_data); | 888 | unsigned char *buf, unsigned int buflen, int rw); |
888 | extern int ata_std_qc_defer(struct ata_queued_cmd *qc); | 889 | extern int ata_std_qc_defer(struct ata_queued_cmd *qc); |
889 | extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); | 890 | extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); |
890 | extern void ata_qc_prep(struct ata_queued_cmd *qc); | 891 | extern void ata_qc_prep(struct ata_queued_cmd *qc); |