aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
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/i2c/busses
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/i2c/busses')
-rw-r--r--drivers/i2c/busses/i2c-elektor.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-ite.c3
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-ocores.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/i2c-rpx.c4
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c3
12 files changed, 14 insertions, 16 deletions
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index caa8e5c8bfbb..a591fe685f06 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -131,7 +131,7 @@ static void pcf_isa_waitforpin(void) {
131} 131}
132 132
133 133
134static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) { 134static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) {
135 spin_lock(&lock); 135 spin_lock(&lock);
136 pcf_pending = 1; 136 pcf_pending = 1;
137 spin_unlock(&lock); 137 spin_unlock(&lock);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 80d4ba1bdfec..781a99c1647a 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -320,7 +320,7 @@ err:
320/* 320/*
321 * IIC interrupt handler 321 * IIC interrupt handler
322 */ 322 */
323static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) 323static irqreturn_t iic_handler(int irq, void *dev_id)
324{ 324{
325 struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; 325 struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
326 volatile struct iic_regs __iomem *iic = dev->vaddr; 326 volatile struct iic_regs __iomem *iic = dev->vaddr;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 4436c89be58e..d108ab4974cc 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -120,7 +120,7 @@ iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
120 * Then it passes the SR flags of interest to BH via adap data 120 * Then it passes the SR flags of interest to BH via adap data
121 */ 121 */
122static irqreturn_t 122static irqreturn_t
123iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) 123iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
124{ 124{
125 struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; 125 struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
126 u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); 126 u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 559a62b04ee9..f7d71869b3b9 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -140,8 +140,7 @@ static void iic_ite_waitforpin(void) {
140} 140}
141 141
142 142
143static irqreturn_t iic_ite_handler(int this_irq, void *dev_id, 143static irqreturn_t iic_ite_handler(int this_irq, void *dev_id)
144 struct pt_regs *regs)
145{ 144{
146 spin_lock(&lock); 145 spin_lock(&lock);
147 iic_pending = 1; 146 iic_pending = 1;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 155a986de516..ee65aa1be13a 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -63,7 +63,7 @@ static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
63 writeb(x, i2c->base + MPC_I2C_CR); 63 writeb(x, i2c->base + MPC_I2C_CR);
64} 64}
65 65
66static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs) 66static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
67{ 67{
68 struct mpc_i2c *i2c = dev_id; 68 struct mpc_i2c *i2c = dev_id;
69 if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) { 69 if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index eacbaf745b64..bbc8e3a7ff55 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -278,7 +278,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
278} 278}
279 279
280static int 280static int
281mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs) 281mv64xxx_i2c_intr(int irq, void *dev_id)
282{ 282{
283 struct mv64xxx_i2c_data *drv_data = dev_id; 283 struct mv64xxx_i2c_data *drv_data = dev_id;
284 unsigned long flags; 284 unsigned long flags;
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 3e276e958ef7..f28a76d1c0af 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -143,7 +143,7 @@ static void ocores_process(struct ocores_i2c *i2c)
143 } 143 }
144} 144}
145 145
146static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs) 146static irqreturn_t ocores_isr(int irq, void *dev_id)
147{ 147{
148 struct ocores_i2c *i2c = dev_id; 148 struct ocores_i2c *i2c = dev_id;
149 149
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 81d87d2c2a2d..dec04da0455c 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -400,7 +400,7 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
400} 400}
401 401
402static irqreturn_t 402static irqreturn_t
403omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs) 403omap_i2c_rev1_isr(int this_irq, void *dev_id)
404{ 404{
405 struct omap_i2c_dev *dev = dev_id; 405 struct omap_i2c_dev *dev = dev_id;
406 u16 iv, w; 406 u16 iv, w;
@@ -452,7 +452,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
452} 452}
453 453
454static irqreturn_t 454static irqreturn_t
455omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs) 455omap_i2c_isr(int this_irq, void *dev_id)
456{ 456{
457 struct omap_i2c_dev *dev = dev_id; 457 struct omap_i2c_dev *dev = dev_id;
458 u16 bits; 458 u16 bits;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index d9b4ddbad7e0..407840b6a260 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -99,7 +99,7 @@ static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
99 return ret; 99 return ret;
100} 100}
101 101
102static irqreturn_t pca_handler(int this_irq, void *dev_id, struct pt_regs *regs) { 102static irqreturn_t pca_handler(int this_irq, void *dev_id) {
103 wake_up_interruptible(&pca_wait); 103 wake_up_interruptible(&pca_wait);
104 return IRQ_HANDLED; 104 return IRQ_HANDLED;
105} 105}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index cd4ad98ad517..81050d3c9b21 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -850,7 +850,7 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
850 ICR = icr; 850 ICR = icr;
851} 851}
852 852
853static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs) 853static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
854{ 854{
855 struct pxa_i2c *i2c = dev_id; 855 struct pxa_i2c *i2c = dev_id;
856 u32 isr = ISR; 856 u32 isr = ISR;
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
index 0ebec3c1a54e..8764df06f51d 100644
--- a/drivers/i2c/busses/i2c-rpx.c
+++ b/drivers/i2c/busses/i2c-rpx.c
@@ -55,10 +55,10 @@ rpx_iic_init(struct i2c_algo_8xx_data *data)
55 data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); 55 data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
56} 56}
57 57
58static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data) 58static int rpx_install_isr(int irq, void (*func)(void *), void *data)
59{ 59{
60 /* install interrupt handler */ 60 /* install interrupt handler */
61 cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data); 61 cpm_install_handler(irq, func, data);
62 62
63 return 0; 63 return 0;
64} 64}
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9ebe429a0a0f..4ca6de209b8b 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -423,8 +423,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
423 * top level IRQ servicing routine 423 * top level IRQ servicing routine
424*/ 424*/
425 425
426static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id, 426static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
427 struct pt_regs *regs)
428{ 427{
429 struct s3c24xx_i2c *i2c = dev_id; 428 struct s3c24xx_i2c *i2c = dev_id;
430 unsigned long status; 429 unsigned long status;