diff options
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r-- | drivers/ide/ide-io.c | 138 |
1 files changed, 72 insertions, 66 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 35dc38d3b2c5..272cc38f6dbe 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -116,9 +116,9 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
116 | unsigned int ide_rq_bytes(struct request *rq) | 116 | unsigned int ide_rq_bytes(struct request *rq) |
117 | { | 117 | { |
118 | if (blk_pc_request(rq)) | 118 | if (blk_pc_request(rq)) |
119 | return rq->data_len; | 119 | return blk_rq_bytes(rq); |
120 | else | 120 | else |
121 | return rq->hard_cur_sectors << 9; | 121 | return blk_rq_cur_sectors(rq) << 9; |
122 | } | 122 | } |
123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); | 123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); |
124 | 124 | ||
@@ -133,7 +133,7 @@ int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) | |||
133 | * and complete the whole request right now | 133 | * and complete the whole request right now |
134 | */ | 134 | */ |
135 | if (blk_noretry_request(rq) && error <= 0) | 135 | if (blk_noretry_request(rq) && error <= 0) |
136 | nr_bytes = rq->hard_nr_sectors << 9; | 136 | nr_bytes = blk_rq_sectors(rq) << 9; |
137 | 137 | ||
138 | rc = ide_end_rq(drive, rq, error, nr_bytes); | 138 | rc = ide_end_rq(drive, rq, error, nr_bytes); |
139 | if (rc == 0) | 139 | if (rc == 0) |
@@ -184,29 +184,42 @@ static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | |||
184 | tf->command = ATA_CMD_SET_MULTI; | 184 | tf->command = ATA_CMD_SET_MULTI; |
185 | } | 185 | } |
186 | 186 | ||
187 | static ide_startstop_t ide_disk_special(ide_drive_t *drive) | 187 | /** |
188 | * do_special - issue some special commands | ||
189 | * @drive: drive the command is for | ||
190 | * | ||
191 | * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, | ||
192 | * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. | ||
193 | */ | ||
194 | |||
195 | static ide_startstop_t do_special(ide_drive_t *drive) | ||
188 | { | 196 | { |
189 | special_t *s = &drive->special; | ||
190 | struct ide_cmd cmd; | 197 | struct ide_cmd cmd; |
191 | 198 | ||
199 | #ifdef DEBUG | ||
200 | printk(KERN_DEBUG "%s: %s: 0x%02x\n", drive->name, __func__, | ||
201 | drive->special_flags); | ||
202 | #endif | ||
203 | if (drive->media != ide_disk) { | ||
204 | drive->special_flags = 0; | ||
205 | drive->mult_req = 0; | ||
206 | return ide_stopped; | ||
207 | } | ||
208 | |||
192 | memset(&cmd, 0, sizeof(cmd)); | 209 | memset(&cmd, 0, sizeof(cmd)); |
193 | cmd.protocol = ATA_PROT_NODATA; | 210 | cmd.protocol = ATA_PROT_NODATA; |
194 | 211 | ||
195 | if (s->b.set_geometry) { | 212 | if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) { |
196 | s->b.set_geometry = 0; | 213 | drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY; |
197 | ide_tf_set_specify_cmd(drive, &cmd.tf); | 214 | ide_tf_set_specify_cmd(drive, &cmd.tf); |
198 | } else if (s->b.recalibrate) { | 215 | } else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) { |
199 | s->b.recalibrate = 0; | 216 | drive->special_flags &= ~IDE_SFLAG_RECALIBRATE; |
200 | ide_tf_set_restore_cmd(drive, &cmd.tf); | 217 | ide_tf_set_restore_cmd(drive, &cmd.tf); |
201 | } else if (s->b.set_multmode) { | 218 | } else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) { |
202 | s->b.set_multmode = 0; | 219 | drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE; |
203 | ide_tf_set_setmult_cmd(drive, &cmd.tf); | 220 | ide_tf_set_setmult_cmd(drive, &cmd.tf); |
204 | } else if (s->all) { | 221 | } else |
205 | int special = s->all; | 222 | BUG(); |
206 | s->all = 0; | ||
207 | printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); | ||
208 | return ide_stopped; | ||
209 | } | ||
210 | 223 | ||
211 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; | 224 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
212 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | 225 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
@@ -217,45 +230,13 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) | |||
217 | return ide_started; | 230 | return ide_started; |
218 | } | 231 | } |
219 | 232 | ||
220 | /** | ||
221 | * do_special - issue some special commands | ||
222 | * @drive: drive the command is for | ||
223 | * | ||
224 | * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, | ||
225 | * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. | ||
226 | * | ||
227 | * It used to do much more, but has been scaled back. | ||
228 | */ | ||
229 | |||
230 | static ide_startstop_t do_special (ide_drive_t *drive) | ||
231 | { | ||
232 | special_t *s = &drive->special; | ||
233 | |||
234 | #ifdef DEBUG | ||
235 | printk("%s: do_special: 0x%02x\n", drive->name, s->all); | ||
236 | #endif | ||
237 | if (drive->media == ide_disk) | ||
238 | return ide_disk_special(drive); | ||
239 | |||
240 | s->all = 0; | ||
241 | drive->mult_req = 0; | ||
242 | return ide_stopped; | ||
243 | } | ||
244 | |||
245 | void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) | 233 | void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) |
246 | { | 234 | { |
247 | ide_hwif_t *hwif = drive->hwif; | 235 | ide_hwif_t *hwif = drive->hwif; |
248 | struct scatterlist *sg = hwif->sg_table; | 236 | struct scatterlist *sg = hwif->sg_table; |
249 | struct request *rq = cmd->rq; | 237 | struct request *rq = cmd->rq; |
250 | 238 | ||
251 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 239 | cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); |
252 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); | ||
253 | cmd->sg_nents = 1; | ||
254 | } else if (!rq->bio) { | ||
255 | sg_init_one(sg, rq->data, rq->data_len); | ||
256 | cmd->sg_nents = 1; | ||
257 | } else | ||
258 | cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | ||
259 | } | 240 | } |
260 | EXPORT_SYMBOL_GPL(ide_map_sg); | 241 | EXPORT_SYMBOL_GPL(ide_map_sg); |
261 | 242 | ||
@@ -286,7 +267,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
286 | 267 | ||
287 | if (cmd) { | 268 | if (cmd) { |
288 | if (cmd->protocol == ATA_PROT_PIO) { | 269 | if (cmd->protocol == ATA_PROT_PIO) { |
289 | ide_init_sg_cmd(cmd, rq->nr_sectors << 9); | 270 | ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9); |
290 | ide_map_sg(drive, cmd); | 271 | ide_map_sg(drive, cmd); |
291 | } | 272 | } |
292 | 273 | ||
@@ -358,7 +339,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
358 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); | 339 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); |
359 | return startstop; | 340 | return startstop; |
360 | } | 341 | } |
361 | if (!drive->special.all) { | 342 | |
343 | if (drive->special_flags == 0) { | ||
362 | struct ide_driver *drv; | 344 | struct ide_driver *drv; |
363 | 345 | ||
364 | /* | 346 | /* |
@@ -371,7 +353,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
371 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) | 353 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) |
372 | return execute_drive_cmd(drive, rq); | 354 | return execute_drive_cmd(drive, rq); |
373 | else if (blk_pm_request(rq)) { | 355 | else if (blk_pm_request(rq)) { |
374 | struct request_pm_state *pm = rq->data; | 356 | struct request_pm_state *pm = rq->special; |
375 | #ifdef DEBUG_PM | 357 | #ifdef DEBUG_PM |
376 | printk("%s: start_power_step(step: %d)\n", | 358 | printk("%s: start_power_step(step: %d)\n", |
377 | drive->name, pm->pm_step); | 359 | drive->name, pm->pm_step); |
@@ -394,7 +376,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
394 | 376 | ||
395 | drv = *(struct ide_driver **)rq->rq_disk->private_data; | 377 | drv = *(struct ide_driver **)rq->rq_disk->private_data; |
396 | 378 | ||
397 | return drv->do_request(drive, rq, rq->sector); | 379 | return drv->do_request(drive, rq, blk_rq_pos(rq)); |
398 | } | 380 | } |
399 | return do_special(drive); | 381 | return do_special(drive); |
400 | kill_rq: | 382 | kill_rq: |
@@ -484,6 +466,9 @@ void do_ide_request(struct request_queue *q) | |||
484 | 466 | ||
485 | spin_unlock_irq(q->queue_lock); | 467 | spin_unlock_irq(q->queue_lock); |
486 | 468 | ||
469 | /* HLD do_request() callback might sleep, make sure it's okay */ | ||
470 | might_sleep(); | ||
471 | |||
487 | if (ide_lock_host(host, hwif)) | 472 | if (ide_lock_host(host, hwif)) |
488 | goto plug_device_2; | 473 | goto plug_device_2; |
489 | 474 | ||
@@ -491,10 +476,10 @@ void do_ide_request(struct request_queue *q) | |||
491 | 476 | ||
492 | if (!ide_lock_port(hwif)) { | 477 | if (!ide_lock_port(hwif)) { |
493 | ide_hwif_t *prev_port; | 478 | ide_hwif_t *prev_port; |
479 | |||
480 | WARN_ON_ONCE(hwif->rq); | ||
494 | repeat: | 481 | repeat: |
495 | prev_port = hwif->host->cur_port; | 482 | prev_port = hwif->host->cur_port; |
496 | hwif->rq = NULL; | ||
497 | |||
498 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && | 483 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && |
499 | time_after(drive->sleep, jiffies)) { | 484 | time_after(drive->sleep, jiffies)) { |
500 | ide_unlock_port(hwif); | 485 | ide_unlock_port(hwif); |
@@ -503,11 +488,15 @@ repeat: | |||
503 | 488 | ||
504 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && | 489 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && |
505 | hwif != prev_port) { | 490 | hwif != prev_port) { |
491 | ide_drive_t *cur_dev = | ||
492 | prev_port ? prev_port->cur_dev : NULL; | ||
493 | |||
506 | /* | 494 | /* |
507 | * set nIEN for previous port, drives in the | 495 | * set nIEN for previous port, drives in the |
508 | * quirk_list may not like intr setups/cleanups | 496 | * quirk list may not like intr setups/cleanups |
509 | */ | 497 | */ |
510 | if (prev_port && prev_port->cur_dev->quirk_list == 0) | 498 | if (cur_dev && |
499 | (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) | ||
511 | prev_port->tp_ops->write_devctl(prev_port, | 500 | prev_port->tp_ops->write_devctl(prev_port, |
512 | ATA_NIEN | | 501 | ATA_NIEN | |
513 | ATA_DEVCTL_OBS); | 502 | ATA_DEVCTL_OBS); |
@@ -523,7 +512,9 @@ repeat: | |||
523 | * we know that the queue isn't empty, but this can happen | 512 | * we know that the queue isn't empty, but this can happen |
524 | * if the q->prep_rq_fn() decides to kill a request | 513 | * if the q->prep_rq_fn() decides to kill a request |
525 | */ | 514 | */ |
526 | rq = elv_next_request(drive->queue); | 515 | if (!rq) |
516 | rq = blk_fetch_request(drive->queue); | ||
517 | |||
527 | spin_unlock_irq(q->queue_lock); | 518 | spin_unlock_irq(q->queue_lock); |
528 | spin_lock_irq(&hwif->lock); | 519 | spin_lock_irq(&hwif->lock); |
529 | 520 | ||
@@ -535,7 +526,7 @@ repeat: | |||
535 | /* | 526 | /* |
536 | * Sanity: don't accept a request that isn't a PM request | 527 | * Sanity: don't accept a request that isn't a PM request |
537 | * if we are currently power managed. This is very important as | 528 | * if we are currently power managed. This is very important as |
538 | * blk_stop_queue() doesn't prevent the elv_next_request() | 529 | * blk_stop_queue() doesn't prevent the blk_fetch_request() |
539 | * above to return us whatever is in the queue. Since we call | 530 | * above to return us whatever is in the queue. Since we call |
540 | * ide_do_request() ourselves, we end up taking requests while | 531 | * ide_do_request() ourselves, we end up taking requests while |
541 | * the queue is blocked... | 532 | * the queue is blocked... |
@@ -559,8 +550,11 @@ repeat: | |||
559 | startstop = start_request(drive, rq); | 550 | startstop = start_request(drive, rq); |
560 | spin_lock_irq(&hwif->lock); | 551 | spin_lock_irq(&hwif->lock); |
561 | 552 | ||
562 | if (startstop == ide_stopped) | 553 | if (startstop == ide_stopped) { |
554 | rq = hwif->rq; | ||
555 | hwif->rq = NULL; | ||
563 | goto repeat; | 556 | goto repeat; |
557 | } | ||
564 | } else | 558 | } else |
565 | goto plug_device; | 559 | goto plug_device; |
566 | out: | 560 | out: |
@@ -576,18 +570,24 @@ plug_device: | |||
576 | plug_device_2: | 570 | plug_device_2: |
577 | spin_lock_irq(q->queue_lock); | 571 | spin_lock_irq(q->queue_lock); |
578 | 572 | ||
573 | if (rq) | ||
574 | blk_requeue_request(q, rq); | ||
579 | if (!elv_queue_empty(q)) | 575 | if (!elv_queue_empty(q)) |
580 | blk_plug_device(q); | 576 | blk_plug_device(q); |
581 | } | 577 | } |
582 | 578 | ||
583 | static void ide_plug_device(ide_drive_t *drive) | 579 | static void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) |
584 | { | 580 | { |
585 | struct request_queue *q = drive->queue; | 581 | struct request_queue *q = drive->queue; |
586 | unsigned long flags; | 582 | unsigned long flags; |
587 | 583 | ||
588 | spin_lock_irqsave(q->queue_lock, flags); | 584 | spin_lock_irqsave(q->queue_lock, flags); |
585 | |||
586 | if (rq) | ||
587 | blk_requeue_request(q, rq); | ||
589 | if (!elv_queue_empty(q)) | 588 | if (!elv_queue_empty(q)) |
590 | blk_plug_device(q); | 589 | blk_plug_device(q); |
590 | |||
591 | spin_unlock_irqrestore(q->queue_lock, flags); | 591 | spin_unlock_irqrestore(q->queue_lock, flags); |
592 | } | 592 | } |
593 | 593 | ||
@@ -636,6 +636,7 @@ void ide_timer_expiry (unsigned long data) | |||
636 | unsigned long flags; | 636 | unsigned long flags; |
637 | int wait = -1; | 637 | int wait = -1; |
638 | int plug_device = 0; | 638 | int plug_device = 0; |
639 | struct request *uninitialized_var(rq_in_flight); | ||
639 | 640 | ||
640 | spin_lock_irqsave(&hwif->lock, flags); | 641 | spin_lock_irqsave(&hwif->lock, flags); |
641 | 642 | ||
@@ -696,7 +697,9 @@ void ide_timer_expiry (unsigned long data) | |||
696 | } | 697 | } |
697 | spin_lock_irq(&hwif->lock); | 698 | spin_lock_irq(&hwif->lock); |
698 | enable_irq(hwif->irq); | 699 | enable_irq(hwif->irq); |
699 | if (startstop == ide_stopped) { | 700 | if (startstop == ide_stopped && hwif->polling == 0) { |
701 | rq_in_flight = hwif->rq; | ||
702 | hwif->rq = NULL; | ||
700 | ide_unlock_port(hwif); | 703 | ide_unlock_port(hwif); |
701 | plug_device = 1; | 704 | plug_device = 1; |
702 | } | 705 | } |
@@ -705,7 +708,7 @@ void ide_timer_expiry (unsigned long data) | |||
705 | 708 | ||
706 | if (plug_device) { | 709 | if (plug_device) { |
707 | ide_unlock_host(hwif->host); | 710 | ide_unlock_host(hwif->host); |
708 | ide_plug_device(drive); | 711 | ide_requeue_and_plug(drive, rq_in_flight); |
709 | } | 712 | } |
710 | } | 713 | } |
711 | 714 | ||
@@ -791,6 +794,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
791 | ide_startstop_t startstop; | 794 | ide_startstop_t startstop; |
792 | irqreturn_t irq_ret = IRQ_NONE; | 795 | irqreturn_t irq_ret = IRQ_NONE; |
793 | int plug_device = 0; | 796 | int plug_device = 0; |
797 | struct request *uninitialized_var(rq_in_flight); | ||
794 | 798 | ||
795 | if (host->host_flags & IDE_HFLAG_SERIALIZE) { | 799 | if (host->host_flags & IDE_HFLAG_SERIALIZE) { |
796 | if (hwif != host->cur_port) | 800 | if (hwif != host->cur_port) |
@@ -868,8 +872,10 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
868 | * same irq as is currently being serviced here, and Linux | 872 | * same irq as is currently being serviced here, and Linux |
869 | * won't allow another of the same (on any CPU) until we return. | 873 | * won't allow another of the same (on any CPU) until we return. |
870 | */ | 874 | */ |
871 | if (startstop == ide_stopped) { | 875 | if (startstop == ide_stopped && hwif->polling == 0) { |
872 | BUG_ON(hwif->handler); | 876 | BUG_ON(hwif->handler); |
877 | rq_in_flight = hwif->rq; | ||
878 | hwif->rq = NULL; | ||
873 | ide_unlock_port(hwif); | 879 | ide_unlock_port(hwif); |
874 | plug_device = 1; | 880 | plug_device = 1; |
875 | } | 881 | } |
@@ -879,7 +885,7 @@ out: | |||
879 | out_early: | 885 | out_early: |
880 | if (plug_device) { | 886 | if (plug_device) { |
881 | ide_unlock_host(hwif->host); | 887 | ide_unlock_host(hwif->host); |
882 | ide_plug_device(drive); | 888 | ide_requeue_and_plug(drive, rq_in_flight); |
883 | } | 889 | } |
884 | 890 | ||
885 | return irq_ret; | 891 | return irq_ret; |