aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-10-05 14:55:46 +0100
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-10-05 15:10:12 +0100
commit7d12e780e003f93433d49ce78cfedf4b4c52adc5 (patch)
tree6748550400445c11a306b132009f3001e3525df8 /drivers/pcmcia
parentda482792a6d1a3fbaaa25fae867b343fb4db3246 (diff)
downloadkernel_samsung_smdk4412-7d12e780e003f93433d49ce78cfedf4b4c52adc5.zip
kernel_samsung_smdk4412-7d12e780e003f93433d49ce78cfedf4b4c52adc5.tar.gz
kernel_samsung_smdk4412-7d12e780e003f93433d49ce78cfedf4b4c52adc5.tar.bz2
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/pcmcia')
-rw-r--r--drivers/pcmcia/at91_cf.c2
-rw-r--r--drivers/pcmcia/hd64465_ss.c2
-rw-r--r--drivers/pcmcia/i82092.c2
-rw-r--r--drivers/pcmcia/i82092aa.h2
-rw-r--r--drivers/pcmcia/i82365.c9
-rw-r--r--drivers/pcmcia/m32r_cfc.c7
-rw-r--r--drivers/pcmcia/m32r_pcc.c4
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c4
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/pcmcia_resource.c2
-rw-r--r--drivers/pcmcia/pd6729.c6
-rw-r--r--drivers/pcmcia/soc_common.c2
-rw-r--r--drivers/pcmcia/tcic.c10
-rw-r--r--drivers/pcmcia/vrc4171_card.c2
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c2
-rw-r--r--drivers/pcmcia/yenta_socket.c6
16 files changed, 31 insertions, 33 deletions
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 40569f4..991e084 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -64,7 +64,7 @@ static int at91_cf_ss_init(struct pcmcia_socket *s)
return 0;
}
-static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+static irqreturn_t at91_cf_irq(int irq, void *_cf)
{
struct at91_cf_socket *cf = (struct at91_cf_socket *) _cf;
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index ad02629..db3c26b 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -671,7 +671,7 @@ static int hs_irq_demux(int irq, void *dev)
* Interrupt handling routine.
*/
-static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hs_interrupt(int irq, void *dev)
{
hs_socket_t *sp = (hs_socket_t *)dev;
u_int events = 0;
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 2163aa7..82715f4 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -315,7 +315,7 @@ static int to_cycles(int ns)
/* Interrupt handler functionality */
-static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t i82092aa_interrupt(int irq, void *dev)
{
int i;
int loopcount = 0;
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index 9c14599..b0d4533 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -23,7 +23,7 @@
static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id);
static void i82092aa_pci_remove(struct pci_dev *dev);
static int card_present(int socketno);
-static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t i82092aa_interrupt(int irq, void *dev);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 1cc2682..ea74f98 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -80,7 +80,7 @@ module_param(pc_debug, int, 0644);
#define debug(lvl, fmt, arg...) do { } while (0)
#endif
-static irqreturn_t i365_count_irq(int, void *, struct pt_regs *);
+static irqreturn_t i365_count_irq(int, void *);
static inline int _check_irq(int irq, int flags)
{
if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
@@ -498,7 +498,7 @@ static u_int __init set_bridge_opts(u_short s, u_short ns)
static volatile u_int irq_hits;
static u_short irq_sock;
-static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t i365_count_irq(int irq, void *dev)
{
i365_get(irq_sock, I365_CSC);
irq_hits++;
@@ -848,8 +848,7 @@ static void __init isa_probe(void)
/*====================================================================*/
-static irqreturn_t pcic_interrupt(int irq, void *dev,
- struct pt_regs *regs)
+static irqreturn_t pcic_interrupt(int irq, void *dev)
{
int i, j, csc;
u_int events, active;
@@ -898,7 +897,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
static void pcic_interrupt_wrapper(u_long data)
{
- pcic_interrupt(0, NULL, NULL);
+ pcic_interrupt(0, NULL);
poll_timer.expires = jiffies + poll_interval;
add_timer(&poll_timer);
}
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 9e768ea..36fdaa5 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -254,7 +254,7 @@ static pcc_t pcc[] = {
#endif /* CONFIG_PLAT_USRV */
};
-static irqreturn_t pcc_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t pcc_interrupt(int, void *);
/*====================================================================*/
@@ -372,14 +372,13 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr
/*====================================================================*/
-static irqreturn_t pcc_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pcc_interrupt(int irq, void *dev)
{
int i;
u_int events = 0;
int handled = 0;
- debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p, regs=%p\n",
- irq, dev, regs);
+ debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev);
for (i = 0; i < pcc_sockets; i++) {
if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq)
continue;
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 61d50b5..0964fd7 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -267,7 +267,7 @@ static pcc_t pcc[] = {
{ "xnux2", 0 }, { "xnux2", 0 },
};
-static irqreturn_t pcc_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t pcc_interrupt(int, void *);
/*====================================================================*/
@@ -352,7 +352,7 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr
/*====================================================================*/
-static irqreturn_t pcc_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pcc_interrupt(int irq, void *dev)
{
int i, j, irc;
u_int events, active;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index d0f68ab..e070a28 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -266,7 +266,7 @@ static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
/* ------------------------------------------------------------------------- */
-static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t m8xx_interrupt(int irq, void *dev);
#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
@@ -646,7 +646,7 @@ static struct platform_device m8xx_device = {
static u32 pending_events[PCMCIA_SOCKETS_NO];
static DEFINE_SPINLOCK(pending_event_lock);
-static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t m8xx_interrupt(int irq, void *dev)
{
struct socket_info *s;
struct event_table *e;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 01be47e..c8e838c 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -102,7 +102,7 @@ static void omap_cf_timer(unsigned long _cf)
* claim the card's IRQ. It may also detect some card insertions, but
* not removals; it can't always eliminate timer irqs.
*/
-static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
+static irqreturn_t omap_cf_irq(int irq, void *_cf)
{
omap_cf_timer((unsigned long)_cf);
return IRQ_HANDLED;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index c832339..74cebd4 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -784,7 +784,7 @@ EXPORT_SYMBOL(pcmcia_request_io);
*/
#ifdef CONFIG_PCMCIA_PROBE
-static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t test_action(int cpl, void *dev_id)
{
return IRQ_NONE;
}
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 22c5e74..c83a0a6 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -182,7 +182,7 @@ static void indirect_write16(struct pd6729_socket *socket, unsigned short reg,
/* Interrupt handler functionality */
-static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pd6729_interrupt(int irq, void *dev)
{
struct pd6729_socket *socket = (struct pd6729_socket *)dev;
int i;
@@ -249,7 +249,7 @@ static void pd6729_interrupt_wrapper(unsigned long data)
{
struct pd6729_socket *socket = (struct pd6729_socket *) data;
- pd6729_interrupt(0, (void *)socket, NULL);
+ pd6729_interrupt(0, (void *)socket);
mod_timer(&socket->poll_timer, jiffies + HZ);
}
@@ -575,7 +575,7 @@ static struct pccard_operations pd6729_operations = {
.set_mem_map = pd6729_set_mem_map,
};
-static irqreturn_t pd6729_test(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pd6729_test(int irq, void *dev)
{
dprintk("-> hit on irq %d\n", irq);
return IRQ_HANDLED;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index ecaa132..3627e52 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -256,7 +256,7 @@ static void soc_common_pcmcia_poll_event(unsigned long dummy)
* handling code performs scheduling operations which cannot be
* executed from within an interrupt context.
*/
-static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev)
{
struct soc_pcmcia_socket *skt = dev;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 65a6067..2d2f415 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -116,7 +116,7 @@ module_param(cycle_time, int, 0444);
/*====================================================================*/
-static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t tcic_interrupt(int irq, void *dev);
static void tcic_timer(u_long data);
static struct pccard_operations tcic_operations;
@@ -218,7 +218,7 @@ static int to_cycles(int ns)
static volatile u_int irq_hits;
-static irqreturn_t __init tcic_irq_count(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t __init tcic_irq_count(int irq, void *dev)
{
irq_hits++;
return IRQ_HANDLED;
@@ -505,7 +505,7 @@ static int __init init_tcic(void)
}
/* jump start interrupt handler, if needed */
- tcic_interrupt(0, NULL, NULL);
+ tcic_interrupt(0, NULL);
platform_device_register(&tcic_device);
@@ -547,7 +547,7 @@ static void __exit exit_tcic(void)
/*====================================================================*/
-static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t tcic_interrupt(int irq, void *dev)
{
int i, quick = 0;
u_char latch, sstat;
@@ -606,7 +606,7 @@ static void tcic_timer(u_long data)
{
debug(2, "tcic_timer()\n");
tcic_timer_pending = 0;
- tcic_interrupt(0, NULL, NULL);
+ tcic_interrupt(0, NULL);
} /* tcic_timer */
/*====================================================================*/
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index e076a13..e90d8e8 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -514,7 +514,7 @@ static inline unsigned int get_events(int slot)
return events;
}
-static irqreturn_t pccard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pccard_interrupt(int irq, void *dev_id)
{
vrc4171_socket_t *socket;
unsigned int events;
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index d19a913..812f038 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -440,7 +440,7 @@ static uint16_t get_events(vrc4173_socket_t *socket)
return events;
}
-static void cardu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void cardu_interrupt(int irq, void *dev_id)
{
vrc4173_socket_t *socket = (vrc4173_socket_t *)dev_id;
uint16_t events;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 1344746..26229d9 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -442,7 +442,7 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *
-static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yenta_interrupt(int irq, void *dev_id)
{
unsigned int events;
struct yenta_socket *socket = (struct yenta_socket *) dev_id;
@@ -478,7 +478,7 @@ static void yenta_interrupt_wrapper(unsigned long data)
{
struct yenta_socket *socket = (struct yenta_socket *) data;
- yenta_interrupt(0, (void *)socket, NULL);
+ yenta_interrupt(0, (void *)socket);
socket->poll_timer.expires = jiffies + HZ;
add_timer(&socket->poll_timer);
}
@@ -896,7 +896,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
#ifdef CONFIG_YENTA_TI
/* interrupt handler, only used during probing */
-static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yenta_probe_handler(int irq, void *dev_id)
{
struct yenta_socket *socket = (struct yenta_socket *) dev_id;
u8 csc;