aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
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/usb
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/usb')
-rw-r--r--sound/usb/usbaudio.c4
-rw-r--r--sound/usb/usbmidi.c4
-rw-r--r--sound/usb/usbmixer.c5
-rw-r--r--sound/usb/usx2y/usbusx2y.c4
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c10
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c6
6 files changed, 16 insertions, 17 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index a42acf6d7b68..c82b01c7ad3a 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -653,7 +653,7 @@ static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
653/* 653/*
654 * complete callback from data urb 654 * complete callback from data urb
655 */ 655 */
656static void snd_complete_urb(struct urb *urb, struct pt_regs *regs) 656static void snd_complete_urb(struct urb *urb)
657{ 657{
658 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 658 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
659 struct snd_usb_substream *subs = ctx->subs; 659 struct snd_usb_substream *subs = ctx->subs;
@@ -676,7 +676,7 @@ static void snd_complete_urb(struct urb *urb, struct pt_regs *regs)
676/* 676/*
677 * complete callback from sync urb 677 * complete callback from sync urb
678 */ 678 */
679static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs) 679static void snd_complete_sync_urb(struct urb *urb)
680{ 680{
681 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 681 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
682 struct snd_usb_substream *subs = ctx->subs; 682 struct snd_usb_substream *subs = ctx->subs;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 0dcf78adb99a..b7c5e59b2299 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -223,7 +223,7 @@ static void dump_urb(const char *type, const u8 *data, int length)
223/* 223/*
224 * Processes the data read from the device. 224 * Processes the data read from the device.
225 */ 225 */
226static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs) 226static void snd_usbmidi_in_urb_complete(struct urb* urb)
227{ 227{
228 struct snd_usb_midi_in_endpoint* ep = urb->context; 228 struct snd_usb_midi_in_endpoint* ep = urb->context;
229 229
@@ -247,7 +247,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
247 snd_usbmidi_submit_urb(urb, GFP_ATOMIC); 247 snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
248} 248}
249 249
250static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs) 250static void snd_usbmidi_out_urb_complete(struct urb* urb)
251{ 251{
252 struct snd_usb_midi_out_endpoint* ep = urb->context; 252 struct snd_usb_midi_out_endpoint* ep = urb->context;
253 253
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e516d6adbb22..1024c178f5c0 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1710,7 +1710,7 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
1710 } 1710 }
1711} 1711}
1712 1712
1713static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs) 1713static void snd_usb_mixer_status_complete(struct urb *urb)
1714{ 1714{
1715 struct usb_mixer_interface *mixer = urb->context; 1715 struct usb_mixer_interface *mixer = urb->context;
1716 1716
@@ -1772,8 +1772,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
1772 return 0; 1772 return 0;
1773} 1773}
1774 1774
1775static void snd_usb_soundblaster_remote_complete(struct urb *urb, 1775static void snd_usb_soundblaster_remote_complete(struct urb *urb)
1776 struct pt_regs *regs)
1777{ 1776{
1778 struct usb_mixer_interface *mixer = urb->context; 1777 struct usb_mixer_interface *mixer = urb->context;
1779 const struct rc_config *rc = mixer->rc_cfg; 1778 const struct rc_config *rc = mixer->rc_cfg;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cfec38d7839b..e011fcacce92 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -172,7 +172,7 @@ static void snd_usX2Y_card_private_free(struct snd_card *card);
172/* 172/*
173 * pipe 4 is used for switching the lamps, setting samplerate, volumes .... 173 * pipe 4 is used for switching the lamps, setting samplerate, volumes ....
174 */ 174 */
175static void i_usX2Y_Out04Int(struct urb *urb, struct pt_regs *regs) 175static void i_usX2Y_Out04Int(struct urb *urb)
176{ 176{
177#ifdef CONFIG_SND_DEBUG 177#ifdef CONFIG_SND_DEBUG
178 if (urb->status) { 178 if (urb->status) {
@@ -184,7 +184,7 @@ static void i_usX2Y_Out04Int(struct urb *urb, struct pt_regs *regs)
184#endif 184#endif
185} 185}
186 186
187static void i_usX2Y_In04Int(struct urb *urb, struct pt_regs *regs) 187static void i_usX2Y_In04Int(struct urb *urb)
188{ 188{
189 int err = 0; 189 int err = 0;
190 struct usX2Ydev *usX2Y = urb->context; 190 struct usX2Ydev *usX2Y = urb->context;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index f6bd0dee563c..e662281a751a 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -306,7 +306,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
306 usX2Y_clients_stop(usX2Y); 306 usX2Y_clients_stop(usX2Y);
307} 307}
308 308
309static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs) 309static void i_usX2Y_urb_complete(struct urb *urb)
310{ 310{
311 struct snd_usX2Y_substream *subs = urb->context; 311 struct snd_usX2Y_substream *subs = urb->context;
312 struct usX2Ydev *usX2Y = subs->usX2Y; 312 struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -350,7 +350,7 @@ static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
350} 350}
351 351
352static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, 352static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y,
353 void (*complete)(struct urb *, struct pt_regs *)) 353 void (*complete)(struct urb *))
354{ 354{
355 int s, u; 355 int s, u;
356 for (s = 0; s < 4; s++) { 356 for (s = 0; s < 4; s++) {
@@ -370,7 +370,7 @@ static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y)
370 usX2Y->prepare_subs = NULL; 370 usX2Y->prepare_subs = NULL;
371} 371}
372 372
373static void i_usX2Y_subs_startup(struct urb *urb, struct pt_regs *regs) 373static void i_usX2Y_subs_startup(struct urb *urb)
374{ 374{
375 struct snd_usX2Y_substream *subs = urb->context; 375 struct snd_usX2Y_substream *subs = urb->context;
376 struct usX2Ydev *usX2Y = subs->usX2Y; 376 struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -382,7 +382,7 @@ static void i_usX2Y_subs_startup(struct urb *urb, struct pt_regs *regs)
382 wake_up(&usX2Y->prepare_wait_queue); 382 wake_up(&usX2Y->prepare_wait_queue);
383 } 383 }
384 384
385 i_usX2Y_urb_complete(urb, regs); 385 i_usX2Y_urb_complete(urb);
386} 386}
387 387
388static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) 388static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs)
@@ -663,7 +663,7 @@ static struct s_c2 SetRate48000[] =
663}; 663};
664#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000) 664#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
665 665
666static void i_usX2Y_04Int(struct urb *urb, struct pt_regs *regs) 666static void i_usX2Y_04Int(struct urb *urb)
667{ 667{
668 struct usX2Ydev *usX2Y = urb->context; 668 struct usX2Ydev *usX2Y = urb->context;
669 669
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 88b72b52590f..9acef9d90543 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -226,7 +226,7 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap
226} 226}
227 227
228 228
229static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs) 229static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
230{ 230{
231 struct snd_usX2Y_substream *subs = urb->context; 231 struct snd_usX2Y_substream *subs = urb->context;
232 struct usX2Ydev *usX2Y = subs->usX2Y; 232 struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -294,7 +294,7 @@ static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y)
294 usX2Y->prepare_subs = NULL; 294 usX2Y->prepare_subs = NULL;
295} 295}
296 296
297static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs) 297static void i_usX2Y_usbpcm_subs_startup(struct urb *urb)
298{ 298{
299 struct snd_usX2Y_substream *subs = urb->context; 299 struct snd_usX2Y_substream *subs = urb->context;
300 struct usX2Ydev *usX2Y = subs->usX2Y; 300 struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -311,7 +311,7 @@ static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs)
311 wake_up(&usX2Y->prepare_wait_queue); 311 wake_up(&usX2Y->prepare_wait_queue);
312 } 312 }
313 313
314 i_usX2Y_usbpcm_urb_complete(urb, regs); 314 i_usX2Y_usbpcm_urb_complete(urb);
315} 315}
316 316
317/* 317/*