aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-io.c23
-rw-r--r--drivers/ide/ide-iops.c18
-rw-r--r--drivers/ide/ide.c41
-rw-r--r--include/linux/ide.h6
4 files changed, 56 insertions, 32 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 28057747c1f8..2b33c129740b 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -766,6 +766,18 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
766 return ide_stopped; 766 return ide_stopped;
767} 767}
768 768
769static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
770{
771 switch (rq->cmd[0]) {
772 case REQ_DRIVE_RESET:
773 return ide_do_reset(drive);
774 default:
775 blk_dump_rq_flags(rq, "ide_special_rq - bad request");
776 ide_end_request(drive, 0, 0);
777 return ide_stopped;
778 }
779}
780
769static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) 781static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
770{ 782{
771 struct request_pm_state *pm = rq->data; 783 struct request_pm_state *pm = rq->data;
@@ -869,7 +881,16 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
869 pm->pm_step == ide_pm_state_completed) 881 pm->pm_step == ide_pm_state_completed)
870 ide_complete_pm_request(drive, rq); 882 ide_complete_pm_request(drive, rq);
871 return startstop; 883 return startstop;
872 } 884 } else if (!rq->rq_disk && blk_special_request(rq))
885 /*
886 * TODO: Once all ULDs have been modified to
887 * check for specific op codes rather than
888 * blindly accepting any special request, the
889 * check for ->rq_disk above may be replaced
890 * by a more suitable mechanism or even
891 * dropped entirely.
892 */
893 return ide_special_rq(drive, rq);
873 894
874 drv = *(ide_driver_t **)rq->rq_disk->private_data; 895 drv = *(ide_driver_t **)rq->rq_disk->private_data;
875 return drv->do_request(drive, rq, block); 896 return drv->do_request(drive, rq, block);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 80ad4f234f3f..96f63eb12092 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -905,6 +905,14 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
905} 905}
906EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); 906EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
907 907
908static inline void ide_complete_drive_reset(ide_drive_t *drive)
909{
910 struct request *rq = drive->hwif->hwgroup->rq;
911
912 if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
913 ide_end_request(drive, 1, 0);
914}
915
908/* needed below */ 916/* needed below */
909static ide_startstop_t do_reset1 (ide_drive_t *, int); 917static ide_startstop_t do_reset1 (ide_drive_t *, int);
910 918
@@ -940,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
940 } 948 }
941 /* done polling */ 949 /* done polling */
942 hwgroup->polling = 0; 950 hwgroup->polling = 0;
943 hwgroup->resetting = 0; 951 ide_complete_drive_reset(drive);
944 return ide_stopped; 952 return ide_stopped;
945} 953}
946 954
@@ -961,7 +969,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
961 if (port_ops->reset_poll(drive)) { 969 if (port_ops->reset_poll(drive)) {
962 printk(KERN_ERR "%s: host reset_poll failure for %s.\n", 970 printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
963 hwif->name, drive->name); 971 hwif->name, drive->name);
964 return ide_stopped; 972 goto out;
965 } 973 }
966 } 974 }
967 975
@@ -1004,7 +1012,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
1004 } 1012 }
1005 } 1013 }
1006 hwgroup->polling = 0; /* done polling */ 1014 hwgroup->polling = 0; /* done polling */
1007 hwgroup->resetting = 0; /* done reset attempt */ 1015out:
1016 ide_complete_drive_reset(drive);
1008 return ide_stopped; 1017 return ide_stopped;
1009} 1018}
1010 1019
@@ -1090,7 +1099,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
1090 1099
1091 /* For an ATAPI device, first try an ATAPI SRST. */ 1100 /* For an ATAPI device, first try an ATAPI SRST. */
1092 if (drive->media != ide_disk && !do_not_try_atapi) { 1101 if (drive->media != ide_disk && !do_not_try_atapi) {
1093 hwgroup->resetting = 1;
1094 pre_reset(drive); 1102 pre_reset(drive);
1095 SELECT_DRIVE(drive); 1103 SELECT_DRIVE(drive);
1096 udelay (20); 1104 udelay (20);
@@ -1112,10 +1120,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
1112 1120
1113 if (io_ports->ctl_addr == 0) { 1121 if (io_ports->ctl_addr == 0) {
1114 spin_unlock_irqrestore(&ide_lock, flags); 1122 spin_unlock_irqrestore(&ide_lock, flags);
1123 ide_complete_drive_reset(drive);
1115 return ide_stopped; 1124 return ide_stopped;
1116 } 1125 }
1117 1126
1118 hwgroup->resetting = 1;
1119 /* 1127 /*
1120 * Note that we also set nIEN while resetting the device, 1128 * Note that we also set nIEN while resetting the device,
1121 * to mask unwanted interrupts from the interface during the reset. 1129 * to mask unwanted interrupts from the interface during the reset.
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 90ae00d4aaf5..1ec983b00511 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -529,6 +529,19 @@ static int generic_ide_resume(struct device *dev)
529 return err; 529 return err;
530} 530}
531 531
532static void generic_drive_reset(ide_drive_t *drive)
533{
534 struct request *rq;
535
536 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
537 rq->cmd_type = REQ_TYPE_SPECIAL;
538 rq->cmd_len = 1;
539 rq->cmd[0] = REQ_DRIVE_RESET;
540 rq->cmd_flags |= REQ_SOFTBARRIER;
541 blk_execute_rq(drive->queue, NULL, rq, 1);
542 blk_put_request(rq);
543}
544
532int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, 545int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
533 unsigned int cmd, unsigned long arg) 546 unsigned int cmd, unsigned long arg)
534{ 547{
@@ -603,33 +616,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
603 if (!capable(CAP_SYS_ADMIN)) 616 if (!capable(CAP_SYS_ADMIN))
604 return -EACCES; 617 return -EACCES;
605 618
606 /* 619 generic_drive_reset(drive);
607 * Abort the current command on the
608 * group if there is one, taking
609 * care not to allow anything else
610 * to be queued and to die on the
611 * spot if we miss one somehow
612 */
613
614 spin_lock_irqsave(&ide_lock, flags);
615
616 if (HWGROUP(drive)->resetting) {
617 spin_unlock_irqrestore(&ide_lock, flags);
618 return -EBUSY;
619 }
620
621 ide_abort(drive, "drive reset");
622
623 BUG_ON(HWGROUP(drive)->handler);
624
625 /* Ensure nothing gets queued after we
626 drop the lock. Reset will clear the busy */
627
628 HWGROUP(drive)->busy = 1;
629 spin_unlock_irqrestore(&ide_lock, flags);
630 (void) ide_do_reset(drive);
631
632 return 0; 620 return 0;
621
633 case HDIO_GET_BUSSTATE: 622 case HDIO_GET_BUSSTATE:
634 if (!capable(CAP_SYS_ADMIN)) 623 if (!capable(CAP_SYS_ADMIN))
635 return -EACCES; 624 return -EACCES;
diff --git a/include/linux/ide.h b/include/linux/ide.h
index f9cbe9350cad..021710cc1b1c 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -139,6 +139,12 @@ struct ide_io_ports {
139#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */ 139#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */
140 140
141/* 141/*
142 * Op codes for special requests to be handled by ide_special_rq().
143 * Values should be in the range of 0x20 to 0x3f.
144 */
145#define REQ_DRIVE_RESET 0x20
146
147/*
142 * Check for an interrupt and acknowledge the interrupt status 148 * Check for an interrupt and acknowledge the interrupt status
143 */ 149 */
144struct hwif_s; 150struct hwif_s;