Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 014e73c9 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

[PATCH] USB UHCI: subroutine reordering



This patch moves a few subroutines around in the uhci-hcd source file.
Nothing else is changed.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 72ebddb5
Loading
Loading
Loading
Loading
+143 −144
Original line number Diff line number Diff line
@@ -90,7 +90,6 @@ static char *errbuf;
static kmem_cache_t *uhci_up_cachep;	/* urb_priv */

static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
static void hc_state_transitions(struct uhci_hcd *uhci);

/* If a transfer is still active after this much time, turn off FSBR */
#define IDLE_TIMEOUT	msecs_to_jiffies(50)
@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci);
#include "uhci-debug.c"
#include "uhci-q.c"

static int init_stall_timer(struct usb_hcd *hcd);

static void stall_callback(unsigned long ptr)
{
	struct usb_hcd *hcd = (struct usb_hcd *)ptr;
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	struct urb_priv *up;
	unsigned long flags;

	spin_lock_irqsave(&uhci->lock, flags);
	uhci_scan_schedule(uhci, NULL);

	list_for_each_entry(up, &uhci->urb_list, urb_list) {
		struct urb *u = up->urb;

		spin_lock(&u->lock);

		/* Check if the FSBR timed out */
		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
			uhci_fsbr_timeout(uhci, u);

		spin_unlock(&u->lock);
	}

	/* Really disable FSBR */
	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
		uhci->fsbrtimeout = 0;
		uhci->skel_term_qh->link = UHCI_PTR_TERM;
	}

	/* Poll for and perform state transitions */
	hc_state_transitions(uhci);
	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
		uhci_check_ports(uhci);

	init_stall_timer(hcd);
	spin_unlock_irqrestore(&uhci->lock, flags);
}

static int init_stall_timer(struct usb_hcd *hcd)
static int ports_active(struct uhci_hcd *uhci)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	unsigned long io_addr = uhci->io_addr;
	int connection = 0;
	int i;

	init_timer(&uhci->stall_timer);
	uhci->stall_timer.function = stall_callback;
	uhci->stall_timer.data = (unsigned long)hcd;
	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
	add_timer(&uhci->stall_timer);
	for (i = 0; i < uhci->rh_numports; i++)
		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);

	return 0;
	return connection;
}

static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
static int suspend_allowed(struct uhci_hcd *uhci)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	unsigned long io_addr = uhci->io_addr;
	unsigned short status;
	int i;

	/*
	 * Read the interrupt status, and write it back to clear the
	 * interrupt cause.  Contrary to the UHCI specification, the
	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
		return 1;

	/* Some of Intel's USB controllers have a bug that causes false
	 * resume indications if any port has an over current condition.
	 * To prevent problems, we will not allow a global suspend if
	 * any ports are OC.
	 *
	 * Some motherboards using Intel's chipsets (but not using all
	 * the USB ports) appear to hardwire the over current inputs active
	 * to disable the USB ports.
	 */
	status = inw(io_addr + USBSTS);
	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
		return IRQ_NONE;
	outw(status, io_addr + USBSTS);		/* Clear it */

	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
		if (status & USBSTS_HSE)
			dev_err(uhci_dev(uhci), "host system error, "
					"PCI problems?\n");
		if (status & USBSTS_HCPE)
			dev_err(uhci_dev(uhci), "host controller process "
					"error, something bad happened!\n");
		if ((status & USBSTS_HCH) && uhci->state > 0) {
			dev_err(uhci_dev(uhci), "host controller halted, "
					"very bad!\n");
			/* FIXME: Reset the controller, fix the offending TD */
		}
	/* check for over current condition on any port */
	for (i = 0; i < uhci->rh_numports; i++) {
		if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
			return 0;
	}

	if (status & USBSTS_RD)
		uhci->resume_detect = 1;

	spin_lock(&uhci->lock);
	uhci_scan_schedule(uhci, regs);
	spin_unlock(&uhci->lock);

	return IRQ_HANDLED;
	return 1;
}

static void reset_hc(struct uhci_hcd *uhci)
@@ -276,43 +222,46 @@ static void wakeup_hc(struct uhci_hcd *uhci)
	}
}

static int ports_active(struct uhci_hcd *uhci)
static int start_hc(struct uhci_hcd *uhci)
{
	unsigned long io_addr = uhci->io_addr;
	int connection = 0;
	int i;

	for (i = 0; i < uhci->rh_numports; i++)
		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
	int timeout = 10;

	return connection;
	/*
	 * Reset the HC - this will force us to get a
	 * new notification of any already connected
	 * ports due to the virtual disconnect that it
	 * implies.
	 */
	outw(USBCMD_HCRESET, io_addr + USBCMD);
	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
		if (--timeout < 0) {
			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
			return -ETIMEDOUT;
		}
		msleep(1);
	}

static int suspend_allowed(struct uhci_hcd *uhci)
{
	unsigned long io_addr = uhci->io_addr;
	int i;
	/* Mark controller as running before we enable interrupts */
	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;

	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
		return 1;
	/* Turn on PIRQ and all interrupts */
	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
			USBLEGSUP_DEFAULT);
	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
		io_addr + USBINTR);

	/* Some of Intel's USB controllers have a bug that causes false
	 * resume indications if any port has an over current condition.
	 * To prevent problems, we will not allow a global suspend if
	 * any ports are OC.
	 *
	 * Some motherboards using Intel's chipsets (but not using all
	 * the USB ports) appear to hardwire the over current inputs active
	 * to disable the USB ports.
	 */
	/* Start at frame 0 */
	outw(0, io_addr + USBFRNUM);
	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);

	/* check for over current condition on any port */
	for (i = 0; i < uhci->rh_numports; i++) {
		if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
			return 0;
	}
	/* Run and mark it configured with a 64-byte max packet */
	uhci->state = UHCI_RUNNING_GRACE;
	uhci->state_end = jiffies + HZ;
	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
	uhci->is_stopped = 0;

	return 1;
	return 0;
}

static void hc_state_transitions(struct uhci_hcd *uhci)
@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
	}
}

/*
 * Store the current frame number in uhci->frame_number if the controller
 * is runnning
 */
static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
static int init_stall_timer(struct usb_hcd *hcd);

static void stall_callback(unsigned long ptr)
{
	if (!uhci->is_stopped)
		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
	struct usb_hcd *hcd = (struct usb_hcd *)ptr;
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	struct urb_priv *up;
	unsigned long flags;

	spin_lock_irqsave(&uhci->lock, flags);
	uhci_scan_schedule(uhci, NULL);

	list_for_each_entry(up, &uhci->urb_list, urb_list) {
		struct urb *u = up->urb;

		spin_lock(&u->lock);

		/* Check if the FSBR timed out */
		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
			uhci_fsbr_timeout(uhci, u);

		spin_unlock(&u->lock);
	}

static int start_hc(struct uhci_hcd *uhci)
	/* Really disable FSBR */
	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
		uhci->fsbrtimeout = 0;
		uhci->skel_term_qh->link = UHCI_PTR_TERM;
	}

	/* Poll for and perform state transitions */
	hc_state_transitions(uhci);
	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
		uhci_check_ports(uhci);

	init_stall_timer(hcd);
	spin_unlock_irqrestore(&uhci->lock, flags);
}

static int init_stall_timer(struct usb_hcd *hcd)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);

	init_timer(&uhci->stall_timer);
	uhci->stall_timer.function = stall_callback;
	uhci->stall_timer.data = (unsigned long)hcd;
	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
	add_timer(&uhci->stall_timer);

	return 0;
}

static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	unsigned long io_addr = uhci->io_addr;
	int timeout = 10;
	unsigned short status;

	/*
	 * Reset the HC - this will force us to get a
	 * new notification of any already connected
	 * ports due to the virtual disconnect that it
	 * implies.
	 * Read the interrupt status, and write it back to clear the
	 * interrupt cause.  Contrary to the UHCI specification, the
	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
	 */
	outw(USBCMD_HCRESET, io_addr + USBCMD);
	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
		if (--timeout < 0) {
			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
			return -ETIMEDOUT;
	status = inw(io_addr + USBSTS);
	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
		return IRQ_NONE;
	outw(status, io_addr + USBSTS);		/* Clear it */

	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
		if (status & USBSTS_HSE)
			dev_err(uhci_dev(uhci), "host system error, "
					"PCI problems?\n");
		if (status & USBSTS_HCPE)
			dev_err(uhci_dev(uhci), "host controller process "
					"error, something bad happened!\n");
		if ((status & USBSTS_HCH) && uhci->state > 0) {
			dev_err(uhci_dev(uhci), "host controller halted, "
					"very bad!\n");
			/* FIXME: Reset the controller, fix the offending TD */
		}
		msleep(1);
	}

	/* Mark controller as running before we enable interrupts */
	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;

	/* Turn on PIRQ and all interrupts */
	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
			USBLEGSUP_DEFAULT);
	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
		io_addr + USBINTR);
	if (status & USBSTS_RD)
		uhci->resume_detect = 1;

	/* Start at frame 0 */
	outw(0, io_addr + USBFRNUM);
	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
	spin_lock(&uhci->lock);
	uhci_scan_schedule(uhci, regs);
	spin_unlock(&uhci->lock);

	/* Run and mark it configured with a 64-byte max packet */
	uhci->state = UHCI_RUNNING_GRACE;
	uhci->state_end = jiffies + HZ;
	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
	uhci->is_stopped = 0;
	return IRQ_HANDLED;
}

	return 0;
/*
 * Store the current frame number in uhci->frame_number if the controller
 * is runnning
 */
static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
{
	if (!uhci->is_stopped)
		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
}

/*