aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/auerswald.c
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 /drivers/usb/misc/auerswald.c
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 'drivers/usb/misc/auerswald.c')
-rw-r--r--drivers/usb/misc/auerswald.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 4fd2110b3411..0be9d62d62ae 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -267,7 +267,7 @@ typedef struct
267 267
268/*-------------------------------------------------------------------*/ 268/*-------------------------------------------------------------------*/
269/* Forwards */ 269/* Forwards */
270static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs); 270static void auerswald_ctrlread_complete (struct urb * urb);
271static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp); 271static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
272static struct usb_driver auerswald_driver; 272static struct usb_driver auerswald_driver;
273 273
@@ -277,7 +277,7 @@ static struct usb_driver auerswald_driver;
277/* -------------------------- */ 277/* -------------------------- */
278 278
279/* completion function for chained urbs */ 279/* completion function for chained urbs */
280static void auerchain_complete (struct urb * urb, struct pt_regs *regs) 280static void auerchain_complete (struct urb * urb)
281{ 281{
282 unsigned long flags; 282 unsigned long flags;
283 int result; 283 int result;
@@ -296,7 +296,7 @@ static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
296 NOTE: this function may lead to more urbs submitted into the chain. 296 NOTE: this function may lead to more urbs submitted into the chain.
297 (no chain lock at calling complete()!) 297 (no chain lock at calling complete()!)
298 acp->active != NULL is protecting us against recursion.*/ 298 acp->active != NULL is protecting us against recursion.*/
299 urb->complete (urb, regs); 299 urb->complete (urb);
300 300
301 /* detach element from chain data structure */ 301 /* detach element from chain data structure */
302 spin_lock_irqsave (&acp->lock, flags); 302 spin_lock_irqsave (&acp->lock, flags);
@@ -331,7 +331,7 @@ static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
331 urb->status = result; 331 urb->status = result;
332 dbg("auerchain_complete: usb_submit_urb with error code %d", result); 332 dbg("auerchain_complete: usb_submit_urb with error code %d", result);
333 /* and do error handling via *this* completion function (recursive) */ 333 /* and do error handling via *this* completion function (recursive) */
334 auerchain_complete( urb, NULL); 334 auerchain_complete( urb);
335 } 335 }
336 } else { 336 } else {
337 /* simple return without submitting a new urb. 337 /* simple return without submitting a new urb.
@@ -408,7 +408,7 @@ static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int ea
408 urb->status = result; 408 urb->status = result;
409 dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result); 409 dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
410 /* and do error handling via completion function */ 410 /* and do error handling via completion function */
411 auerchain_complete( urb, NULL); 411 auerchain_complete( urb);
412 } 412 }
413 } 413 }
414 414
@@ -448,7 +448,7 @@ static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
448 spin_unlock_irqrestore (&acp->lock, flags); 448 spin_unlock_irqrestore (&acp->lock, flags);
449 dbg ("unlink waiting urb"); 449 dbg ("unlink waiting urb");
450 urb->status = -ENOENT; 450 urb->status = -ENOENT;
451 urb->complete (urb, NULL); 451 urb->complete (urb);
452 return 0; 452 return 0;
453 } 453 }
454 } 454 }
@@ -505,7 +505,7 @@ static void auerchain_unlink_all (pauerchain_t acp)
505 spin_unlock_irqrestore (&acp->lock, flags); 505 spin_unlock_irqrestore (&acp->lock, flags);
506 dbg ("unlink waiting urb"); 506 dbg ("unlink waiting urb");
507 urbp->status = -ENOENT; 507 urbp->status = -ENOENT;
508 urbp->complete (urbp, NULL); 508 urbp->complete (urbp);
509 spin_lock_irqsave (&acp->lock, flags); 509 spin_lock_irqsave (&acp->lock, flags);
510 } 510 }
511 spin_unlock_irqrestore (&acp->lock, flags); 511 spin_unlock_irqrestore (&acp->lock, flags);
@@ -591,7 +591,7 @@ ac_fail:/* free the elements */
591 591
592 592
593/* completion handler for synchronous chained URBs */ 593/* completion handler for synchronous chained URBs */
594static void auerchain_blocking_completion (struct urb *urb, struct pt_regs *regs) 594static void auerchain_blocking_completion (struct urb *urb)
595{ 595{
596 pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context; 596 pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
597 pchs->done = 1; 597 pchs->done = 1;
@@ -846,7 +846,7 @@ static int auerswald_status_retry (int status)
846} 846}
847 847
848/* Completion of asynchronous write block */ 848/* Completion of asynchronous write block */
849static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs) 849static void auerchar_ctrlwrite_complete (struct urb * urb)
850{ 850{
851 pauerbuf_t bp = (pauerbuf_t) urb->context; 851 pauerbuf_t bp = (pauerbuf_t) urb->context;
852 pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); 852 pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
@@ -859,7 +859,7 @@ static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs)
859} 859}
860 860
861/* Completion handler for dummy retry packet */ 861/* Completion handler for dummy retry packet */
862static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *regs) 862static void auerswald_ctrlread_wretcomplete (struct urb * urb)
863{ 863{
864 pauerbuf_t bp = (pauerbuf_t) urb->context; 864 pauerbuf_t bp = (pauerbuf_t) urb->context;
865 pauerswald_t cp; 865 pauerswald_t cp;
@@ -893,12 +893,12 @@ static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *r
893 if (ret) { 893 if (ret) {
894 dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); 894 dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
895 bp->urbp->status = ret; 895 bp->urbp->status = ret;
896 auerswald_ctrlread_complete (bp->urbp, NULL); 896 auerswald_ctrlread_complete (bp->urbp);
897 } 897 }
898} 898}
899 899
900/* completion handler for receiving of control messages */ 900/* completion handler for receiving of control messages */
901static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs) 901static void auerswald_ctrlread_complete (struct urb * urb)
902{ 902{
903 unsigned int serviceid; 903 unsigned int serviceid;
904 pauerswald_t cp; 904 pauerswald_t cp;
@@ -941,7 +941,7 @@ static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
941 if (ret) { 941 if (ret) {
942 dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); 942 dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
943 bp->urbp->status = ret; 943 bp->urbp->status = ret;
944 auerswald_ctrlread_wretcomplete (bp->urbp, regs); 944 auerswald_ctrlread_wretcomplete (bp->urbp);
945 } 945 }
946 return; 946 return;
947 } 947 }
@@ -970,7 +970,7 @@ static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
970 messages from the USB device. 970 messages from the USB device.
971*/ 971*/
972/* int completion handler. */ 972/* int completion handler. */
973static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs) 973static void auerswald_int_complete (struct urb * urb)
974{ 974{
975 unsigned long flags; 975 unsigned long flags;
976 unsigned int channelid; 976 unsigned int channelid;
@@ -1070,7 +1070,7 @@ static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs)
1070 if (ret) { 1070 if (ret) {
1071 dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret); 1071 dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
1072 bp->urbp->status = ret; 1072 bp->urbp->status = ret;
1073 auerswald_ctrlread_complete( bp->urbp, NULL); 1073 auerswald_ctrlread_complete( bp->urbp);
1074 /* here applies the same problem as above: device locking! */ 1074 /* here applies the same problem as above: device locking! */
1075 } 1075 }
1076exit: 1076exit: