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/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index d56d400..1ffee7a 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -30,7 +30,7 @@
 
 /*#define DEBUG_ADB_IOP*/
 
-extern void iop_ism_irq(int, void *, struct pt_regs *);
+extern void iop_ism_irq(int, void *);
 
 static struct adb_request *current_req;
 static struct adb_request *last_req;
@@ -78,7 +78,7 @@
  * This will be called when a packet has been successfully sent.
  */
 
-static void adb_iop_complete(struct iop_msg *msg, struct pt_regs *regs)
+static void adb_iop_complete(struct iop_msg *msg)
 {
 	struct adb_request *req;
 	uint flags;
@@ -100,7 +100,7 @@
  * commands or autopoll packets) are received.
  */
 
-static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs)
+static void adb_iop_listen(struct iop_msg *msg)
 {
 	struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message;
 	struct adb_request *req;
@@ -143,7 +143,7 @@
 			req->reply_len = amsg->count + 1;
 			memcpy(req->reply, &amsg->cmd, req->reply_len);
 		} else {
-			adb_input(&amsg->cmd, amsg->count + 1, regs,
+			adb_input(&amsg->cmd, amsg->count + 1,
 				  amsg->flags & ADB_IOP_AUTOPOLL);
 		}
 		memcpy(msg->reply, msg->message, IOP_MSG_LEN);
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 360f93f..be0bd34 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -103,7 +103,7 @@
 static int try_handler_change(int, int);
 
 static struct adb_handler {
-	void (*handler)(unsigned char *, int, struct pt_regs *, int);
+	void (*handler)(unsigned char *, int, int);
 	int original_address;
 	int handler_id;
 	int busy;
@@ -522,7 +522,7 @@
     the handler_id id it doesn't match. */
 int
 adb_register(int default_id, int handler_id, struct adb_ids *ids,
-	     void (*handler)(unsigned char *, int, struct pt_regs *, int))
+	     void (*handler)(unsigned char *, int, int))
 {
 	int i;
 
@@ -570,13 +570,13 @@
 }
 
 void
-adb_input(unsigned char *buf, int nb, struct pt_regs *regs, int autopoll)
+adb_input(unsigned char *buf, int nb, int autopoll)
 {
 	int i, id;
 	static int dump_adb_input = 0;
 	unsigned long flags;
 	
-	void (*handler)(unsigned char *, int, struct pt_regs *, int);
+	void (*handler)(unsigned char *, int, int);
 
 	/* We skip keystrokes and mouse moves when the sleep process
 	 * has been started. We stop autopoll, but this is another security
@@ -597,7 +597,7 @@
 		adb_handler[id].busy = 1;
 	write_unlock_irqrestore(&adb_handler_lock, flags);
 	if (handler != NULL) {
-		(*handler)(buf, nb, regs, autopoll);
+		(*handler)(buf, nb, autopoll);
 		wmb();
 		adb_handler[id].busy = 0;
 	}
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index b7fb367..5066e7a 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -222,7 +222,7 @@
 
 static void adbhid_probe(void);
 
-static void adbhid_input_keycode(int, int, int, struct pt_regs *);
+static void adbhid_input_keycode(int, int, int);
 
 static void init_trackpad(int id);
 static void init_trackball(int id);
@@ -253,7 +253,7 @@
 #define ADBMOUSE_MACALLY2	9	/* MacAlly 2-button mouse */
 
 static void
-adbhid_keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll)
+adbhid_keyboard_input(unsigned char *data, int nb, int apoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -266,13 +266,13 @@
 	/* first check this is from register 0 */
 	if (nb != 3 || (data[0] & 3) != KEYB_KEYREG)
 		return;		/* ignore it */
-	adbhid_input_keycode(id, data[1], 0, regs);
+	adbhid_input_keycode(id, data[1], 0);
 	if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f)))
-		adbhid_input_keycode(id, data[2], 0, regs);
+		adbhid_input_keycode(id, data[2], 0);
 }
 
 static void
-adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
+adbhid_input_keycode(int id, int keycode, int repeat)
 {
 	struct adbhid *ahid = adbhid[id];
 	int up_flag;
@@ -282,7 +282,6 @@
 
 	switch (keycode) {
 	case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
-		input_regs(ahid->input, regs);
 		input_report_key(ahid->input, KEY_CAPSLOCK, 1);
 		input_report_key(ahid->input, KEY_CAPSLOCK, 0);
 		input_sync(ahid->input);
@@ -338,7 +337,6 @@
 	}
 
 	if (adbhid[id]->keycode[keycode]) {
-		input_regs(adbhid[id]->input, regs);
 		input_report_key(adbhid[id]->input,
 				 adbhid[id]->keycode[keycode], !up_flag);
 		input_sync(adbhid[id]->input);
@@ -349,7 +347,7 @@
 }
 
 static void
-adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+adbhid_mouse_input(unsigned char *data, int nb, int autopoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -432,8 +430,6 @@
                 break;
 	}
 
-	input_regs(adbhid[id]->input, regs);
-
 	input_report_key(adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
 	input_report_key(adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
@@ -449,7 +445,7 @@
 }
 
 static void
-adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+adbhid_buttons_input(unsigned char *data, int nb, int autopoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -458,8 +454,6 @@
 		return;
 	}
 
-	input_regs(adbhid[id]->input, regs);
-
 	switch (adbhid[id]->original_handler_id) {
 	default:
 	case 0x02: /* Adjustable keyboard button device */
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index 4b08852..57ccc19 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -64,7 +64,7 @@
 
 static int macio_probe(void);
 static int macio_init(void);
-static irqreturn_t macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macio_adb_interrupt(int irq, void *arg);
 static int macio_send_request(struct adb_request *req, int sync);
 static int macio_adb_autopoll(int devs);
 static void macio_adb_poll(void);
@@ -189,8 +189,7 @@
 	return 0;
 }
 
-static irqreturn_t macio_adb_interrupt(int irq, void *arg,
-				       struct pt_regs *regs)
+static irqreturn_t macio_adb_interrupt(int irq, void *arg)
 {
 	int i, n, err;
 	struct adb_request *req = NULL;
@@ -260,7 +259,7 @@
 		(*done)(req);
 	}
 	if (ibuf_len)
-		adb_input(ibuf, ibuf_len, regs, autopoll);
+		adb_input(ibuf, ibuf_len, autopoll);
 
 	return IRQ_RETVAL(handled);
 }
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index c0f9d82..ade25b3 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -145,7 +145,7 @@
 }
 
 
-static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t smu_db_intr(int irq, void *arg)
 {
 	unsigned long flags;
 	struct smu_cmd *cmd;
@@ -224,7 +224,7 @@
 }
 
 
-static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t smu_msg_intr(int irq, void *arg)
 {
 	/* I don't quite know what to do with this one, we seem to never
 	 * receive it, so I suspect we have to arm it someway in the SMU
@@ -309,7 +309,7 @@
 
 	gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
 	if ((gpio & 7) == 7)
-		smu_db_intr(smu->db_irq, smu, NULL);
+		smu_db_intr(smu->db_irq, smu);
 }
 EXPORT_SYMBOL(smu_poll);
 
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 7512d1c..64a07cc 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -98,8 +98,8 @@
 
 static int cuda_init_via(void);
 static void cuda_start(void);
-static irqreturn_t cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
-static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static irqreturn_t cuda_interrupt(int irq, void *arg);
+static void cuda_input(unsigned char *buf, int nb);
 void cuda_poll(void);
 static int cuda_write(struct adb_request *req);
 
@@ -442,7 +442,7 @@
 }
 
 static irqreturn_t
-cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
+cuda_interrupt(int irq, void *arg)
 {
     int status;
     struct adb_request *req = NULL;
@@ -594,12 +594,12 @@
 		(*done)(req);
     }
     if (ibuf_len)
-	cuda_input(ibuf, ibuf_len, regs);
+	cuda_input(ibuf, ibuf_len);
     return IRQ_HANDLED;
 }
 
 static void
-cuda_input(unsigned char *buf, int nb, struct pt_regs *regs)
+cuda_input(unsigned char *buf, int nb)
 {
     int i;
 
@@ -615,7 +615,7 @@
 	}
 #endif /* CONFIG_XMON */
 #ifdef CONFIG_ADB
-	adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
+	adb_input(buf+2, nb-2, buf[1] & 0x40);
 #endif /* CONFIG_ADB */
 	break;
 
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 2a2ffe0..ad4bd57 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -77,7 +77,7 @@
 
 static int  macii_init_via(void);
 static void macii_start(void);
-static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macii_interrupt(int irq, void *arg);
 static void macii_retransmit(int);
 static void macii_queue_poll(void);
 
@@ -410,7 +410,7 @@
  * Note: As of 21/10/97, the MacII ADB part works including timeout detection
  * and retransmit (Talk to the last active device).
  */
-static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t macii_interrupt(int irq, void *arg)
 {
 	int x, adbdir;
 	unsigned long flags;
@@ -602,8 +602,7 @@
 				current_req = req->next;
 				if (req->done) (*req->done)(req);
 			} else {
-				adb_input(reply_buf, reply_ptr - reply_buf,
-					  regs, 0);
+				adb_input(reply_buf, reply_ptr - reply_buf, 0);
 			}
 
 			/*
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 0129fcc..789ee52 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -84,8 +84,8 @@
 static int maciisi_send_request(struct adb_request* req, int sync);
 static void maciisi_sync(struct adb_request *req);
 static int maciisi_write(struct adb_request* req);
-static irqreturn_t maciisi_interrupt(int irq, void* arg, struct pt_regs* regs);
-static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static irqreturn_t maciisi_interrupt(int irq, void* arg);
+static void maciisi_input(unsigned char *buf, int nb);
 static int maciisi_init_via(void);
 static void maciisi_poll(void);
 static int maciisi_start(void);
@@ -433,7 +433,7 @@
    register is either full or empty. In practice, I have no idea what
    it means :( */
 static irqreturn_t
-maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
+maciisi_interrupt(int irq, void* arg)
 {
 	int status;
 	struct adb_request *req;
@@ -612,7 +612,7 @@
 			/* Obviously, we got it */
 			reading_reply = 0;
 		} else {
-			maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf, regs);
+			maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf);
 		}
 		maciisi_state = idle;
 		status = via[B] & (TIP|TREQ);
@@ -657,7 +657,7 @@
 }
 
 static void
-maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs)
+maciisi_input(unsigned char *buf, int nb)
 {
 #ifdef DEBUG_MACIISI_ADB
     int i;
@@ -665,7 +665,7 @@
 
     switch (buf[0]) {
     case ADB_PACKET:
-	    adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
+	    adb_input(buf+2, nb-2, buf[1] & 0x40);
 	    break;
     default:
 #ifdef DEBUG_MACIISI_ADB
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4f04fd0..e63ea1c 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -191,8 +191,8 @@
 
 static int init_pmu(void);
 static void pmu_start(void);
-static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
-static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t via_pmu_interrupt(int irq, void *arg);
+static irqreturn_t gpio1_interrupt(int irq, void *arg);
 static int proc_get_info(char *page, char **start, off_t off,
 			  int count, int *eof, void *data);
 static int proc_get_irqstats(char *page, char **start, off_t off,
@@ -555,7 +555,7 @@
 		}
 		if (pmu_state == idle)
 			adb_int_pending = 1;
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		udelay(10);
 	}
 
@@ -1215,7 +1215,7 @@
 		return;
 	if (disable_poll)
 		return;
-	via_pmu_interrupt(0, NULL, NULL);
+	via_pmu_interrupt(0, NULL);
 }
 
 void
@@ -1228,7 +1228,7 @@
 	/* Kicks ADB read when PMU is suspended */
 	adb_int_pending = 1;
 	do {
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 	} while (pmu_suspended && (adb_int_pending || pmu_state != idle
 		|| req_awaiting_reply));
 }
@@ -1239,7 +1239,7 @@
 	if (!via)
 		return;
 	while((pmu_state != idle && pmu_state != locked) || !req->complete)
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 }
 
 /* This function loops until the PMU is idle and prevents it from
@@ -1268,7 +1268,7 @@
 		spin_unlock_irqrestore(&pmu_lock, flags);
 		if (req_awaiting_reply)
 			adb_int_pending = 1;
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		spin_lock_irqsave(&pmu_lock, flags);
 		if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {
 #ifdef SUSPEND_USES_PMU
@@ -1318,7 +1318,7 @@
 
 /* Interrupt data could be the result data from an ADB cmd */
 static void
-pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
+pmu_handle_data(unsigned char *data, int len)
 {
 	unsigned char ints, pirq;
 	int i = 0;
@@ -1393,7 +1393,7 @@
 			if (!(pmu_kind == PMU_OHARE_BASED && len == 4
 			      && data[1] == 0x2c && data[3] == 0xff
 			      && (data[2] & ~1) == 0xf4))
-				adb_input(data+1, len-1, regs, 1);
+				adb_input(data+1, len-1, 1);
 #endif /* CONFIG_ADB */		
 		}
 	}
@@ -1431,7 +1431,7 @@
 }
 
 static struct adb_request*
-pmu_sr_intr(struct pt_regs *regs)
+pmu_sr_intr(void)
 {
 	struct adb_request *req;
 	int bite = 0;
@@ -1537,7 +1537,7 @@
 }
 
 static irqreturn_t
-via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
+via_pmu_interrupt(int irq, void *arg)
 {
 	unsigned long flags;
 	int intr;
@@ -1567,7 +1567,7 @@
 			pmu_irq_stats[0]++;
 		}
 		if (intr & SR_INT) {
-			req = pmu_sr_intr(regs);
+			req = pmu_sr_intr();
 			if (req)
 				break;
 		}
@@ -1613,7 +1613,7 @@
 		
 	/* Deal with interrupt datas outside of the lock */
 	if (int_data >= 0) {
-		pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data], regs);
+		pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data]);
 		spin_lock_irqsave(&pmu_lock, flags);
 		++disable_poll;
 		int_data_state[int_data] = int_data_empty;
@@ -1638,7 +1638,7 @@
 
 
 static irqreturn_t
-gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
+gpio1_interrupt(int irq, void *arg)
 {
 	unsigned long flags;
 
@@ -1651,7 +1651,7 @@
 		pmu_irq_stats[1]++;
 		adb_int_pending = 1;
 		spin_unlock_irqrestore(&pmu_lock, flags);
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
@@ -2116,7 +2116,7 @@
 
 	/* Force a poll of ADB interrupts */
 	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL, NULL);
+	via_pmu_interrupt(0, NULL);
 
 	/* Restart jiffies & scheduling */
 	wakeup_decrementer();
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 9f4eff1..98ec915 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -107,7 +107,7 @@
 static int pmu_probe(void);
 static int pmu_init(void);
 static void pmu_start(void);
-static irqreturn_t pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t pmu_interrupt(int irq, void *arg);
 static int pmu_send_request(struct adb_request *req, int sync);
 static int pmu_autopoll(int devs);
 void pmu_poll(void);
@@ -118,8 +118,7 @@
 static void send_byte(int x);
 static void recv_byte(void);
 static void pmu_done(struct adb_request *req);
-static void pmu_handle_data(unsigned char *data, int len,
-			    struct pt_regs *regs);
+static void pmu_handle_data(unsigned char *data, int len);
 static void set_volume(int level);
 static void pmu_enable_backlight(int on);
 static void pmu_set_brightness(int level);
@@ -573,7 +572,7 @@
 }
 
 static irqreturn_t
-pmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+pmu_interrupt(int irq, void *dev_id)
 {
 	struct adb_request *req;
 	int timeout, bite = 0;	/* to prevent compiler warning */
@@ -657,7 +656,7 @@
 			}
 
 			if (pmu_state == reading_intr) {
-				pmu_handle_data(interrupt_data, data_index, regs);
+				pmu_handle_data(interrupt_data, data_index);
 			} else {
 				req = current_req;
 				current_req = req->next;
@@ -701,7 +700,7 @@
 
 /* Interrupt data could be the result data from an ADB cmd */
 static void 
-pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
+pmu_handle_data(unsigned char *data, int len)
 {
 	static int show_pmu_ints = 1;
 
@@ -726,7 +725,7 @@
 			}
 			pmu_done(req);
 		} else {
-			adb_input(data+1, len-1, regs, 1);
+			adb_input(data+1, len-1, 1);
 		}
 	} else {
 		if (data[0] == 0x08 && len == 3) {