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 <[email protected]>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
This commit is contained in:
David Howells 2006-10-05 14:55:46 +01:00 • committed by David Howells
commit 7d12e780e0
1079 changed files with 2621 additions and 2976 deletions

View file

@ -230,7 +230,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
/********************************************************************************/
/* interrupt handler */
static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t interrupt_hw(int irq, void *dev_id)
{
struct saa7146_dev *dev = dev_id;
u32 isr = 0;

View file

@ -122,7 +122,7 @@ static void flexcop_pci_irq_check_work(void *data)
/* When PID filtering is turned on, we use the timer IRQ, because small amounts
* of data need to be passed to the user space instantly as well. When PID
* filtering is turned off, we use the page-change-IRQ */
static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
{
struct flexcop_pci *fc_pci = dev_id;
struct flexcop_device *fc = fc_pci->fc_dev;

View file

@ -328,7 +328,7 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in
fc_usb->tmp_buffer_length = l;
}
static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
static void flexcop_usb_urb_complete(struct urb *urb)
{
struct flexcop_usb *fc_usb = urb->context;
int i;

View file

@ -266,7 +266,7 @@ EXPORT_SYMBOL(bt878_stop);
/* Interrupt service routine */
/*****************************/
static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t bt878_irq(int irq, void *dev_id)
{
u32 stat, astat, mask;
int count;

View file

@ -238,7 +238,7 @@ static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep)
cinergyt2->sleeping = sleep;
}
static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs);
static void cinergyt2_stream_irq (struct urb *urb);
static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb)
{
@ -258,7 +258,7 @@ static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb
return err;
}
static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs)
static void cinergyt2_stream_irq (struct urb *urb)
{
struct cinergyt2 *cinergyt2 = urb->context;

View file

@ -11,7 +11,7 @@
#include "dvb-usb-common.h"
/* URB stuff for streaming */
static void usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
static void usb_urb_complete(struct urb *urb)
{
struct usb_data_stream *stream = urb->context;
int ptype = usb_pipetype(urb->pipe);

View file

@ -306,7 +306,7 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
}
static irqreturn_t pluto_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t pluto_irq(int irq, void *dev_id)
{
struct pluto *pluto = dev_id;
u32 tscr;

View file

@ -732,7 +732,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
}
}
static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
static void ttusb_iso_irq(struct urb *urb)
{
struct ttusb *ttusb = urb->context;

View file

@ -203,7 +203,7 @@ static u16 rc_keys[] = {
static void ttusb_dec_set_model(struct ttusb_dec *dec,
enum ttusb_dec_model model);
static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
static void ttusb_dec_handle_irq( struct urb *urb)
{
struct ttusb_dec * dec = urb->context;
char *buffer = dec->irq_buffer;
@ -755,7 +755,7 @@ static void ttusb_dec_process_urb_frame_list(unsigned long data)
}
}
static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
static void ttusb_dec_process_urb(struct urb *urb)
{
struct ttusb_dec *dec = urb->context;

View file

@ -549,7 +549,7 @@ static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
/*
* Interrupt handler
*/
static void ar_interrupt(int irq, void *dev, struct pt_regs *regs)
static void ar_interrupt(int irq, void *dev)
{
struct ar_device *ar = dev;
unsigned int line_count;

View file

@ -3753,7 +3753,7 @@ bttv_irq_switch_vbi(struct bttv *btv)
spin_unlock(&btv->s_lock);
}
static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
static irqreturn_t bttv_irq(int irq, void *dev_id)
{
u32 stat,astat;
u32 dstat;

View file

@ -49,7 +49,7 @@ static int frame_sizes[] = {
#define FRAME_SIZE_PER_DESC frame_sizes[cam->cur_alt]
static void process_frame(struct camera_data *cam);
static void cpia2_usb_complete(struct urb *urb, struct pt_regs *);
static void cpia2_usb_complete(struct urb *urb);
static int cpia2_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void cpia2_usb_disconnect(struct usb_interface *intf);
@ -199,7 +199,7 @@ static void add_COM(struct camera_data *cam)
*
* callback when incoming packet is received
*****************************************************************************/
static void cpia2_usb_complete(struct urb *urb, struct pt_regs *regs)
static void cpia2_usb_complete(struct urb *urb)
{
int i;
unsigned char *cdata;

View file

@ -109,7 +109,7 @@ static struct cpia_camera_ops cpia_usb_ops = {
static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_usb;
static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
static void cpia_usb_complete(struct urb *urb)
{
int i;
char *cdata;

View file

@ -262,7 +262,7 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
/*
* BOARD Specific: Handles IRQ calls
*/
static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t cx8801_irq(int irq, void *dev_id)
{
snd_cx88_card_t *chip = dev_id;
struct cx88_core *core = chip->core;

View file

@ -376,7 +376,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
#define MAX_IRQ_LOOP 10
static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t cx8802_irq(int irq, void *dev_id)
{
struct cx8802_dev *dev = dev_id;
struct cx88_core *core = dev->core;

View file

@ -1744,7 +1744,7 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
}
}
static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t cx8800_irq(int irq, void *dev_id)
{
struct cx8800_dev *dev = dev_id;
struct cx88_core *core = dev->core;

View file

@ -166,7 +166,7 @@ static int dabusb_free_buffers (pdabusb_t s)
return 0;
}
/*-------------------------------------------------------------------*/
static void dabusb_iso_complete (struct urb *purb, struct pt_regs *regs)
static void dabusb_iso_complete (struct urb *purb)
{
pbuff_t b = purb->context;
pdabusb_t s = b->s;

View file

@ -382,7 +382,7 @@ int em28xx_resolution_set(struct em28xx *dev)
/******************* isoc transfer handling ****************************/
#ifdef ENABLE_DEBUG_ISOC_FRAMES
static void em28xx_isoc_dump(struct urb *urb, struct pt_regs *regs)
static void em28xx_isoc_dump(struct urb *urb)
{
int len = 0;
int ntrans = 0;
@ -534,7 +534,7 @@ static inline void em28xx_isoc_video_copy(struct em28xx *dev,
* em28xx_isoIrq()
* handles the incoming isoc urbs and fills the frames from our inqueue
*/
static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
static void em28xx_isocIrq(struct urb *urb)
{
struct em28xx *dev = urb->context;
int i, status;
@ -545,7 +545,7 @@ static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
return;
#ifdef ENABLE_DEBUG_ISOC_FRAMES
if (isoc_debug>1)
em28xx_isoc_dump(urb, regs);
em28xx_isoc_dump(urb);
#endif
if (urb->status == -ENOENT)

View file

@ -398,7 +398,7 @@ int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value)
/*****************************************************************************/
static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
static void et61x251_urb_complete(struct urb *urb)
{
struct et61x251_device* cam = urb->context;
struct et61x251_frame_t** f;

View file

@ -786,7 +786,7 @@ static void mchip_cont_compression_start(void)
/* Interrupt handling */
/****************************************************************************/
static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t meye_irq(int irq, void *dev_id)
{
u32 v;
int reqnr;

View file

@ -3503,7 +3503,7 @@ check_middle:
}
static void
ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs)
ov51x_isoc_irq(struct urb *urb)
{
int i;
struct usb_ov511 *ov;

View file

@ -91,7 +91,7 @@ static void planb_close(struct video_device *);
static int planb_ioctl(struct video_device *, unsigned int, void *);
static int planb_init_done(struct video_device *);
static int planb_mmap(struct video_device *, const char *, unsigned long);
static void planb_irq(int, void *, struct pt_regs *);
static void planb_irq(int, void *);
static void release_planb(void);
int init_planbs(struct video_init *);
@ -1316,7 +1316,7 @@ cmd_tab_data_end:
return c1;
}
static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
static void planb_irq(int irq, void *dev_id)
{
unsigned int stat, astat;
struct planb *pb = (struct planb *)dev_id;

View file

@ -2552,7 +2552,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
}
static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
static void pvr2_ctl_write_complete(struct urb *urb)
{
struct pvr2_hdw *hdw = urb->context;
hdw->ctl_write_pend_flag = 0;
@ -2561,7 +2561,7 @@ static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
}
static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs)
static void pvr2_ctl_read_complete(struct urb *urb)
{
struct pvr2_hdw *hdw = urb->context;
hdw->ctl_read_pend_flag = 0;

View file

@ -429,7 +429,7 @@ static void pvr2_stream_done(struct pvr2_stream *sp)
} while (0); mutex_unlock(&sp->mutex);
}
static void buffer_complete(struct urb *urb, struct pt_regs *regs)
static void buffer_complete(struct urb *urb)
{
struct pvr2_buffer *bp = urb->context;
struct pvr2_stream *sp;

View file

@ -682,7 +682,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
static void pwc_isoc_handler(struct urb *urb)
{
struct pwc_device *pdev;
int i, fst, flen;

View file

@ -212,7 +212,7 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
*
*/
static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
{
struct saa7134_dmasound *dmasound = dev_id;
struct saa7134_dev *dev = dmasound->priv_data;

View file

@ -495,7 +495,7 @@ static void print_irqstatus(struct saa7134_dev *dev, int loop,
printk("\n");
}
static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t saa7134_irq(int irq, void *dev_id)
{
struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
unsigned long report,status;

View file

@ -814,7 +814,7 @@ struct file_operations saa7134_mixer_fops = {
/* ------------------------------------------------------------------ */
static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t saa7134_oss_irq(int irq, void *dev_id)
{
struct saa7134_dmasound *dmasound = dev_id;
struct saa7134_dev *dev = dmasound->priv_data;

View file

@ -282,7 +282,7 @@ static void se401_auto_resetlevel(struct usb_se401 *se401)
}
/* irq handler for snapshot button */
static void se401_button_irq(struct urb *urb, struct pt_regs *regs)
static void se401_button_irq(struct urb *urb)
{
struct usb_se401 *se401 = urb->context;
int status;
@ -318,7 +318,7 @@ exit:
__FUNCTION__, status);
}
static void se401_video_irq(struct urb *urb, struct pt_regs *regs)
static void se401_video_irq(struct urb *urb)
{
struct usb_se401 *se401 = urb->context;
int length = urb->actual_length;

View file

@ -518,7 +518,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
}
static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
static void sn9c102_urb_complete(struct urb *urb)
{
struct sn9c102_device* cam = urb->context;
struct sn9c102_frame_t** f;

View file

@ -406,7 +406,7 @@ static void send_osd_data(struct saa7146 *saa)
}
}
static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t saa7146_irq(int irq, void *dev_id)
{
struct saa7146 *saa = dev_id;
u32 stat, astat;

View file

@ -582,7 +582,7 @@ static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
return 0;
}
static void stv680_video_irq (struct urb *urb, struct pt_regs *regs)
static void stv680_video_irq (struct urb *urb)
{
struct usb_stv *stv680 = urb->context;
int length = urb->actual_length;

View file

@ -387,7 +387,7 @@ static void resubmit_urb(struct uvd *uvd, struct urb *urb)
}
static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs)
static void konicawc_isoc_irq(struct urb *urb)
{
struct uvd *uvd = urb->context;
struct konicawc *cam = (struct konicawc *)uvd->user_data;

View file

@ -125,7 +125,7 @@ static void qcm_report_buttonstat(struct qcm *cam)
}
}
static void qcm_int_irq(struct urb *urb, struct pt_regs *regs)
static void qcm_int_irq(struct urb *urb)
{
int ret;
struct uvd *uvd = urb->context;
@ -606,7 +606,7 @@ static void resubmit_urb(struct uvd *uvd, struct urb *urb)
err("usb_submit_urb error (%d)", ret);
}
static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)
static void qcm_isoc_irq(struct urb *urb)
{
int len;
struct uvd *uvd = urb->context;

View file

@ -1680,7 +1680,7 @@ static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb)
return totlen;
}
static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs)
static void usbvideo_IsocIrq(struct urb *urb)
{
int i, ret, len;
struct uvd *uvd = urb->context;

View file

@ -2325,7 +2325,7 @@ static void vino_capture_tasklet(unsigned long channel) {
}
}
static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t vino_interrupt(int irq, void *dev_id)
{
u32 ctrl, intr;
unsigned int fc_a, fc_b;

View file

@ -417,7 +417,7 @@ static int w9968cf_write_fsb(struct w9968cf_device*, u16* data);
static int w9968cf_write_sb(struct w9968cf_device*, u16 value);
static int w9968cf_read_sb(struct w9968cf_device*);
static int w9968cf_upload_quantizationtables(struct w9968cf_device*);
static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs);
static void w9968cf_urb_complete(struct urb *urb);
/* Low-level I2C (SMBus) I/O */
static int w9968cf_smbus_start(struct w9968cf_device*);
@ -781,7 +781,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam)
If there are no requested frames in the FIFO list, packets are collected into
a temporary buffer.
--------------------------------------------------------------------------*/
static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
static void w9968cf_urb_complete(struct urb *urb)
{
struct w9968cf_device* cam = (struct w9968cf_device*)urb->context;
struct w9968cf_frame_t** f;

View file

@ -303,7 +303,7 @@ int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value)
/*****************************************************************************/
static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
static void zc0301_urb_complete(struct urb *urb)
{
struct zc0301_device* cam = urb->context;
struct zc0301_frame_t** f;

View file

@ -1408,8 +1408,7 @@ error_handler (struct zoran *zr,
irqreturn_t
zoran_irq (int irq,
void *dev_id,
struct pt_regs *regs)
void *dev_id)
{
u32 stat, astat;
int count;

View file

@ -64,9 +64,7 @@ extern int wait_grab_pending(struct zoran *zr);
/* interrupts */
extern void print_interrupts(struct zoran *zr);
extern void clear_interrupt_counters(struct zoran *zr);
extern irqreturn_t zoran_irq(int irq,
void *dev_id,
struct pt_regs *regs);
extern irqreturn_t zoran_irq(int irq, void *dev_id);
/* JPEG codec access */
extern void jpeg_start(struct zoran *zr);

View file

@ -335,13 +335,13 @@ DEBUG(printk(CARD_DEBUG "turning off\n",CARD));
}
static
void zoran_irq(int irq, void *dev_id, struct pt_regs * regs)
void zoran_irq(int irq, void *dev_id)
{
u32 stat,estat;
int count = 0;
struct zoran *ztv = dev_id;
UNUSED(irq); UNUSED(regs);
UNUSED(irq);
for (;;) {
/* get/clear interrupt status bits */
stat=zrread(ZORAN_ISR);