aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-taskfile.c73
1 files changed, 37 insertions, 36 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 84532be97c00..8d7e87d04b3b 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -189,7 +189,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
189} 189}
190 190
191static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, 191static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
192 unsigned int write, unsigned int nr_bytes) 192 unsigned int write, unsigned int len)
193{ 193{
194 ide_hwif_t *hwif = drive->hwif; 194 ide_hwif_t *hwif = drive->hwif;
195 struct scatterlist *sg = hwif->sg_table; 195 struct scatterlist *sg = hwif->sg_table;
@@ -202,56 +202,55 @@ static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
202 u8 *buf; 202 u8 *buf;
203 203
204 cursg = cmd->cursg; 204 cursg = cmd->cursg;
205 if (!cursg) { 205 if (cursg == NULL)
206 cursg = sg; 206 cursg = cmd->cursg = sg;
207 cmd->cursg = sg; 207
208 } 208 while (len) {
209 unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs);
209 210
210 page = sg_page(cursg); 211 if (nr_bytes > PAGE_SIZE)
211 offset = cursg->offset + cmd->cursg_ofs; 212 nr_bytes = PAGE_SIZE;
212 213
213 /* get the current page and offset */ 214 page = sg_page(cursg);
214 page = nth_page(page, (offset >> PAGE_SHIFT)); 215 offset = cursg->offset + cmd->cursg_ofs;
215 offset %= PAGE_SIZE; 216
217 /* get the current page and offset */
218 page = nth_page(page, (offset >> PAGE_SHIFT));
219 offset %= PAGE_SIZE;
216 220
217#ifdef CONFIG_HIGHMEM 221#ifdef CONFIG_HIGHMEM
218 local_irq_save(flags); 222 local_irq_save(flags);
219#endif 223#endif
220 buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; 224 buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
221 225
222 cmd->nleft -= nr_bytes; 226 cmd->nleft -= nr_bytes;
223 cmd->cursg_ofs += nr_bytes; 227 cmd->cursg_ofs += nr_bytes;
224 228
225 if (cmd->cursg_ofs == cursg->length) { 229 if (cmd->cursg_ofs == cursg->length) {
226 cmd->cursg = sg_next(cmd->cursg); 230 cursg = cmd->cursg = sg_next(cmd->cursg);
227 cmd->cursg_ofs = 0; 231 cmd->cursg_ofs = 0;
228 } 232 }
229 233
230 /* do the actual data transfer */ 234 /* do the actual data transfer */
231 if (write) 235 if (write)
232 hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes); 236 hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes);
233 else 237 else
234 hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes); 238 hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes);
235 239
236 kunmap_atomic(buf, KM_BIO_SRC_IRQ); 240 kunmap_atomic(buf, KM_BIO_SRC_IRQ);
237#ifdef CONFIG_HIGHMEM 241#ifdef CONFIG_HIGHMEM
238 local_irq_restore(flags); 242 local_irq_restore(flags);
239#endif 243#endif
240}
241
242static void ide_pio_multi(ide_drive_t *drive, struct ide_cmd *cmd,
243 unsigned int write)
244{
245 unsigned int nsect;
246 244
247 nsect = min_t(unsigned int, cmd->nleft >> 9, drive->mult_count); 245 len -= nr_bytes;
248 while (nsect--) 246 }
249 ide_pio_bytes(drive, cmd, write, SECTOR_SIZE);
250} 247}
251 248
252static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd, 249static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
253 unsigned int write) 250 unsigned int write)
254{ 251{
252 unsigned int nr_bytes;
253
255 u8 saved_io_32bit = drive->io_32bit; 254 u8 saved_io_32bit = drive->io_32bit;
256 255
257 if (cmd->tf_flags & IDE_TFLAG_FS) 256 if (cmd->tf_flags & IDE_TFLAG_FS)
@@ -263,9 +262,11 @@ static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
263 touch_softlockup_watchdog(); 262 touch_softlockup_watchdog();
264 263
265 if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) 264 if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
266 ide_pio_multi(drive, cmd, write); 265 nr_bytes = min_t(unsigned, cmd->nleft, drive->mult_count << 9);
267 else 266 else
268 ide_pio_bytes(drive, cmd, write, SECTOR_SIZE); 267 nr_bytes = SECTOR_SIZE;
268
269 ide_pio_bytes(drive, cmd, write, nr_bytes);
269 270
270 drive->io_32bit = saved_io_32bit; 271 drive->io_32bit = saved_io_32bit;
271} 272}