aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware
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/isdn/hardware
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/isdn/hardware')
-rw-r--r--drivers/isdn/hardware/avm/avmcard.h4
-rw-r--r--drivers/isdn/hardware/avm/b1.c2
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c2
-rw-r--r--drivers/isdn/hardware/avm/c4.c2
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c2
-rw-r--r--drivers/isdn/hardware/eicon/diva.c4
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c3
7 files changed, 8 insertions, 11 deletions
diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h
index 3b431723c7c..d964f07e4a5 100644
--- a/drivers/isdn/hardware/avm/avmcard.h
+++ b/drivers/isdn/hardware/avm/avmcard.h
@@ -554,7 +554,7 @@ void b1_register_appl(struct capi_ctr *ctrl, u16 appl,
554void b1_release_appl(struct capi_ctr *ctrl, u16 appl); 554void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
555u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); 555u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
556void b1_parse_version(avmctrl_info *card); 556void b1_parse_version(avmctrl_info *card);
557irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs); 557irqreturn_t b1_interrupt(int interrupt, void *devptr);
558 558
559int b1ctl_read_proc(char *page, char **start, off_t off, 559int b1ctl_read_proc(char *page, char **start, off_t off,
560 int count, int *eof, struct capi_ctr *ctrl); 560 int count, int *eof, struct capi_ctr *ctrl);
@@ -567,7 +567,7 @@ void avmcard_dma_free(avmcard_dmainfo *);
567int b1pciv4_detect(avmcard *card); 567int b1pciv4_detect(avmcard *card);
568int t1pci_detect(avmcard *card); 568int t1pci_detect(avmcard *card);
569void b1dma_reset(avmcard *card); 569void b1dma_reset(avmcard *card);
570irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs); 570irqreturn_t b1dma_interrupt(int interrupt, void *devptr);
571 571
572int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); 572int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
573void b1dma_reset_ctr(struct capi_ctr *ctrl); 573void b1dma_reset_ctr(struct capi_ctr *ctrl);
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 0c7061d5502..da272924771 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -485,7 +485,7 @@ void b1_parse_version(avmctrl_info *cinfo)
485 485
486/* ------------------------------------------------------------- */ 486/* ------------------------------------------------------------- */
487 487
488irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs) 488irqreturn_t b1_interrupt(int interrupt, void *devptr)
489{ 489{
490 avmcard *card = devptr; 490 avmcard *card = devptr;
491 avmctrl_info *cinfo = &card->ctrlinfo[0]; 491 avmctrl_info *cinfo = &card->ctrlinfo[0];
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index a4beeb46c85..ddd47cdfdb1 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -628,7 +628,7 @@ static void b1dma_handle_interrupt(avmcard *card)
628 spin_unlock(&card->lock); 628 spin_unlock(&card->lock);
629} 629}
630 630
631irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs) 631irqreturn_t b1dma_interrupt(int interrupt, void *devptr)
632{ 632{
633 avmcard *card = devptr; 633 avmcard *card = devptr;
634 634
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 6c3d5f5f1f4..2a3eb38f0eb 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -713,7 +713,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
713 return IRQ_HANDLED; 713 return IRQ_HANDLED;
714} 714}
715 715
716static irqreturn_t c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs) 716static irqreturn_t c4_interrupt(int interrupt, void *devptr)
717{ 717{
718 avmcard *card = devptr; 718 avmcard *card = devptr;
719 719
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index 5a2f854d55b..e47c60b0a8e 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -131,7 +131,7 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
131 return 0; 131 return 0;
132} 132}
133 133
134static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) 134static irqreturn_t t1isa_interrupt(int interrupt, void *devptr)
135{ 135{
136 avmcard *card = devptr; 136 avmcard *card = devptr;
137 avmctrl_info *cinfo = &card->ctrlinfo[0]; 137 avmctrl_info *cinfo = &card->ctrlinfo[0];
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
index 8ab8027f33c..ffa2afa77c2 100644
--- a/drivers/isdn/hardware/eicon/diva.c
+++ b/drivers/isdn/hardware/eicon/diva.c
@@ -71,8 +71,6 @@ DivaIdiReqFunc(29)
71DivaIdiReqFunc(30) 71DivaIdiReqFunc(30)
72DivaIdiReqFunc(31) 72DivaIdiReqFunc(31)
73 73
74struct pt_regs;
75
76/* 74/*
77** LOCALS 75** LOCALS
78*/ 76*/
@@ -515,7 +513,7 @@ diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
515} 513}
516 514
517 515
518irqreturn_t diva_os_irq_wrapper(int irq, void *context, struct pt_regs *regs) 516irqreturn_t diva_os_irq_wrapper(int irq, void *context)
519{ 517{
520 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context; 518 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
521 diva_xdi_clear_interrupts_proc_t clear_int_proc; 519 diva_xdi_clear_interrupts_proc_t clear_int_proc;
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index b7dadba13e8..dae2e83dd5e 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -58,8 +58,7 @@ static char *DRIVERLNAME = "divas";
58static char *DEVNAME = "Divas"; 58static char *DEVNAME = "Divas";
59char *DRIVERRELEASE_DIVAS = "2.0"; 59char *DRIVERRELEASE_DIVAS = "2.0";
60 60
61extern irqreturn_t diva_os_irq_wrapper(int irq, void *context, 61extern irqreturn_t diva_os_irq_wrapper(int irq, void *context);
62 struct pt_regs *regs);
63extern int create_divas_proc(void); 62extern int create_divas_proc(void);
64extern void remove_divas_proc(void); 63extern void remove_divas_proc(void);
65extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf); 64extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);