summaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
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/usb/misc
parentda482792a6d1a3fbaaa25fae867b343fb4db3246 (diff)
downloadop-kernel-dev-7d12e780e003f93433d49ce78cfedf4b4c52adc5.zip
op-kernel-dev-7d12e780e003f93433d49ce78cfedf4b4c52adc5.tar.gz
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/misc')
-rw-r--r--drivers/usb/misc/adutux.c4
-rw-r--r--drivers/usb/misc/appledisplay.c2
-rw-r--r--drivers/usb/misc/auerswald.c30
-rw-r--r--drivers/usb/misc/ftdi-elan.c2
-rw-r--r--drivers/usb/misc/ldusb.c4
-rw-r--r--drivers/usb/misc/legousbtower.c8
-rw-r--r--drivers/usb/misc/phidgetkit.c2
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c2
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c4
-rw-r--r--drivers/usb/misc/usblcd.c2
-rw-r--r--drivers/usb/misc/usbtest.c8
-rw-r--r--drivers/usb/misc/uss720.c4
12 files changed, 36 insertions, 36 deletions
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index d396319..aecd633 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -177,7 +177,7 @@ static void adu_delete(struct adu_device *dev)
dbg(2, "%s : leave", __FUNCTION__);
}
-static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+static void adu_interrupt_in_callback(struct urb *urb)
{
struct adu_device *dev = urb->context;
@@ -221,7 +221,7 @@ exit:
dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
}
-static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+static void adu_interrupt_out_callback(struct urb *urb)
{
struct adu_device *dev = urb->context;
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index fc6cc14..6b23a1d 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -84,7 +84,7 @@ struct appledisplay {
static atomic_t count_displays = ATOMIC_INIT(0);
static struct workqueue_struct *wq;
-static void appledisplay_complete(struct urb *urb, struct pt_regs *regs)
+static void appledisplay_complete(struct urb *urb)
{
struct appledisplay *pdata = urb->context;
unsigned long flags;
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 4fd2110..0be9d62 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -267,7 +267,7 @@ typedef struct
/*-------------------------------------------------------------------*/
/* Forwards */
-static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs);
+static void auerswald_ctrlread_complete (struct urb * urb);
static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
static struct usb_driver auerswald_driver;
@@ -277,7 +277,7 @@ static struct usb_driver auerswald_driver;
/* -------------------------- */
/* completion function for chained urbs */
-static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
+static void auerchain_complete (struct urb * urb)
{
unsigned long flags;
int result;
@@ -296,7 +296,7 @@ static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
NOTE: this function may lead to more urbs submitted into the chain.
(no chain lock at calling complete()!)
acp->active != NULL is protecting us against recursion.*/
- urb->complete (urb, regs);
+ urb->complete (urb);
/* detach element from chain data structure */
spin_lock_irqsave (&acp->lock, flags);
@@ -331,7 +331,7 @@ static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
urb->status = result;
dbg("auerchain_complete: usb_submit_urb with error code %d", result);
/* and do error handling via *this* completion function (recursive) */
- auerchain_complete( urb, NULL);
+ auerchain_complete( urb);
}
} else {
/* simple return without submitting a new urb.
@@ -408,7 +408,7 @@ static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int ea
urb->status = result;
dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
/* and do error handling via completion function */
- auerchain_complete( urb, NULL);
+ auerchain_complete( urb);
}
}
@@ -448,7 +448,7 @@ static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
spin_unlock_irqrestore (&acp->lock, flags);
dbg ("unlink waiting urb");
urb->status = -ENOENT;
- urb->complete (urb, NULL);
+ urb->complete (urb);
return 0;
}
}
@@ -505,7 +505,7 @@ static void auerchain_unlink_all (pauerchain_t acp)
spin_unlock_irqrestore (&acp->lock, flags);
dbg ("unlink waiting urb");
urbp->status = -ENOENT;
- urbp->complete (urbp, NULL);
+ urbp->complete (urbp);
spin_lock_irqsave (&acp->lock, flags);
}
spin_unlock_irqrestore (&acp->lock, flags);
@@ -591,7 +591,7 @@ ac_fail:/* free the elements */
/* completion handler for synchronous chained URBs */
-static void auerchain_blocking_completion (struct urb *urb, struct pt_regs *regs)
+static void auerchain_blocking_completion (struct urb *urb)
{
pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
pchs->done = 1;
@@ -846,7 +846,7 @@ static int auerswald_status_retry (int status)
}
/* Completion of asynchronous write block */
-static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs)
+static void auerchar_ctrlwrite_complete (struct urb * urb)
{
pauerbuf_t bp = (pauerbuf_t) urb->context;
pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
@@ -859,7 +859,7 @@ static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs)
}
/* Completion handler for dummy retry packet */
-static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_ctrlread_wretcomplete (struct urb * urb)
{
pauerbuf_t bp = (pauerbuf_t) urb->context;
pauerswald_t cp;
@@ -893,12 +893,12 @@ static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *r
if (ret) {
dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
bp->urbp->status = ret;
- auerswald_ctrlread_complete (bp->urbp, NULL);
+ auerswald_ctrlread_complete (bp->urbp);
}
}
/* completion handler for receiving of control messages */
-static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_ctrlread_complete (struct urb * urb)
{
unsigned int serviceid;
pauerswald_t cp;
@@ -941,7 +941,7 @@ static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
if (ret) {
dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
bp->urbp->status = ret;
- auerswald_ctrlread_wretcomplete (bp->urbp, regs);
+ auerswald_ctrlread_wretcomplete (bp->urbp);
}
return;
}
@@ -970,7 +970,7 @@ static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
messages from the USB device.
*/
/* int completion handler. */
-static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_int_complete (struct urb * urb)
{
unsigned long flags;
unsigned int channelid;
@@ -1070,7 +1070,7 @@ static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs)
if (ret) {
dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
bp->urbp->status = ret;
- auerswald_ctrlread_complete( bp->urbp, NULL);
+ auerswald_ctrlread_complete( bp->urbp);
/* here applies the same problem as above: device locking! */
}
exit:
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index c6f2f48..0eb26a2 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -758,7 +758,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
return bytes_read;
}
-static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ftdi_elan_write_bulk_callback(struct urb *urb)
{
struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
if (urb->status && !(urb->status == -ENOENT || urb->status ==
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 10b6403..788a11e 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -212,7 +212,7 @@ static void ld_usb_delete(struct ld_usb *dev)
/**
* ld_usb_interrupt_in_callback
*/
-static void ld_usb_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+static void ld_usb_interrupt_in_callback(struct urb *urb)
{
struct ld_usb *dev = urb->context;
size_t *actual_buffer;
@@ -264,7 +264,7 @@ exit:
/**
* ld_usb_interrupt_out_callback
*/
-static void ld_usb_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+static void ld_usb_interrupt_out_callback(struct urb *urb)
{
struct ld_usb *dev = urb->context;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 77c36e6..2708949 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -248,8 +248,8 @@ static loff_t tower_llseek (struct file *file, loff_t off, int whence);
static void tower_abort_transfers (struct lego_usb_tower *dev);
static void tower_check_for_read_packet (struct lego_usb_tower *dev);
-static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs);
-static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs);
+static void tower_interrupt_in_callback (struct urb *urb);
+static void tower_interrupt_out_callback (struct urb *urb);
static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id);
static void tower_disconnect (struct usb_interface *interface);
@@ -755,7 +755,7 @@ exit:
/**
* tower_interrupt_in_callback
*/
-static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs)
+static void tower_interrupt_in_callback (struct urb *urb)
{
struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
int retval;
@@ -811,7 +811,7 @@ exit:
/**
* tower_interrupt_out_callback
*/
-static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs)
+static void tower_interrupt_out_callback (struct urb *urb)
{
struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 78e4199..abb4dcd 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -300,7 +300,7 @@ out:
static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
-static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
+static void interfacekit_irq(struct urb *urb)
{
struct interfacekit *kit = urb->context;
unsigned char *buffer = kit->data;
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 6b59b62..5c780ca 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -90,7 +90,7 @@ static int set_motor(struct motorcontrol *mc, int motor)
return retval < 0 ? retval : 0;
}
-static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs)
+static void motorcontrol_irq(struct urb *urb)
{
struct motorcontrol *mc = urb->context;
unsigned char *buffer = mc->data;
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index a287836..b99ca9c 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -209,7 +209,7 @@ sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
/* completion callback */
static void
-sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completeout(struct urb *urb)
{
struct sisusb_urb_context *context = urb->context;
struct sisusb_usb_data *sisusb;
@@ -288,7 +288,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
/* completion callback */
static void
-sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completein(struct urb *urb)
{
struct sisusb_usb_data *sisusb = urb->context;
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index dbaca9f..ada2ebc 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -165,7 +165,7 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
return 0;
}
-static void lcd_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void lcd_write_bulk_callback(struct urb *urb)
{
struct usb_lcd *dev;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 983e104..7c2cbdf 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -198,7 +198,7 @@ found:
* them with non-zero test data (or test for it) when appropriate.
*/
-static void simple_callback (struct urb *urb, struct pt_regs *regs)
+static void simple_callback (struct urb *urb)
{
complete ((struct completion *) urb->context);
}
@@ -730,7 +730,7 @@ struct subcase {
int expected;
};
-static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
+static void ctrl_complete (struct urb *urb)
{
struct ctrl_ctx *ctx = urb->context;
struct usb_ctrlrequest *reqp;
@@ -1035,7 +1035,7 @@ cleanup:
/*-------------------------------------------------------------------------*/
-static void unlink1_callback (struct urb *urb, struct pt_regs *regs)
+static void unlink1_callback (struct urb *urb)
{
int status = urb->status;
@@ -1343,7 +1343,7 @@ struct iso_context {
struct usbtest_dev *dev;
};
-static void iso_callback (struct urb *urb, struct pt_regs *regs)
+static void iso_callback (struct urb *urb)
{
struct iso_context *ctx = urb->context;
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 4081990..7e8a0ac 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -106,7 +106,7 @@ static void destroy_async(struct kref *kref)
/* --------------------------------------------------------------------- */
-static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+static void async_complete(struct urb *urb)
{
struct uss720_async_request *rq;
struct parport *pp;
@@ -127,7 +127,7 @@ static void async_complete(struct urb *urb, struct pt_regs *ptregs)
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
- parport_generic_irq(0, pp, NULL);
+ parport_generic_irq(0, pp);
}
complete(&rq->compl);
kref_put(&rq->ref_count, destroy_async);
OpenPOWER on IntegriCloud