Commit e323de46 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] UHCI: remove hc_inaccessible flag

This patch (as706) removes the private hc_inaccessible flag from
uhci-hcd.  It's not needed because it conveys exactly the same
information as the generic HCD_FLAG_HW_ACCESSIBLE bit.

In its place goes a new flag recording whether the controller is dead.
The new code allows a complete device reset to resurrect a dead
controller (although usbcore doesn't yet implement such a facility).
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent be3cbc5f
...@@ -110,17 +110,23 @@ static void finish_reset(struct uhci_hcd *uhci) ...@@ -110,17 +110,23 @@ static void finish_reset(struct uhci_hcd *uhci)
uhci->is_stopped = UHCI_IS_STOPPED; uhci->is_stopped = UHCI_IS_STOPPED;
uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->state = HC_STATE_HALT;
uhci_to_hcd(uhci)->poll_rh = 0; uhci_to_hcd(uhci)->poll_rh = 0;
uhci->dead = 0; /* Full reset resurrects the controller */
} }
/* /*
* Last rites for a defunct/nonfunctional controller * Last rites for a defunct/nonfunctional controller
* or one we don't want to use any more. * or one we don't want to use any more.
*/ */
static void hc_died(struct uhci_hcd *uhci) static void uhci_hc_died(struct uhci_hcd *uhci)
{ {
uhci_get_current_frame_number(uhci);
uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
finish_reset(uhci); finish_reset(uhci);
uhci->hc_inaccessible = 1; uhci->dead = 1;
/* The current frame may already be partway finished */
++uhci->frame_number;
} }
/* /*
...@@ -234,7 +240,7 @@ __acquires(uhci->lock) ...@@ -234,7 +240,7 @@ __acquires(uhci->lock)
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
msleep(1); msleep(1);
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (uhci->hc_inaccessible) /* Died */ if (uhci->dead)
return; return;
} }
if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
...@@ -287,7 +293,7 @@ __acquires(uhci->lock) ...@@ -287,7 +293,7 @@ __acquires(uhci->lock)
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
msleep(20); msleep(20);
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (uhci->hc_inaccessible) /* Died */ if (uhci->dead)
return; return;
/* End Global Resume and wait for EOP to be sent */ /* End Global Resume and wait for EOP to be sent */
...@@ -339,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -339,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
errbuf, ERRBUF_LEN); errbuf, ERRBUF_LEN);
lprintk(errbuf); lprintk(errbuf);
} }
hc_died(uhci); uhci_hc_died(uhci);
/* Force a callback in case there are /* Force a callback in case there are
* pending unlinks */ * pending unlinks */
...@@ -462,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev) ...@@ -462,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev)
{ {
struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
hc_died(hcd_to_uhci(hcd)); uhci_hc_died(hcd_to_uhci(hcd));
} }
/* /*
...@@ -664,8 +670,8 @@ static void uhci_stop(struct usb_hcd *hcd) ...@@ -664,8 +670,8 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (!uhci->hc_inaccessible) if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
hc_died(uhci); uhci_hc_died(uhci);
uhci_scan_schedule(uhci, NULL); uhci_scan_schedule(uhci, NULL);
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
...@@ -681,7 +687,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) ...@@ -681,7 +687,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
rc = -ESHUTDOWN; rc = -ESHUTDOWN;
else if (!uhci->hc_inaccessible) else if (!uhci->dead)
suspend_rh(uhci, UHCI_RH_SUSPENDED); suspend_rh(uhci, UHCI_RH_SUSPENDED);
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
return rc; return rc;
...@@ -696,7 +702,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd) ...@@ -696,7 +702,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
rc = -ESHUTDOWN; rc = -ESHUTDOWN;
} else if (!uhci->hc_inaccessible) } else if (!uhci->dead)
wakeup_rh(uhci); wakeup_rh(uhci);
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
return rc; return rc;
...@@ -710,8 +716,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) ...@@ -710,8 +716,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (uhci->hc_inaccessible) /* Dead or already suspended */ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
goto done; goto done_okay; /* Already suspended or dead */
if (uhci->rh_state > UHCI_RH_SUSPENDED) { if (uhci->rh_state > UHCI_RH_SUSPENDED) {
dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
...@@ -724,12 +730,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) ...@@ -724,12 +730,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
*/ */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
mb(); mb();
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
uhci->hc_inaccessible = 1;
hcd->poll_rh = 0; hcd->poll_rh = 0;
/* FIXME: Enable non-PME# remote wakeup? */ /* FIXME: Enable non-PME# remote wakeup? */
done_okay:
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
done: done:
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
return rc; return rc;
...@@ -742,25 +748,22 @@ static int uhci_resume(struct usb_hcd *hcd) ...@@ -742,25 +748,22 @@ static int uhci_resume(struct usb_hcd *hcd)
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
/* Since we aren't in D3 any more, it's safe to set this flag /* Since we aren't in D3 any more, it's safe to set this flag
* even if the controller was dead. It might not even be dead * even if the controller was dead.
* any more, if the firmware or quirks code has reset it.
*/ */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb(); mb();
if (uhci->rh_state == UHCI_RH_RESET) /* Dead */
return 0;
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
/* FIXME: Disable non-PME# remote wakeup? */ /* FIXME: Disable non-PME# remote wakeup? */
uhci->hc_inaccessible = 0; /* The firmware or a boot kernel may have changed the controller
* settings during a system wakeup. Check it and reconfigure
/* The BIOS may have changed the controller settings during a * to avoid problems.
* system wakeup. Check it and reconfigure to avoid problems.
*/ */
check_and_reset_hc(uhci); check_and_reset_hc(uhci);
/* If the controller was dead before, it's back alive now */
configure_hc(uhci); configure_hc(uhci);
if (uhci->rh_state == UHCI_RH_RESET) { if (uhci->rh_state == UHCI_RH_RESET) {
......
...@@ -395,7 +395,7 @@ struct uhci_hcd { ...@@ -395,7 +395,7 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */ unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */ unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int hc_inaccessible:1; /* HC is suspended or dead */ unsigned int dead:1; /* Controller has died */
unsigned int working_RD:1; /* Suspended root hub doesn't unsigned int working_RD:1; /* Suspended root hub doesn't
need to be polled */ need to be polled */
unsigned int is_initialized:1; /* Data structure is usable */ unsigned int is_initialized:1; /* Data structure is usable */
......
...@@ -171,7 +171,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) ...@@ -171,7 +171,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
spin_lock_irqsave(&uhci->lock, flags); spin_lock_irqsave(&uhci->lock, flags);
uhci_scan_schedule(uhci, NULL); uhci_scan_schedule(uhci, NULL);
if (uhci->hc_inaccessible) if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
goto done; goto done;
uhci_check_ports(uhci); uhci_check_ports(uhci);
...@@ -227,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -227,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wPortChange, wPortStatus; u16 wPortChange, wPortStatus;
unsigned long flags; unsigned long flags;
if (uhci->hc_inaccessible) if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
return -ETIMEDOUT; return -ETIMEDOUT;
spin_lock_irqsave(&uhci->lock, flags); spin_lock_irqsave(&uhci->lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment