diff options
| -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); |
