aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pcmcia
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/net/pcmcia
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/net/pcmcia')
-rw-r--r--drivers/net/pcmcia/3c574_cs.c6
-rw-r--r--drivers/net/pcmcia/3c589_cs.c6
-rw-r--r--drivers/net/pcmcia/axnet_cs.c12
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c4
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c4
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c8
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c6
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c4
8 files changed, 25 insertions, 25 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 2418cdb9d317..046009928526 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -238,7 +238,7 @@ static void tc574_reset(struct net_device *dev);
238static void media_check(unsigned long arg); 238static void media_check(unsigned long arg);
239static int el3_open(struct net_device *dev); 239static int el3_open(struct net_device *dev);
240static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); 240static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
241static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); 241static irqreturn_t el3_interrupt(int irq, void *dev_id);
242static void update_stats(struct net_device *dev); 242static void update_stats(struct net_device *dev);
243static struct net_device_stats *el3_get_stats(struct net_device *dev); 243static struct net_device_stats *el3_get_stats(struct net_device *dev);
244static int el3_rx(struct net_device *dev, int worklimit); 244static int el3_rx(struct net_device *dev, int worklimit);
@@ -817,7 +817,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
817} 817}
818 818
819/* The EL3 interrupt handler. */ 819/* The EL3 interrupt handler. */
820static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) 820static irqreturn_t el3_interrupt(int irq, void *dev_id)
821{ 821{
822 struct net_device *dev = (struct net_device *) dev_id; 822 struct net_device *dev = (struct net_device *) dev_id;
823 struct el3_private *lp = netdev_priv(dev); 823 struct el3_private *lp = netdev_priv(dev);
@@ -927,7 +927,7 @@ static void media_check(unsigned long arg)
927 if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) { 927 if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
928 if (!lp->fast_poll) 928 if (!lp->fast_poll)
929 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); 929 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
930 el3_interrupt(dev->irq, lp, NULL); 930 el3_interrupt(dev->irq, lp);
931 lp->fast_poll = HZ; 931 lp->fast_poll = HZ;
932 } 932 }
933 if (lp->fast_poll) { 933 if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index a0e2b01c027c..231fa2c9ec6c 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -151,7 +151,7 @@ static void media_check(unsigned long arg);
151static int el3_config(struct net_device *dev, struct ifmap *map); 151static int el3_config(struct net_device *dev, struct ifmap *map);
152static int el3_open(struct net_device *dev); 152static int el3_open(struct net_device *dev);
153static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); 153static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
154static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); 154static irqreturn_t el3_interrupt(int irq, void *dev_id);
155static void update_stats(struct net_device *dev); 155static void update_stats(struct net_device *dev);
156static struct net_device_stats *el3_get_stats(struct net_device *dev); 156static struct net_device_stats *el3_get_stats(struct net_device *dev);
157static int el3_rx(struct net_device *dev); 157static int el3_rx(struct net_device *dev);
@@ -645,7 +645,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
645} 645}
646 646
647/* The EL3 interrupt handler. */ 647/* The EL3 interrupt handler. */
648static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) 648static irqreturn_t el3_interrupt(int irq, void *dev_id)
649{ 649{
650 struct net_device *dev = (struct net_device *) dev_id; 650 struct net_device *dev = (struct net_device *) dev_id;
651 struct el3_private *lp = netdev_priv(dev); 651 struct el3_private *lp = netdev_priv(dev);
@@ -748,7 +748,7 @@ static void media_check(unsigned long arg)
748 (inb(ioaddr + EL3_TIMER) == 0xff)) { 748 (inb(ioaddr + EL3_TIMER) == 0xff)) {
749 if (!lp->fast_poll) 749 if (!lp->fast_poll)
750 printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name); 750 printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
751 el3_interrupt(dev->irq, lp, NULL); 751 el3_interrupt(dev->irq, lp);
752 lp->fast_poll = HZ; 752 lp->fast_poll = HZ;
753 } 753 }
754 if (lp->fast_poll) { 754 if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index a8891a9000ac..e5f366910914 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -92,7 +92,7 @@ static int axnet_open(struct net_device *dev);
92static int axnet_close(struct net_device *dev); 92static int axnet_close(struct net_device *dev);
93static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 93static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
94static const struct ethtool_ops netdev_ethtool_ops; 94static const struct ethtool_ops netdev_ethtool_ops;
95static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); 95static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
96static void ei_watchdog(u_long arg); 96static void ei_watchdog(u_long arg);
97static void axnet_reset_8390(struct net_device *dev); 97static void axnet_reset_8390(struct net_device *dev);
98 98
@@ -112,7 +112,7 @@ static void axdev_setup(struct net_device *dev);
112static void AX88190_init(struct net_device *dev, int startp); 112static void AX88190_init(struct net_device *dev, int startp);
113static int ax_open(struct net_device *dev); 113static int ax_open(struct net_device *dev);
114static int ax_close(struct net_device *dev); 114static int ax_close(struct net_device *dev);
115static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs); 115static irqreturn_t ax_interrupt(int irq, void *dev_id);
116 116
117/*====================================================================*/ 117/*====================================================================*/
118 118
@@ -599,11 +599,11 @@ static void axnet_reset_8390(struct net_device *dev)
599 599
600/*====================================================================*/ 600/*====================================================================*/
601 601
602static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) 602static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
603{ 603{
604 struct net_device *dev = dev_id; 604 struct net_device *dev = dev_id;
605 PRIV(dev)->stale = 0; 605 PRIV(dev)->stale = 0;
606 return ax_interrupt(irq, dev_id, regs); 606 return ax_interrupt(irq, dev_id);
607} 607}
608 608
609static void ei_watchdog(u_long arg) 609static void ei_watchdog(u_long arg)
@@ -621,7 +621,7 @@ static void ei_watchdog(u_long arg)
621 if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { 621 if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
622 if (!info->fast_poll) 622 if (!info->fast_poll)
623 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); 623 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
624 ei_irq_wrapper(dev->irq, dev, NULL); 624 ei_irq_wrapper(dev->irq, dev);
625 info->fast_poll = HZ; 625 info->fast_poll = HZ;
626 } 626 }
627 if (info->fast_poll) { 627 if (info->fast_poll) {
@@ -1193,7 +1193,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
1193 * needed. 1193 * needed.
1194 */ 1194 */
1195 1195
1196static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs * regs) 1196static irqreturn_t ax_interrupt(int irq, void *dev_id)
1197{ 1197{
1198 struct net_device *dev = dev_id; 1198 struct net_device *dev = dev_id;
1199 long e8390_base; 1199 long e8390_base;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index d682f30dea6e..65f6fdf43725 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -97,7 +97,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map);
97static int fjn_open(struct net_device *dev); 97static int fjn_open(struct net_device *dev);
98static int fjn_close(struct net_device *dev); 98static int fjn_close(struct net_device *dev);
99static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev); 99static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
100static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); 100static irqreturn_t fjn_interrupt(int irq, void *dev_id);
101static void fjn_rx(struct net_device *dev); 101static void fjn_rx(struct net_device *dev);
102static void fjn_reset(struct net_device *dev); 102static void fjn_reset(struct net_device *dev);
103static struct net_device_stats *fjn_get_stats(struct net_device *dev); 103static struct net_device_stats *fjn_get_stats(struct net_device *dev);
@@ -733,7 +733,7 @@ module_exit(exit_fmvj18x_cs);
733 733
734/*====================================================================*/ 734/*====================================================================*/
735 735
736static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) 736static irqreturn_t fjn_interrupt(int irq, void *dev_id)
737{ 737{
738 struct net_device *dev = dev_id; 738 struct net_device *dev = dev_id;
739 local_info_t *lp = netdev_priv(dev); 739 local_info_t *lp = netdev_priv(dev);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 7d5687e94607..e77110e4c288 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -426,7 +426,7 @@ static int mace_open(struct net_device *dev);
426static int mace_close(struct net_device *dev); 426static int mace_close(struct net_device *dev);
427static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev); 427static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev);
428static void mace_tx_timeout(struct net_device *dev); 428static void mace_tx_timeout(struct net_device *dev);
429static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); 429static irqreturn_t mace_interrupt(int irq, void *dev_id);
430static struct net_device_stats *mace_get_stats(struct net_device *dev); 430static struct net_device_stats *mace_get_stats(struct net_device *dev);
431static int mace_rx(struct net_device *dev, unsigned char RxCnt); 431static int mace_rx(struct net_device *dev, unsigned char RxCnt);
432static void restore_multicast_list(struct net_device *dev); 432static void restore_multicast_list(struct net_device *dev);
@@ -1002,7 +1002,7 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
1002mace_interrupt 1002mace_interrupt
1003 The interrupt handler. 1003 The interrupt handler.
1004---------------------------------------------------------------------------- */ 1004---------------------------------------------------------------------------- */
1005static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1005static irqreturn_t mace_interrupt(int irq, void *dev_id)
1006{ 1006{
1007 struct net_device *dev = (struct net_device *) dev_id; 1007 struct net_device *dev = (struct net_device *) dev_id;
1008 mace_private *lp = netdev_priv(dev); 1008 mace_private *lp = netdev_priv(dev);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index a09c22840f63..0c00d182e7fd 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -109,7 +109,7 @@ static int pcnet_open(struct net_device *dev);
109static int pcnet_close(struct net_device *dev); 109static int pcnet_close(struct net_device *dev);
110static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 110static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
111static const struct ethtool_ops netdev_ethtool_ops; 111static const struct ethtool_ops netdev_ethtool_ops;
112static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); 112static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
113static void ei_watchdog(u_long arg); 113static void ei_watchdog(u_long arg);
114static void pcnet_reset_8390(struct net_device *dev); 114static void pcnet_reset_8390(struct net_device *dev);
115static int set_config(struct net_device *dev, struct ifmap *map); 115static int set_config(struct net_device *dev, struct ifmap *map);
@@ -1071,11 +1071,11 @@ static int set_config(struct net_device *dev, struct ifmap *map)
1071 1071
1072/*====================================================================*/ 1072/*====================================================================*/
1073 1073
1074static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) 1074static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
1075{ 1075{
1076 struct net_device *dev = dev_id; 1076 struct net_device *dev = dev_id;
1077 pcnet_dev_t *info; 1077 pcnet_dev_t *info;
1078 irqreturn_t ret = ei_interrupt(irq, dev_id, regs); 1078 irqreturn_t ret = ei_interrupt(irq, dev_id);
1079 1079
1080 if (ret == IRQ_HANDLED) { 1080 if (ret == IRQ_HANDLED) {
1081 info = PRIV(dev); 1081 info = PRIV(dev);
@@ -1100,7 +1100,7 @@ static void ei_watchdog(u_long arg)
1100 if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { 1100 if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
1101 if (!info->fast_poll) 1101 if (!info->fast_poll)
1102 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); 1102 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
1103 ei_irq_wrapper(dev->irq, dev, NULL); 1103 ei_irq_wrapper(dev->irq, dev);
1104 info->fast_poll = HZ; 1104 info->fast_poll = HZ;
1105 } 1105 }
1106 if (info->fast_poll) { 1106 if (info->fast_poll) {
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index a2f3a0e2a005..20fcc3576202 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -287,7 +287,7 @@ static int smc_close(struct net_device *dev);
287static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 287static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
288static void smc_tx_timeout(struct net_device *dev); 288static void smc_tx_timeout(struct net_device *dev);
289static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); 289static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
290static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); 290static irqreturn_t smc_interrupt(int irq, void *dev_id);
291static void smc_rx(struct net_device *dev); 291static void smc_rx(struct net_device *dev);
292static struct net_device_stats *smc_get_stats(struct net_device *dev); 292static struct net_device_stats *smc_get_stats(struct net_device *dev);
293static void set_rx_mode(struct net_device *dev); 293static void set_rx_mode(struct net_device *dev);
@@ -1545,7 +1545,7 @@ static void smc_eph_irq(struct net_device *dev)
1545 1545
1546/*====================================================================*/ 1546/*====================================================================*/
1547 1547
1548static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1548static irqreturn_t smc_interrupt(int irq, void *dev_id)
1549{ 1549{
1550 struct net_device *dev = dev_id; 1550 struct net_device *dev = dev_id;
1551 struct smc_private *smc = netdev_priv(dev); 1551 struct smc_private *smc = netdev_priv(dev);
@@ -1966,7 +1966,7 @@ static void media_check(u_long arg)
1966 if (smc->watchdog++ && ((i>>8) & i)) { 1966 if (smc->watchdog++ && ((i>>8) & i)) {
1967 if (!smc->fast_poll) 1967 if (!smc->fast_poll)
1968 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); 1968 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
1969 smc_interrupt(dev->irq, smc, NULL); 1969 smc_interrupt(dev->irq, smc);
1970 smc->fast_poll = HZ; 1970 smc->fast_poll = HZ;
1971 } 1971 }
1972 if (smc->fast_poll) { 1972 if (smc->fast_poll) {
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 62664c01eb45..f3914f58d67f 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -308,7 +308,7 @@ static void xirc2ps_detach(struct pcmcia_device *p_dev);
308 * less on other parts of the kernel. 308 * less on other parts of the kernel.
309 */ 309 */
310 310
311static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); 311static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
312 312
313/**************** 313/****************
314 * A linked list of "instances" of the device. Each actual 314 * A linked list of "instances" of the device. Each actual
@@ -1121,7 +1121,7 @@ static int xirc2ps_resume(struct pcmcia_device *link)
1121 * This is the Interrupt service route. 1121 * This is the Interrupt service route.
1122 */ 1122 */
1123static irqreturn_t 1123static irqreturn_t
1124xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1124xirc2ps_interrupt(int irq, void *dev_id)
1125{ 1125{
1126 struct net_device *dev = (struct net_device *)dev_id; 1126 struct net_device *dev = (struct net_device *)dev_id;
1127 local_info_t *lp = netdev_priv(dev); 1127 local_info_t *lp = netdev_priv(dev);