aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
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/usb/gadget
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/usb/gadget')
-rw-r--r--drivers/usb/gadget/at91_udc.c4
-rw-r--r--drivers/usb/gadget/goku_udc.c2
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c2
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c9
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c11
6 files changed, 13 insertions, 17 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 77beba485a84..72f3db99ff94 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1366,7 +1366,7 @@ static void handle_ep0(struct at91_udc *udc)
1366 } 1366 }
1367} 1367}
1368 1368
1369static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) 1369static irqreturn_t at91_udc_irq (int irq, void *_udc)
1370{ 1370{
1371 struct at91_udc *udc = _udc; 1371 struct at91_udc *udc = _udc;
1372 u32 rescans = 5; 1372 u32 rescans = 5;
@@ -1552,7 +1552,7 @@ static struct at91_udc controller = {
1552 /* ep6 and ep7 are also reserved (custom silicon might use them) */ 1552 /* ep6 and ep7 are also reserved (custom silicon might use them) */
1553}; 1553};
1554 1554
1555static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) 1555static irqreturn_t at91_vbus_irq(int irq, void *_udc)
1556{ 1556{
1557 struct at91_udc *udc = _udc; 1557 struct at91_udc *udc = _udc;
1558 unsigned value; 1558 unsigned value;
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 7cf2999e8616..a3076da3f4eb 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1628,7 +1628,7 @@ stall:
1628 handled = 1; \ 1628 handled = 1; \
1629 } 1629 }
1630 1630
1631static irqreturn_t goku_irq(int irq, void *_dev, struct pt_regs *r) 1631static irqreturn_t goku_irq(int irq, void *_dev)
1632{ 1632{
1633 struct goku_udc *dev = _dev; 1633 struct goku_udc *dev = _dev;
1634 struct goku_udc_regs __iomem *regs = dev->regs; 1634 struct goku_udc_regs __iomem *regs = dev->regs;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 36db72579377..179259664c18 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -922,7 +922,7 @@ static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
922/* 922/*
923 * lh7a40x usb client interrupt handler. 923 * lh7a40x usb client interrupt handler.
924 */ 924 */
925static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev, struct pt_regs *r) 925static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
926{ 926{
927 struct lh7a40x_udc *dev = _dev; 927 struct lh7a40x_udc *dev = _dev;
928 928
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3bda37f9a35f..d954daa8e9e0 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2753,7 +2753,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
2753 DEBUG (dev, "unhandled irqstat1 %08x\n", stat); 2753 DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
2754} 2754}
2755 2755
2756static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r) 2756static irqreturn_t net2280_irq (int irq, void *_dev)
2757{ 2757{
2758 struct net2280 *dev = _dev; 2758 struct net2280 *dev = _dev;
2759 2759
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 8c18df869833..48a09fd89d18 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1815,8 +1815,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
1815 UDC_IRQ_SRC_REG = UDC_DS_CHG; 1815 UDC_IRQ_SRC_REG = UDC_DS_CHG;
1816} 1816}
1817 1817
1818static irqreturn_t 1818static irqreturn_t omap_udc_irq(int irq, void *_udc)
1819omap_udc_irq(int irq, void *_udc, struct pt_regs *r)
1820{ 1819{
1821 struct omap_udc *udc = _udc; 1820 struct omap_udc *udc = _udc;
1822 u16 irq_src; 1821 u16 irq_src;
@@ -1888,8 +1887,7 @@ static void pio_out_timer(unsigned long _ep)
1888 spin_unlock_irqrestore(&ep->udc->lock, flags); 1887 spin_unlock_irqrestore(&ep->udc->lock, flags);
1889} 1888}
1890 1889
1891static irqreturn_t 1890static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
1892omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
1893{ 1891{
1894 u16 epn_stat, irq_src; 1892 u16 epn_stat, irq_src;
1895 irqreturn_t status = IRQ_NONE; 1893 irqreturn_t status = IRQ_NONE;
@@ -1968,8 +1966,7 @@ omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
1968} 1966}
1969 1967
1970#ifdef USE_ISO 1968#ifdef USE_ISO
1971static irqreturn_t 1969static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
1972omap_udc_iso_irq(int irq, void *_dev, struct pt_regs *r)
1973{ 1970{
1974 struct omap_udc *udc = _dev; 1971 struct omap_udc *udc = _dev;
1975 struct omap_ep *ep; 1972 struct omap_ep *ep;
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index f1adcf8b2023..f42c00ef0bca 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -110,7 +110,7 @@ static int use_dma = 1;
110module_param(use_dma, bool, 0); 110module_param(use_dma, bool, 0);
111MODULE_PARM_DESC (use_dma, "true to use dma"); 111MODULE_PARM_DESC (use_dma, "true to use dma");
112 112
113static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r); 113static void dma_nodesc_handler (int dmach, void *_ep);
114static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req); 114static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
115 115
116#ifdef USE_OUT_DMA 116#ifdef USE_OUT_DMA
@@ -828,7 +828,7 @@ static void cancel_dma(struct pxa2xx_ep *ep)
828} 828}
829 829
830/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */ 830/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
831static void dma_nodesc_handler(int dmach, void *_ep, struct pt_regs *r) 831static void dma_nodesc_handler(int dmach, void *_ep)
832{ 832{
833 struct pxa2xx_ep *ep = _ep; 833 struct pxa2xx_ep *ep = _ep;
834 struct pxa2xx_request *req; 834 struct pxa2xx_request *req;
@@ -1724,7 +1724,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
1724 */ 1724 */
1725 1725
1726static irqreturn_t 1726static irqreturn_t
1727lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r) 1727lubbock_vbus_irq(int irq, void *_dev)
1728{ 1728{
1729 struct pxa2xx_udc *dev = _dev; 1729 struct pxa2xx_udc *dev = _dev;
1730 int vbus; 1730 int vbus;
@@ -1754,8 +1754,7 @@ lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
1754 1754
1755#endif 1755#endif
1756 1756
1757static irqreturn_t 1757static irqreturn_t udc_vbus_irq(int irq, void *_dev)
1758udc_vbus_irq(int irq, void *_dev, struct pt_regs *r)
1759{ 1758{
1760 struct pxa2xx_udc *dev = _dev; 1759 struct pxa2xx_udc *dev = _dev;
1761 int vbus = pxa_gpio_get(dev->mach->gpio_vbus); 1760 int vbus = pxa_gpio_get(dev->mach->gpio_vbus);
@@ -2084,7 +2083,7 @@ static void handle_ep(struct pxa2xx_ep *ep)
2084 * could cause usb protocol errors. 2083 * could cause usb protocol errors.
2085 */ 2084 */
2086static irqreturn_t 2085static irqreturn_t
2087pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r) 2086pxa2xx_udc_irq(int irq, void *_dev)
2088{ 2087{
2089 struct pxa2xx_udc *dev = _dev; 2088 struct pxa2xx_udc *dev = _dev;
2090 int handled; 2089 int handled;