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/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5ac9185..aac6ec5 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -254,8 +254,8 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs);
-static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
+static void end_unlink_async (struct ehci_hcd *ehci);
+static void ehci_work(struct ehci_hcd *ehci);
 
 #include "ehci-hub.c"
 #include "ehci-mem.c"
@@ -280,7 +280,7 @@
 			ehci_vdbg (ehci, "lost IAA\n");
 			COUNT (ehci->stats.lost_iaa);
 			writel (STS_IAA, &ehci->regs->status);
-			end_unlink_async (ehci, NULL);
+			end_unlink_async (ehci);
 		}
 	}
 
@@ -299,7 +299,7 @@
 		start_unlink_async (ehci, ehci->async);
 
 	/* ehci could run by timer, without IRQs ... */
-	ehci_work (ehci, NULL);
+	ehci_work (ehci);
 
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
@@ -342,7 +342,7 @@
  * ehci_work is called from some interrupts, timers, and so on.
  * it calls driver completion functions, after dropping ehci->lock.
  */
-static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void ehci_work (struct ehci_hcd *ehci)
 {
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
 
@@ -353,9 +353,9 @@
 	if (ehci->scanning)
 		return;
 	ehci->scanning = 1;
-	scan_async (ehci, regs);
+	scan_async (ehci);
 	if (ehci->next_uframe != -1)
-		scan_periodic (ehci, regs);
+		scan_periodic (ehci);
 	ehci->scanning = 0;
 
 	/* the IO watchdog guards against hardware or driver bugs that
@@ -397,7 +397,7 @@
 	/* root hub is shut down separately (first, when possible) */
 	spin_lock_irq (&ehci->lock);
 	if (ehci->async)
-		ehci_work (ehci, NULL);
+		ehci_work (ehci);
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
@@ -573,7 +573,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status;
@@ -619,7 +619,7 @@
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 		COUNT (ehci->stats.reclaim);
-		end_unlink_async (ehci, regs);
+		end_unlink_async (ehci);
 		bh = 1;
 	}
 
@@ -670,7 +670,7 @@
 	}
 
 	if (bh)
-		ehci_work (ehci, regs);
+		ehci_work (ehci);
 	spin_unlock (&ehci->lock);
 	return IRQ_HANDLED;
 }
@@ -727,7 +727,7 @@
 
 	/* failfast */
 	if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
-		end_unlink_async (ehci, NULL);
+		end_unlink_async (ehci);
 
 	/* defer till later if busy */
 	else if (ehci->reclaim) {
@@ -787,7 +787,7 @@
 			intr_deschedule (ehci, qh);
 			/* FALL THROUGH */
 		case QH_STATE_IDLE:
-			qh_completions (ehci, qh, NULL);
+			qh_completions (ehci, qh);
 			break;
 		default:
 			ehci_dbg (ehci, "bogus qh %p state %d\n",
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index b2ee13c..2012213 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -48,8 +48,8 @@
 	}
 	ehci->command = readl (&ehci->regs->command);
 	if (ehci->reclaim)
-		end_unlink_async (ehci, NULL);
-	ehci_work(ehci, NULL);
+		end_unlink_async (ehci);
+	ehci_work(ehci);
 
 	/* suspend any active/unsuspended ports, maybe allow wakeup */
 	while (port--) {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 08d0472..35e3fab 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -303,8 +303,8 @@
 	/* emptying the schedule aborts any urbs */
 	spin_lock_irq(&ehci->lock);
 	if (ehci->reclaim)
-		end_unlink_async (ehci, NULL);
-	ehci_work(ehci, NULL);
+		end_unlink_async (ehci);
+	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
 	/* restart; khubd will disconnect devices */
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 7fc25b6..4632727 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -214,7 +214,7 @@
 }
 
 static void
-ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs)
+ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb)
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
@@ -262,7 +262,7 @@
 
 	/* complete() can reenter this HCD */
 	spin_unlock (&ehci->lock);
-	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb, regs);
+	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb);
 	spin_lock (&ehci->lock);
 }
 
@@ -279,7 +279,7 @@
  */
 #define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
 static unsigned
-qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
+qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	struct ehci_qtd		*last = NULL, *end = qh->dummy;
 	struct list_head	*entry, *tmp;
@@ -317,7 +317,7 @@
 		/* clean up any state from previous QTD ...*/
 		if (last) {
 			if (likely (last->urb != urb)) {
-				ehci_urb_done (ehci, last->urb, regs);
+				ehci_urb_done (ehci, last->urb);
 				count++;
 			}
 			ehci_qtd_free (ehci, last);
@@ -407,7 +407,7 @@
 
 	/* last urb's completion might still need calling */
 	if (likely (last != NULL)) {
-		ehci_urb_done (ehci, last->urb, regs);
+		ehci_urb_done (ehci, last->urb);
 		count++;
 		ehci_qtd_free (ehci, last);
 	}
@@ -962,7 +962,7 @@
 
 /* the async qh for the qtds being reclaimed are now unlinked from the HC */
 
-static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void end_unlink_async (struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
@@ -979,7 +979,7 @@
 	ehci->reclaim = next;
 	qh->reclaim = NULL;
 
-	qh_completions (ehci, qh, regs);
+	qh_completions (ehci, qh);
 
 	if (!list_empty (&qh->qtd_list)
 			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
@@ -1047,7 +1047,7 @@
 		/* if (unlikely (qh->reclaim != 0))
 		 *	this will recurse, probably not much
 		 */
-		end_unlink_async (ehci, NULL);
+		end_unlink_async (ehci);
 		return;
 	}
 
@@ -1059,8 +1059,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void
-scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void scan_async (struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
@@ -1084,7 +1083,7 @@
 				 */
 				qh = qh_get (qh);
 				qh->stamp = ehci->stamp;
-				temp = qh_completions (ehci, qh, regs);
+				temp = qh_completions (ehci, qh);
 				qh_put (qh);
 				if (temp != 0) {
 					goto rescan;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e5e9c65..65c402a 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1553,8 +1553,7 @@
 static unsigned
 itd_complete (
 	struct ehci_hcd	*ehci,
-	struct ehci_itd	*itd,
-	struct pt_regs	*regs
+	struct ehci_itd	*itd
 ) {
 	struct urb				*urb = itd->urb;
 	struct usb_iso_packet_descriptor	*desc;
@@ -1613,7 +1612,7 @@
 
 	/* give urb back to the driver ... can be out-of-order */
 	dev = urb->dev;
-	ehci_urb_done (ehci, urb, regs);
+	ehci_urb_done (ehci, urb);
 	urb = NULL;
 
 	/* defer stopping schedule; completion can submit */
@@ -1930,8 +1929,7 @@
 static unsigned
 sitd_complete (
 	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd,
-	struct pt_regs		*regs
+	struct ehci_sitd	*sitd
 ) {
 	struct urb				*urb = sitd->urb;
 	struct usb_iso_packet_descriptor	*desc;
@@ -1978,7 +1976,7 @@
 
 	/* give urb back to the driver */
 	dev = urb->dev;
-	ehci_urb_done (ehci, urb, regs);
+	ehci_urb_done (ehci, urb);
 	urb = NULL;
 
 	/* defer stopping schedule; completion can submit */
@@ -2065,8 +2063,7 @@
 static inline unsigned
 sitd_complete (
 	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd,
-	struct pt_regs		*regs
+	struct ehci_sitd	*sitd
 ) {
 	ehci_err (ehci, "sitd_complete %p?\n", sitd);
 	return 0;
@@ -2077,7 +2074,7 @@
 /*-------------------------------------------------------------------------*/
 
 static void
-scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
+scan_periodic (struct ehci_hcd *ehci)
 {
 	unsigned	frame, clock, now_uframe, mod;
 	unsigned	modified;
@@ -2131,7 +2128,7 @@
 				temp.qh = qh_get (q.qh);
 				type = Q_NEXT_TYPE (q.qh->hw_next);
 				q = q.qh->qh_next;
-				modified = qh_completions (ehci, temp.qh, regs);
+				modified = qh_completions (ehci, temp.qh);
 				if (unlikely (list_empty (&temp.qh->qtd_list)))
 					intr_deschedule (ehci, temp.qh);
 				qh_put (temp.qh);
@@ -2169,7 +2166,7 @@
 				*hw_p = q.itd->hw_next;
 				type = Q_NEXT_TYPE (q.itd->hw_next);
 				wmb();
-				modified = itd_complete (ehci, q.itd, regs);
+				modified = itd_complete (ehci, q.itd);
 				q = *q_p;
 				break;
 			case Q_TYPE_SITD:
@@ -2185,7 +2182,7 @@
 				*hw_p = q.sitd->hw_next;
 				type = Q_NEXT_TYPE (q.sitd->hw_next);
 				wmb();
-				modified = sitd_complete (ehci, q.sitd, regs);
+				modified = sitd_complete (ehci, q.sitd);
 				q = *q_p;
 				break;
 			default:
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 61e5717..87eca6a 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -478,9 +478,9 @@
 static int etrax_usb_unlink_urb(struct urb *urb, int status);
 static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
 
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs);
+static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc);
+static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc);
+static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc);
 static void etrax_usb_hc_interrupt_bottom_half(void *data);
 
 static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data);
@@ -1573,7 +1573,7 @@
 	return (*R_USB_FM_NUMBER & 0x7ff);
 }
 
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc)
 {
 	DBFENTER;
 
@@ -1839,7 +1839,7 @@
 
 
 
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc)
 {
 	struct urb *urb;
 	etrax_urb_priv_t *urb_priv;
@@ -3280,7 +3280,7 @@
 
 
 
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc)
 {
 	usb_interrupt_registers_t *reg;
 	unsigned long flags;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index a72e041..2718b5d 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -418,7 +418,7 @@
   processed urbs.
 */
 static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
-			   struct urb *urb, struct pt_regs *regs)
+			   struct urb *urb)
 __releases(isp116x->lock) __acquires(isp116x->lock)
 {
 	unsigned i;
@@ -432,7 +432,7 @@
 	urb_dbg(urb, "Finish");
 
 	spin_unlock(&isp116x->lock);
-	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs);
+	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
 	spin_lock(&isp116x->lock);
 
 	/* take idle endpoints out of the schedule */
@@ -568,7 +568,7 @@
 /*
   Finish the processed transfers
 */
-static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs)
+static void finish_atl_transfers(struct isp116x *isp116x)
 {
 	struct isp116x_ep *ep;
 	struct urb *urb;
@@ -590,12 +590,12 @@
 		   occured, while URB_SHORT_NOT_OK was set */
 		if (urb && urb->status != -EINPROGRESS
 		    && ep->nextpid != USB_PID_ACK)
-			finish_request(isp116x, ep, urb, regs);
+			finish_request(isp116x, ep, urb);
 	}
 	atomic_dec(&isp116x->atl_finishing);
 }
 
-static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	u16 irqstat;
@@ -608,7 +608,7 @@
 
 	if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) {
 		ret = IRQ_HANDLED;
-		finish_atl_transfers(isp116x, regs);
+		finish_atl_transfers(isp116x);
 	}
 
 	if (irqstat & HCuPINT_OPR) {
@@ -824,7 +824,7 @@
 	spin_lock(&urb->lock);
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock(&urb->lock);
-		finish_request(isp116x, ep, urb, NULL);
+		finish_request(isp116x, ep, urb);
 		ret = 0;
 		goto fail;
 	}
@@ -870,7 +870,7 @@
 			}
 
 	if (urb)
-		finish_request(isp116x, ep, urb, NULL);
+		finish_request(isp116x, ep, urb);
 
 	spin_unlock_irqrestore(&isp116x->lock, flags);
 	return 0;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index d1d68c4..9be6b30 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -261,7 +261,7 @@
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock (&urb->lock);
 		urb->hcpriv = urb_priv;
-		finish_urb (ohci, urb, NULL);
+		finish_urb (ohci, urb);
 		retval = 0;
 		goto fail;
 	}
@@ -337,7 +337,7 @@
 		 * any more ... just clean up every urb's memory.
 		 */
 		if (urb->hcpriv)
-			finish_urb (ohci, urb, NULL);
+			finish_urb (ohci, urb);
 	}
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return 0;
@@ -369,7 +369,7 @@
 	if (!HC_IS_RUNNING (hcd->state)) {
 sanitize:
 		ed->state = ED_IDLE;
-		finish_unlinks (ohci, 0, NULL);
+		finish_unlinks (ohci, 0);
 	}
 
 	switch (ed->state) {
@@ -691,7 +691,7 @@
 
 /* an interrupt happens */
 
-static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	struct ohci_regs __iomem *regs = ohci->regs;
@@ -747,7 +747,7 @@
 		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
 		spin_lock (&ohci->lock);
-		dl_done_list (ohci, ptregs);
+		dl_done_list (ohci);
 		spin_unlock (&ohci->lock);
 		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable); 
@@ -760,7 +760,7 @@
 	 */
 	spin_lock (&ohci->lock);
 	if (ohci->ed_rm_list)
-		finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
+		finish_unlinks (ohci, ohci_frame_no(ohci));
 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
 			&& HC_IS_RUNNING(hcd->state))
 		ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);	
@@ -852,7 +852,7 @@
 		urb->status = -ESHUTDOWN;
 		spin_unlock (&urb->lock);
 	}
-	finish_unlinks (ohci, 0, NULL);
+	finish_unlinks (ohci, 0);
 	spin_unlock_irq(&ohci->lock);
 
 	/* paranoia, in case that didn't work: */
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index ec75774..6f11359 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -47,8 +47,8 @@
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
-static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
-static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
+static void dl_done_list (struct ohci_hcd *);
+static void finish_unlinks (struct ohci_hcd *, u16);
 
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
 __releases(ohci->lock)
@@ -94,8 +94,8 @@
 		msleep (8);
 		spin_lock_irq (&ohci->lock);
 	}
-	dl_done_list (ohci, NULL);
-	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
+	dl_done_list (ohci);
+	finish_unlinks (ohci, ohci_frame_no(ohci));
 
 	/* maybe resume can wake root hub */
 	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index e372306..e08d1a2 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -7,6 +7,8 @@
  * This file is licenced under the GPL.
  */
 
+#include <linux/irq.h>
+
 static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
 {
 	int		last = urb_priv->length - 1;
@@ -34,7 +36,7 @@
  * PRECONDITION:  ohci lock held, irqs blocked.
  */
 static void
-finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
+finish_urb (struct ohci_hcd *ohci, struct urb *urb)
 __releases(ohci->lock)
 __acquires(ohci->lock)
 {
@@ -73,7 +75,7 @@
 
 	/* urb->complete() can reenter this HCD */
 	spin_unlock (&ohci->lock);
-	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb, regs);
+	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
 	spin_lock (&ohci->lock);
 
 	/* stop periodic dma if it's not needed */
@@ -910,7 +912,7 @@
 
 /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
 static void
-finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
+finish_unlinks (struct ohci_hcd *ohci, u16 tick)
 {
 	struct ed	*ed, **last;
 
@@ -923,7 +925,7 @@
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
 		 */
-		if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
+		if (likely (get_irq_regs() && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
 			if (tick_before (tick, ed->tick)) {
 skip_ed:
 				last = &ed->ed_next;
@@ -990,7 +992,7 @@
 			/* if URB is done, clean up */
 			if (urb_priv->td_cnt == urb_priv->length) {
 				modified = completed = 1;
-				finish_urb (ohci, urb, regs);
+				finish_urb (ohci, urb);
 			}
 		}
 		if (completed && !list_empty (&ed->td_list))
@@ -1068,7 +1070,7 @@
  * scanning the (re-reversed) donelist as this does.
  */
 static void
-dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs)
+dl_done_list (struct ohci_hcd *ohci)
 {
 	struct td	*td = dl_reverse_done_list (ohci);
 
@@ -1084,7 +1086,7 @@
 
 		/* If all this urb's TDs are done, call complete() */
   		if (urb_priv->td_cnt == urb_priv->length)
-  			finish_urb (ohci, urb, regs);
+  			finish_urb (ohci, urb);
 
 		/* clean schedule:  unlink EDs that are no longer busy */
 		if (list_empty (&ed->td_list)) {
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 3a586aa..5fa5647 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -428,7 +428,6 @@
 	struct sl811		*sl811,
 	struct sl811h_ep	*ep,
 	struct urb		*urb,
-	struct pt_regs		*regs,
 	int			status
 ) __releases(sl811->lock) __acquires(sl811->lock)
 {
@@ -444,7 +443,7 @@
 	spin_unlock(&urb->lock);
 
 	spin_unlock(&sl811->lock);
-	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, regs);
+	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
 	spin_lock(&sl811->lock);
 
 	/* leave active endpoints in the schedule */
@@ -484,7 +483,7 @@
 }
 
 static void
-done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
+done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
 {
 	u8			status;
 	struct urb		*urb;
@@ -608,7 +607,7 @@
 	}
 
 	if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS))
-		finish_request(sl811, ep, urb, regs, urbstat);
+		finish_request(sl811, ep, urb, urbstat);
 }
 
 static inline u8 checkdone(struct sl811 *sl811)
@@ -641,7 +640,7 @@
 	return irqstat;
 }
 
-static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t sl811h_irq(struct usb_hcd *hcd)
 {
 	struct sl811	*sl811 = hcd_to_sl811(hcd);
 	u8		irqstat;
@@ -670,13 +669,13 @@
 	 * issued ... that's fine if they're different endpoints.
 	 */
 	if (irqstat & SL11H_INTMASK_DONE_A) {
-		done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF), regs);
+		done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF));
 		sl811->active_a = NULL;
 		sl811->stat_a++;
 	}
 #ifdef USE_B
 	if (irqstat & SL11H_INTMASK_DONE_B) {
-		done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF), regs);
+		done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF));
 		sl811->active_b = NULL;
 		sl811->stat_b++;
 	}
@@ -723,7 +722,7 @@
 				container_of(sl811->active_a
 						->hep->urb_list.next,
 					struct urb, urb_list),
-				NULL, -ESHUTDOWN);
+				-ESHUTDOWN);
 			sl811->active_a = NULL;
 		}
 #ifdef	USE_B
@@ -957,7 +956,7 @@
 	spin_lock(&urb->lock);
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock(&urb->lock);
-		finish_request(sl811, ep, urb, NULL, 0);
+		finish_request(sl811, ep, urb, 0);
 		retval = 0;
 		goto fail;
 	}
@@ -1026,7 +1025,7 @@
 		}
 
 		if (urb)
-			finish_request(sl811, ep, urb, NULL, 0);
+			finish_request(sl811, ep, urb, 0);
 		else
 			VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
 				(sl811->active_a == ep) ? "A" : "B");
@@ -1083,7 +1082,7 @@
 	 */
 	local_irq_save(flags);
 	if (!timer_pending(&sl811->timer)) {
-		if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE)
+		if (sl811h_irq( /* ~0, */ hcd) != IRQ_NONE)
 			sl811->stat_lost++;
 	}
 	local_irq_restore(flags);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 0a31520..32c635e 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -557,7 +557,7 @@
         u132_ring_queue_work(u132, ring, 0);
         up(&u132->scheduler_lock);
         u132_endp_put_kref(u132, endp);
-        usb_hcd_giveback_urb(hcd, urb, NULL);
+        usb_hcd_giveback_urb(hcd, urb);
         return;
 }
 
@@ -590,7 +590,7 @@
                 endp->active = 0;
                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
                 kfree(urbq);
-        } usb_hcd_giveback_urb(hcd, urb, NULL);
+        } usb_hcd_giveback_urb(hcd, urb);
         return;
 }
 
@@ -2434,7 +2434,7 @@
                         endp->queue_size -= 1;
                         urb->error_count = 0;
                         urb->hcpriv = NULL;
-                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else
                         continue;
@@ -2512,7 +2512,7 @@
                                 kfree(urbq);
                         } urb->error_count = 0;
                         urb->hcpriv = NULL;
-                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else if (list_empty(&endp->urb_more)) {
                         dev_err(&u132->platform_dev->dev, "urb=%p not found in "
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index eb4eab9..45ee692 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -252,7 +252,7 @@
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	uhci_fsbr_off(uhci);
 }
 
@@ -309,7 +309,7 @@
 	mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
-static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t uhci_irq(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned short status;
@@ -358,7 +358,7 @@
 		usb_hcd_poll_rh_status(hcd);
 	else {
 		spin_lock_irqsave(&uhci->lock, flags);
-		uhci_scan_schedule(uhci, regs);
+		uhci_scan_schedule(uhci);
 		spin_unlock_irqrestore(&uhci->lock, flags);
 	}
 
@@ -671,7 +671,7 @@
 	spin_lock_irq(&uhci->lock);
 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
 		uhci_hc_died(uhci);
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	spin_unlock_irq(&uhci->lock);
 
 	del_timer_sync(&uhci->fsbr_timer);
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 16fb72eb..f8347f1 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -176,7 +176,7 @@
 
 	spin_lock_irqsave(&uhci->lock, flags);
 
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
 		goto done;
 	uhci_check_ports(uhci);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 431e8f3..06115f2 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1244,7 +1244,7 @@
  * Finish unlinking an URB and give it back
  */
 static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
-		struct urb *urb, struct pt_regs *regs)
+		struct urb *urb)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
@@ -1293,7 +1293,7 @@
 	}
 
 	spin_unlock(&uhci->lock);
-	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs);
+	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
 	spin_lock(&uhci->lock);
 
 	/* If the queue is now empty, we can unlink the QH and give up its
@@ -1313,8 +1313,7 @@
 		(qh->state == QH_STATE_UNLINKING &&	\
 		uhci->frame_number + uhci->is_stopped != qh->unlink_frame)
 
-static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
-		struct pt_regs *regs)
+static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct urb_priv *urbp;
 	struct urb *urb;
@@ -1347,7 +1346,7 @@
 				return;
 		}
 
-		uhci_giveback_urb(uhci, qh, urb, regs);
+		uhci_giveback_urb(uhci, qh, urb);
 		if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
 			break;
 	}
@@ -1372,7 +1371,7 @@
 				qh->is_stopped = 0;
 				return;
 			}
-			uhci_giveback_urb(uhci, qh, urb, regs);
+			uhci_giveback_urb(uhci, qh, urb);
 			goto restart;
 		}
 	}
@@ -1487,7 +1486,7 @@
 /*
  * Process events in the schedule, but only in one thread at a time
  */
-static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+static void uhci_scan_schedule(struct uhci_hcd *uhci)
 {
 	int i;
 	struct uhci_qh *qh;
@@ -1515,7 +1514,7 @@
 					struct uhci_qh, node);
 
 			if (uhci_advance_check(uhci, qh)) {
-				uhci_scan_qh(uhci, qh, regs);
+				uhci_scan_qh(uhci, qh);
 				if (qh->state == QH_STATE_ACTIVE) {
 					uhci_urbp_wants_fsbr(uhci,
 	list_entry(qh->queue.next, struct urb_priv, node));