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

Commit 09ca8adb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Revert "USB: don't explicitly reenable root-hub status interrupts"

This reverts commit e8721549.

Andrey Borzenkov reports that it resulted in a totally hung machine for
him when loading the OHCI driver.  Extensive netconsole capture with
SysRq output shows that modprobe gets stuck in ohci_hub_status_data()
when probing and enabling the OHCI controller, see for example

	http://lkml.org/lkml/2008/7/5/236



for an analysis.

The problem appears to be an interrupt flood triggered by the commit
that gets reverted, and Andrey confirmed that the revert makes things
work for him again.

Reported-and-tested-by: default avatarAndrey Borzenkov <arvidjaar@mail.ru>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Acked-by: default avatarDavid Brownell <david-b@pacbell.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b7279469
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd)
	return retval;
}

void usb_enable_root_hub_irq (struct usb_bus *bus)
{
	struct usb_hcd *hcd;

	hcd = container_of (bus, struct usb_hcd, self);
	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
		hcd->driver->hub_irq_enable (hcd);
}


/*-------------------------------------------------------------------------*/

+2 −0
Original line number Diff line number Diff line
@@ -210,6 +210,8 @@ struct hc_driver {
	int	(*bus_suspend)(struct usb_hcd *);
	int	(*bus_resume)(struct usb_hcd *);
	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
	void	(*hub_irq_enable)(struct usb_hcd *);
		/* Needed only if port-change IRQs are level-triggered */

		/* force handover of high-speed port to full-speed companion */
	void	(*relinquish_port)(struct usb_hcd *, int);
+9 −0
Original line number Diff line number Diff line
@@ -2073,6 +2073,8 @@ int usb_port_resume(struct usb_device *udev)
	}

	clear_bit(port1, hub->busy_bits);
	if (!hub->hdev->parent && !hub->busy_bits[0])
		usb_enable_root_hub_irq(hub->hdev->bus);

	if (status == 0)
		status = finish_port_resume(udev);
@@ -3002,6 +3004,11 @@ static void hub_events(void)

		hub->activating = 0;

		/* If this is a root hub, tell the HCD it's okay to
		 * re-enable port-change interrupts now. */
		if (!hdev->parent && !hub->busy_bits[0])
			usb_enable_root_hub_irq(hdev->bus);

loop_autopm:
		/* Allow autosuspend if we're not going to run again */
		if (list_empty(&hub->event_list))
@@ -3227,6 +3234,8 @@ int usb_reset_device(struct usb_device *udev)
			break;
	}
	clear_bit(port1, parent_hub->busy_bits);
	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
		usb_enable_root_hub_irq(parent_hdev->bus);

	if (ret < 0)
		goto re_enumerate;
+1 −0
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
	 */
	.hub_status_data =	ohci_hub_status_data,
	.hub_control =		ohci_hub_control,
	.hub_irq_enable =	ohci_rhsc_enable,
#ifdef CONFIG_PM
	.bus_suspend =		ohci_bus_suspend,
	.bus_resume =		ohci_bus_resume,
+1 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
	 */
	.hub_status_data =	ohci_hub_status_data,
	.hub_control =		ohci_hub_control,
	.hub_irq_enable =	ohci_rhsc_enable,
#ifdef	CONFIG_PM
	.bus_suspend =		ohci_bus_suspend,
	.bus_resume =		ohci_bus_resume,
Loading