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)
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 5c5e682..4861799 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -549,7 +549,7 @@
 /*
  * 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;
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 50dde828..6e1ddad 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3753,7 +3753,7 @@
 	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;
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index f4da029..28dc6a1a1 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -49,7 +49,7 @@
 #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 @@
  *
  *  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;
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 2ee34a3..9da4726 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -109,7 +109,7 @@
 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;
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index f034066..e4355fd 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -262,7 +262,7 @@
 /*
  * 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;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index d6d9807..6b23a4e 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -376,7 +376,7 @@
 
 #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;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index cb0c0ee..90e298d 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1744,7 +1744,7 @@
 	}
 }
 
-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;
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index b9ba95f..b1012e9 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -166,7 +166,7 @@
 	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;
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 4350cc7..255a47d 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -382,7 +382,7 @@
 /******************* 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 @@
  * 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 @@
 		return;
 #ifdef ENABLE_DEBUG_ISOC_FRAMES
 	if (isoc_debug>1)
-		em28xx_isoc_dump(urb, regs);
+		em28xx_isoc_dump(urb);
 #endif
 
 	if (urb->status == -ENOENT)
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 8992b6e..bc544cc 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -398,7 +398,7 @@
 
 /*****************************************************************************/
 
-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;
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index e278753..b083338 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -786,7 +786,7 @@
 /* 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;
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 5d8cd28..ce4886f 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -3503,7 +3503,7 @@
 }
 
 static void
-ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs)
+ov51x_isoc_irq(struct urb *urb)
 {
 	int i;
 	struct usb_ov511 *ov;
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 3484e36..368d6e2 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -91,7 +91,7 @@
 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 @@
 	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;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 3d8cd0d..f920e0c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2552,7 +2552,7 @@
 }
 
 
-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_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;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 1e39376..70aa63e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -429,7 +429,7 @@
 	} 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;
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 53c4b57..c77b85c 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -682,7 +682,7 @@
 /* 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;
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index a39e013..4abf5c0 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -212,7 +212,7 @@
  *
  */
 
-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;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 09aa62f..5c9e63d 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -495,7 +495,7 @@
 	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;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 2e3ba5f..bfcb860 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -814,7 +814,7 @@
 
 /* ------------------------------------------------------------------ */
 
-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;
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 67987ba..7aeec57 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -282,7 +282,7 @@
 }
 
 /* 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 @@
 		     __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;
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 48d138a..3e0ff8a 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -518,7 +518,7 @@
 }
 
 
-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;
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 5686547..525d812 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -406,7 +406,7 @@
 	}
 }
 
-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;
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 2ba2991..87e1130 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -582,7 +582,7 @@
 	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;
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index 4eee8be..abe2146 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -387,7 +387,7 @@
 }
 
 
-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;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index 56e01b6..9a26b94 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -125,7 +125,7 @@
 	}
 }
 
-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 @@
 		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;
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 13b37c8..d8b8802 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -1680,7 +1680,7 @@
 	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;
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index d1e04f7..6b6dff4 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -2325,7 +2325,7 @@
 	}
 }
 
-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;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 2912326..ddce2fb 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -417,7 +417,7 @@
 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 @@
   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;
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 1b2be2d..5b55634 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -303,7 +303,7 @@
 
 /*****************************************************************************/
 
-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;
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 3cbac2e..d9d5020 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -1408,8 +1408,7 @@
 
 irqreturn_t
 zoran_irq (int             irq,
-	   void           *dev_id,
-	   struct pt_regs *regs)
+	   void           *dev_id)
 {
 	u32 stat, astat;
 	int count;
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h
index f19705c..37fa86a 100644
--- a/drivers/media/video/zoran_device.h
+++ b/drivers/media/video/zoran_device.h
@@ -64,9 +64,7 @@
 /* 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);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index b5ffe53..0cbf564 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -335,13 +335,13 @@
 }
 
 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);