aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-01-02 10:12:48 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-01-02 10:12:48 -0500
commit295f00042aaf6b553b5f37348f89bab463d4a469 (patch)
treecbd56955f148f0e175d5b6b779c2888bf2645382 /drivers
parentebdab07dad3d3a008e519b0a028e1e1ad5ecaef0 (diff)
ide: don't execute the next queued command from the hard-IRQ context (v2)
* Tell the block layer that we are not done handling requests by using blk_plug_device() in ide_do_request() (request handling function) and ide_timer_expiry() (timeout handler) if the queue is not empty. * Remove optimization which directly calls ide_do_request() for the next queued command from the ide_intr() (IRQ handler) and ide_timer_expiry(). * Remove no longer needed IRQ masking from ide_do_request() - in case of IDE ports needing serialization disable_irq_nosync()/enable_irq() was used for the (possibly shared) IRQ of the other IDE port. * Put the misplaced comment in the right place in ide_do_request(). * Drop no longer needed 'int masked_irq' argument from ide_do_request(). * Merge ide_do_request() into do_ide_request(). * Remove no longer needed IDE_NO_IRQ define. While at it: * Don't use HWGROUP() macro in do_ide_request(). * Use __func__ in ide_intr(). This patch reduces IRQ hadling latency for IDE and improves the system-wide handling of shared IRQs (which should result in more timeout resistant and stable IDE systems). It also makes it possible to do some further changes later (i.e. replace some busy-waiting delays with sleeping equivalents). v2: Changes per review from Elias Oltmanns: - fix wrong goto statement in 'if (startstop == ide_stopped)' block - use spin_unlock_irq() - don't use obsolete HWIF() macro Cc: Elias Oltmanns <eo@nebensachen.de> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/ide-io.c67
1 files changed, 30 insertions, 37 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecacc008fda..23754bc5e59 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -778,8 +778,10 @@ repeat:
778 * the driver. This makes the driver much more friendlier to shared IRQs 778 * the driver. This makes the driver much more friendlier to shared IRQs
779 * than previous designs, while remaining 100% (?) SMP safe and capable. 779 * than previous designs, while remaining 100% (?) SMP safe and capable.
780 */ 780 */
781static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) 781void do_ide_request(struct request_queue *q)
782{ 782{
783 ide_drive_t *orig_drive = q->queuedata;
784 ide_hwgroup_t *hwgroup = orig_drive->hwif->hwgroup;
783 ide_drive_t *drive; 785 ide_drive_t *drive;
784 ide_hwif_t *hwif; 786 ide_hwif_t *hwif;
785 struct request *rq; 787 struct request *rq;
@@ -837,10 +839,14 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
837 } 839 }
838 840
839 /* no more work for this hwgroup (for now) */ 841 /* no more work for this hwgroup (for now) */
840 return; 842 goto plug_device;
841 } 843 }
842 again: 844
843 hwif = HWIF(drive); 845 if (drive != orig_drive)
846 goto plug_device;
847again:
848 hwif = drive->hwif;
849
844 if (hwif != hwgroup->hwif) { 850 if (hwif != hwgroup->hwif) {
845 /* 851 /*
846 * set nIEN for previous hwif, drives in the 852 * set nIEN for previous hwif, drives in the
@@ -888,41 +894,26 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
888 goto again; 894 goto again;
889 /* We clear busy, there should be no pending ATA command at this point. */ 895 /* We clear busy, there should be no pending ATA command at this point. */
890 hwgroup->busy = 0; 896 hwgroup->busy = 0;
891 break; 897 goto plug_device;
892 } 898 }
893 899
894 hwgroup->rq = rq; 900 hwgroup->rq = rq;
895 901
896 /* 902 spin_unlock_irq(&hwgroup->lock);
897 * Some systems have trouble with IDE IRQs arriving while
898 * the driver is still setting things up. So, here we disable
899 * the IRQ used by this interface while the request is being started.
900 * This may look bad at first, but pretty much the same thing
901 * happens anyway when any interrupt comes in, IDE or otherwise
902 * -- the kernel masks the IRQ while it is being handled.
903 */
904 if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
905 disable_irq_nosync(hwif->irq);
906 spin_unlock(&hwgroup->lock);
907 local_irq_enable_in_hardirq();
908 /* allow other IRQs while we start this request */
909 startstop = start_request(drive, rq); 903 startstop = start_request(drive, rq);
910 spin_lock_irq(&hwgroup->lock); 904 spin_lock_irq(&hwgroup->lock);
911 if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) 905
912 enable_irq(hwif->irq); 906 if (startstop == ide_stopped) {
913 if (startstop == ide_stopped)
914 hwgroup->busy = 0; 907 hwgroup->busy = 0;
908 if (!elv_queue_empty(orig_drive->queue))
909 blk_plug_device(orig_drive->queue);
910 }
915 } 911 }
916} 912 return;
917 913
918/* 914plug_device:
919 * Passes the stuff to ide_do_request 915 if (!elv_queue_empty(orig_drive->queue))
920 */ 916 blk_plug_device(orig_drive->queue);
921void do_ide_request(struct request_queue *q)
922{
923 ide_drive_t *drive = q->queuedata;
924
925 ide_do_request(HWGROUP(drive), IDE_NO_IRQ);
926} 917}
927 918
928/* 919/*
@@ -1074,11 +1065,13 @@ void ide_timer_expiry (unsigned long data)
1074 drive->service_time = jiffies - drive->service_start; 1065 drive->service_time = jiffies - drive->service_start;
1075 spin_lock_irq(&hwgroup->lock); 1066 spin_lock_irq(&hwgroup->lock);
1076 enable_irq(hwif->irq); 1067 enable_irq(hwif->irq);
1077 if (startstop == ide_stopped) 1068 if (startstop == ide_stopped) {
1078 hwgroup->busy = 0; 1069 hwgroup->busy = 0;
1070 if (!elv_queue_empty(drive->queue))
1071 blk_plug_device(drive->queue);
1072 }
1079 } 1073 }
1080 } 1074 }
1081 ide_do_request(hwgroup, IDE_NO_IRQ);
1082 spin_unlock_irqrestore(&hwgroup->lock, flags); 1075 spin_unlock_irqrestore(&hwgroup->lock, flags);
1083} 1076}
1084 1077
@@ -1271,11 +1264,11 @@ irqreturn_t ide_intr (int irq, void *dev_id)
1271 if (startstop == ide_stopped) { 1264 if (startstop == ide_stopped) {
1272 if (hwgroup->handler == NULL) { /* paranoia */ 1265 if (hwgroup->handler == NULL) { /* paranoia */
1273 hwgroup->busy = 0; 1266 hwgroup->busy = 0;
1274 ide_do_request(hwgroup, hwif->irq); 1267 if (!elv_queue_empty(drive->queue))
1275 } else { 1268 blk_plug_device(drive->queue);
1276 printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " 1269 } else
1277 "on exit\n", drive->name); 1270 printk(KERN_ERR "%s: %s: huh? expected NULL handler "
1278 } 1271 "on exit\n", __func__, drive->name);
1279 } 1272 }
1280out_handled: 1273out_handled:
1281 irq_ret = IRQ_HANDLED; 1274 irq_ret = IRQ_HANDLED;