aboutsummaryrefslogtreecommitdiffstats
path: root/sound/oss/dmasound
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-10-05 09:55:46 -0400
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-10-05 10:10:12 -0400
commit7d12e780e003f93433d49ce78cfedf4b4c52adc5 (patch)
tree6748550400445c11a306b132009f3001e3525df8 /sound/oss/dmasound
parentda482792a6d1a3fbaaa25fae867b343fb4db3246 (diff)
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead of passing regs around manually through all ~1800 interrupt handlers in the Linux kernel. The regs pointer is used in few places, but it potentially costs both stack space and code to pass it around. On the FRV arch, removing the regs parameter from all the genirq function results in a 20% speed up of the IRQ exit path (ie: from leaving timer_interrupt() to leaving do_IRQ()). Where appropriate, an arch may override the generic storage facility and do something different with the variable. On FRV, for instance, the address is maintained in GR28 at all times inside the kernel as part of general exception handling. Having looked over the code, it appears that the parameter may be handed down through up to twenty or so layers of functions. Consider a USB character device attached to a USB hub, attached to a USB controller that posts its interrupts through a cascaded auxiliary interrupt controller. A character device driver may want to pass regs to the sysrq handler through the input layer which adds another few layers of parameter passing. I've build this code with allyesconfig for x86_64 and i386. I've runtested the main part of the code on FRV and i386, though I can't test most of the drivers. I've also done partial conversion for powerpc and MIPS - these at least compile with minimal configurations. This will affect all archs. Mostly the changes should be relatively easy. Take do_IRQ(), store the regs pointer at the beginning, saving the old one: struct pt_regs *old_regs = set_irq_regs(regs); And put the old one back at the end: set_irq_regs(old_regs); Don't pass regs through to generic_handle_irq() or __do_IRQ(). In timer_interrupt(), this sort of change will be necessary: - update_process_times(user_mode(regs)); - profile_tick(CPU_PROFILING, regs); + update_process_times(user_mode(get_irq_regs())); + profile_tick(CPU_PROFILING); I'd like to move update_process_times()'s use of get_irq_regs() into itself, except that i386, alone of the archs, uses something other than user_mode(). Some notes on the interrupt handling in the drivers: (*) input_dev() is now gone entirely. The regs pointer is no longer stored in the input_dev struct. (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does something different depending on whether it's been supplied with a regs pointer or not. (*) Various IRQ handler function pointers have been moved to type irq_handler_t. Signed-Off-By: David Howells <dhowells@redhat.com> (cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
Diffstat (limited to 'sound/oss/dmasound')
-rw-r--r--sound/oss/dmasound/dmasound_atari.c4
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c14
-rw-r--r--sound/oss/dmasound/dmasound_paula.c4
-rw-r--r--sound/oss/dmasound/dmasound_q40.c8
4 files changed, 15 insertions, 15 deletions
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index dc31373069a5..285239d64b82 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -133,7 +133,7 @@ static int FalconSetFormat(int format);
133static int FalconSetVolume(int volume); 133static int FalconSetVolume(int volume);
134static void AtaPlayNextFrame(int index); 134static void AtaPlayNextFrame(int index);
135static void AtaPlay(void); 135static void AtaPlay(void);
136static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp); 136static irqreturn_t AtaInterrupt(int irq, void *dummy);
137 137
138/*** Mid level stuff *********************************************************/ 138/*** Mid level stuff *********************************************************/
139 139
@@ -1257,7 +1257,7 @@ static void AtaPlay(void)
1257} 1257}
1258 1258
1259 1259
1260static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp) 1260static irqreturn_t AtaInterrupt(int irq, void *dummy)
1261{ 1261{
1262#if 0 1262#if 0
1263 /* ++TeSche: if you should want to test this... */ 1263 /* ++TeSche: if you should want to test this... */
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 9ae659f82430..3bd19c36fcd9 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -281,9 +281,9 @@ static int PMacSetFormat(int format);
281static int PMacSetVolume(int volume); 281static int PMacSetVolume(int volume);
282static void PMacPlay(void); 282static void PMacPlay(void);
283static void PMacRecord(void); 283static void PMacRecord(void);
284static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs); 284static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid);
285static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs); 285static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid);
286static irqreturn_t pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs); 286static irqreturn_t pmac_awacs_intr(int irq, void *devid);
287static void awacs_write(int val); 287static void awacs_write(int val);
288static int awacs_get_volume(int reg, int lshift); 288static int awacs_get_volume(int reg, int lshift);
289static int awacs_volume_setter(int volume, int n, int mute, int lshift); 289static int awacs_volume_setter(int volume, int n, int mute, int lshift);
@@ -398,7 +398,7 @@ read_audio_gpio(int gpio_addr)
398 * Headphone interrupt via GPIO (Tumbler, Snapper, DACA) 398 * Headphone interrupt via GPIO (Tumbler, Snapper, DACA)
399 */ 399 */
400static irqreturn_t 400static irqreturn_t
401headphone_intr(int irq, void *devid, struct pt_regs *regs) 401headphone_intr(int irq, void *devid)
402{ 402{
403 unsigned long flags; 403 unsigned long flags;
404 404
@@ -1037,7 +1037,7 @@ static void PMacRecord(void)
1037*/ 1037*/
1038 1038
1039static irqreturn_t 1039static irqreturn_t
1040pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs) 1040pmac_awacs_tx_intr(int irq, void *devid)
1041{ 1041{
1042 int i = write_sq.front; 1042 int i = write_sq.front;
1043 int stat; 1043 int stat;
@@ -1129,7 +1129,7 @@ printk("dmasound_pmac: tx-irq: xfer died - patching it up...\n") ;
1129 1129
1130 1130
1131static irqreturn_t 1131static irqreturn_t
1132pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs) 1132pmac_awacs_rx_intr(int irq, void *devid)
1133{ 1133{
1134 int stat ; 1134 int stat ;
1135 /* For some reason on my PowerBook G3, I get one interrupt 1135 /* For some reason on my PowerBook G3, I get one interrupt
@@ -1212,7 +1212,7 @@ printk("dmasound_pmac: rx-irq: DIED - attempting resurection\n");
1212 1212
1213 1213
1214static irqreturn_t 1214static irqreturn_t
1215pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) 1215pmac_awacs_intr(int irq, void *devid)
1216{ 1216{
1217 int ctrl; 1217 int ctrl;
1218 int status; 1218 int status;
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index 68e1d8f6c359..90fc058e1159 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -82,7 +82,7 @@ static int AmiSetVolume(int volume);
82static int AmiSetTreble(int treble); 82static int AmiSetTreble(int treble);
83static void AmiPlayNextFrame(int index); 83static void AmiPlayNextFrame(int index);
84static void AmiPlay(void); 84static void AmiPlay(void);
85static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp); 85static irqreturn_t AmiInterrupt(int irq, void *dummy);
86 86
87#ifdef CONFIG_HEARTBEAT 87#ifdef CONFIG_HEARTBEAT
88 88
@@ -556,7 +556,7 @@ static void AmiPlay(void)
556} 556}
557 557
558 558
559static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp) 559static irqreturn_t AmiInterrupt(int irq, void *dummy)
560{ 560{
561 int minframes = 1; 561 int minframes = 1;
562 562
diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c
index e2081f32b0c4..b3379dd7ca5e 100644
--- a/sound/oss/dmasound/dmasound_q40.c
+++ b/sound/oss/dmasound/dmasound_q40.c
@@ -48,8 +48,8 @@ static int Q40SetFormat(int format);
48static int Q40SetVolume(int volume); 48static int Q40SetVolume(int volume);
49static void Q40PlayNextFrame(int index); 49static void Q40PlayNextFrame(int index);
50static void Q40Play(void); 50static void Q40Play(void);
51static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp); 51static irqreturn_t Q40StereoInterrupt(int irq, void *dummy);
52static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp); 52static irqreturn_t Q40MonoInterrupt(int irq, void *dummy);
53static void Q40Interrupt(void); 53static void Q40Interrupt(void);
54 54
55 55
@@ -451,7 +451,7 @@ static void Q40Play(void)
451 spin_unlock_irqrestore(&dmasound.lock, flags); 451 spin_unlock_irqrestore(&dmasound.lock, flags);
452} 452}
453 453
454static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp) 454static irqreturn_t Q40StereoInterrupt(int irq, void *dummy)
455{ 455{
456 spin_lock(&dmasound.lock); 456 spin_lock(&dmasound.lock);
457 if (q40_sc>1){ 457 if (q40_sc>1){
@@ -463,7 +463,7 @@ static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp)
463 spin_unlock(&dmasound.lock); 463 spin_unlock(&dmasound.lock);
464 return IRQ_HANDLED; 464 return IRQ_HANDLED;
465} 465}
466static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp) 466static irqreturn_t Q40MonoInterrupt(int irq, void *dummy)
467{ 467{
468 spin_lock(&dmasound.lock); 468 spin_lock(&dmasound.lock);
469 if (q40_sc>0){ 469 if (q40_sc>0){