aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
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/video
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/video')
-rw-r--r--drivers/video/amifb.c4
-rw-r--r--drivers/video/arcfb.c3
-rw-r--r--drivers/video/atafb.c2
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--drivers/video/au1200fb.c2
-rw-r--r--drivers/video/console/fbcon.c4
-rw-r--r--drivers/video/intelfb/intelfbhw.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c2
-rw-r--r--drivers/video/pvr2fb.c4
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/s3c2410fb.c2
-rw-r--r--drivers/video/sa1100fb.c2
12 files changed, 15 insertions, 16 deletions
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index f1ba54f4fc39..a4e3fca05891 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1144,7 +1144,7 @@ static void amifb_deinit(void);
1144 */ 1144 */
1145 1145
1146static int flash_cursor(void); 1146static int flash_cursor(void);
1147static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp); 1147static irqreturn_t amifb_interrupt(int irq, void *dev_id);
1148static u_long chipalloc(u_long size); 1148static u_long chipalloc(u_long size);
1149static void chipfree(void); 1149static void chipfree(void);
1150 1150
@@ -2492,7 +2492,7 @@ static int flash_cursor(void)
2492 * VBlank Display Interrupt 2492 * VBlank Display Interrupt
2493 */ 2493 */
2494 2494
2495static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp) 2495static irqreturn_t amifb_interrupt(int irq, void *dev_id)
2496{ 2496{
2497 if (do_vmode_pan || do_vmode_full) 2497 if (do_vmode_pan || do_vmode_full)
2498 ami_update_display(); 2498 ami_update_display();
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 70dd8115a4d8..ab34b96acc31 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -218,8 +218,7 @@ static int arcfb_pan_display(struct fb_var_screeninfo *var,
218 return -EINVAL; 218 return -EINVAL;
219} 219}
220 220
221static irqreturn_t arcfb_interrupt(int vec, void *dev_instance, 221static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
222 struct pt_regs *regs)
223{ 222{
224 struct fb_info *info = dev_instance; 223 struct fb_info *info = dev_instance;
225 unsigned char ctl2status; 224 unsigned char ctl2status;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 5831893bf7a0..02c41a626fa2 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1521,7 +1521,7 @@ static void falcon_set_par( struct atafb_par *par )
1521} 1521}
1522 1522
1523 1523
1524static irqreturn_t falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp ) 1524static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
1525{ 1525{
1526 struct falcon_hw *hw = &f_new_mode; 1526 struct falcon_hw *hw = &f_new_mode;
1527 1527
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index b45c9fd1b330..b77b30923928 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1532,7 +1532,7 @@ static int atyfb_open(struct fb_info *info, int user)
1532 return (0); 1532 return (0);
1533} 1533}
1534 1534
1535static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp) 1535static irqreturn_t aty_irq(int irq, void *dev_id)
1536{ 1536{
1537 struct atyfb_par *par = dev_id; 1537 struct atyfb_par *par = dev_id;
1538 int handled = 0; 1538 int handled = 0;
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index c6a5f0ccc107..dbf4ec3f6d57 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1545,7 +1545,7 @@ static struct fb_ops au1200fb_fb_ops = {
1545 1545
1546/*-------------------------------------------------------------------------*/ 1546/*-------------------------------------------------------------------------*/
1547 1547
1548static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) 1548static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
1549{ 1549{
1550 /* Nothing to do for now, just clear any pending interrupt */ 1550 /* Nothing to do for now, just clear any pending interrupt */
1551 lcd->intstatus = lcd->intstatus; 1551 lcd->intstatus = lcd->intstatus;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 8c041daa3a15..302174b8e477 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -204,7 +204,7 @@ static struct class_device *fbcon_class_device;
204 */ 204 */
205static int vbl_detected; 205static int vbl_detected;
206 206
207static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) 207static irqreturn_t fb_vbl_detect(int irq, void *dummy)
208{ 208{
209 vbl_detected++; 209 vbl_detected++;
210 return IRQ_HANDLED; 210 return IRQ_HANDLED;
@@ -414,7 +414,7 @@ static void fb_flashcursor(void *private)
414 414
415#if defined(CONFIG_ATARI) || defined(CONFIG_MAC) 415#if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
416static int cursor_blink_rate; 416static int cursor_blink_rate;
417static irqreturn_t fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp) 417static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
418{ 418{
419 struct fb_info *info = dev_id; 419 struct fb_info *info = dev_id;
420 420
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index f887f1efd3fe..eeeeff9a09eb 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -1952,7 +1952,7 @@ intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
1952} 1952}
1953 1953
1954static irqreturn_t 1954static irqreturn_t
1955intelfbhw_irq(int irq, void *dev_id, struct pt_regs *fp) { 1955intelfbhw_irq(int irq, void *dev_id) {
1956 int handled = 0; 1956 int handled = 0;
1957 u16 tmp; 1957 u16 tmp;
1958 struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; 1958 struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 7acf01c181ee..e9b4115fcad0 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -198,7 +198,7 @@ static void matroxfb_crtc1_panpos(WPMINFO2) {
198 } 198 }
199} 199}
200 200
201static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp) 201static irqreturn_t matrox_irq(int irq, void *dev_id)
202{ 202{
203 u_int32_t status; 203 u_int32_t status;
204 int handled = 0; 204 int handled = 0;
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 78dc59a1751b..c7bc80921f16 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -209,7 +209,7 @@ static int pvr2fb_set_par(struct fb_info *info);
209static void pvr2_update_display(struct fb_info *info); 209static void pvr2_update_display(struct fb_info *info);
210static void pvr2_init_display(struct fb_info *info); 210static void pvr2_init_display(struct fb_info *info);
211static void pvr2_do_blank(void); 211static void pvr2_do_blank(void);
212static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp); 212static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id);
213static int pvr2_init_cable(void); 213static int pvr2_init_cable(void);
214static int pvr2_get_param(const struct pvr2_params *p, const char *s, 214static int pvr2_get_param(const struct pvr2_params *p, const char *s,
215 int val, int size); 215 int val, int size);
@@ -626,7 +626,7 @@ static void pvr2_do_blank(void)
626 is_blanked = do_blank > 0 ? do_blank : 0; 626 is_blanked = do_blank > 0 ? do_blank : 0;
627} 627}
628 628
629static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp) 629static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
630{ 630{
631 struct fb_info *info = dev_id; 631 struct fb_info *info = dev_id;
632 632
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 3bc5da4a57ca..8a8ae55a7403 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -846,7 +846,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
846/* 846/*
847 * pxafb_handle_irq: Handle 'LCD DONE' interrupts. 847 * pxafb_handle_irq: Handle 'LCD DONE' interrupts.
848 */ 848 */
849static irqreturn_t pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) 849static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
850{ 850{
851 struct pxafb_info *fbi = dev_id; 851 struct pxafb_info *fbi = dev_id;
852 unsigned int lcsr = LCSR; 852 unsigned int lcsr = LCSR;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ad3bdd6f1ac1..59407343cc73 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -614,7 +614,7 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
614 } 614 }
615} 615}
616 616
617static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r) 617static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
618{ 618{
619 struct s3c2410fb_info *fbi = dev_id; 619 struct s3c2410fb_info *fbi = dev_id;
620 unsigned long lcdirq = readl(S3C2410_LCDINTPND); 620 unsigned long lcdirq = readl(S3C2410_LCDINTPND);
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index a2e6e7205d7e..cd10b18150b8 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1085,7 +1085,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
1085/* 1085/*
1086 * sa1100fb_handle_irq: Handle 'LCD DONE' interrupts. 1086 * sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
1087 */ 1087 */
1088static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) 1088static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
1089{ 1089{
1090 struct sa1100fb_info *fbi = dev_id; 1090 struct sa1100fb_info *fbi = dev_id;
1091 unsigned int lcsr = LCSR; 1091 unsigned int lcsr = LCSR;