static void uhci_check_ports(struct uhci_hcd *uhci) { unsigned int port; unsigned long port_addr; int status; for (port = 0; port < uhci->rh_numports; ++port) { port_addr = USBPORTSC1 + 2 * port; status = uhci_readw(uhci, port_addr); if (unlikely(status & USBPORTSC_PR)) { if (time_after_eq(jiffies, uhci->ports_timeout)) { CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); /* HP's server management chip requires * a longer delay. */ if (uhci->wait_for_hp) wait_for_HP(uhci, port_addr); /* If the port was enabled before, turning * reset on caused a port enable change. * Turning reset off causes a port connect * status change. Clear these changes. */ CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC); SET_RH_PORTSTAT(USBPORTSC_PE); } } if (unlikely(status & USBPORTSC_RD)) { if (!test_bit(port, &uhci->resuming_ports)) { /* Port received a wakeup request */ set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + msecs_to_jiffies(USB_RESUME_TIMEOUT); usb_hcd_start_port_resume( &uhci_to_hcd(uhci)->self, port); /* Make sure we see the port again * after the resuming period is over. */ mod_timer(&uhci_to_hcd(uhci)->rh_timer, uhci->ports_timeout); } else if (time_after_eq(jiffies, uhci->ports_timeout)) { uhci_finish_suspend(uhci, port, port_addr); } } } }
/* * Store the basic register settings needed by the controller. */ static void configure_hc(struct uhci_hcd *uhci) { struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); /* Set the frame length to the default: 1 ms exactly */ outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); /* Store the frame list base address */ outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); /* Set the current frame number */ outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, uhci->io_addr + USBFRNUM); /* Mark controller as not halted before we enable interrupts */ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; mb(); /* Enable PIRQ */ pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); /* Disable platform-specific non-PME# wakeup */ if (pdev->vendor == PCI_VENDOR_ID_INTEL) pci_write_config_byte(pdev, USBRES_INTEL, 0); }
/* UHCI controllers don't automatically stop resume signalling after 20 msec, * so we have to poll and check timeouts in order to take care of it. */ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, unsigned long port_addr) { int status; int i; if (uhci_readw(uhci, port_addr) & SUSPEND_BITS) { CLR_RH_PORTSTAT(SUSPEND_BITS); if (test_bit(port, &uhci->resuming_ports)) set_bit(port, &uhci->port_c_suspend); /* The controller won't actually turn off the RD bit until * it has had a chance to send a low-speed EOP sequence, * which is supposed to take 3 bit times (= 2 microseconds). * Experiments show that some controllers take longer, so * we'll poll for completion. */ for (i = 0; i < 10; ++i) { if (!(uhci_readw(uhci, port_addr) & SUSPEND_BITS)) break; udelay(1); } } clear_bit(port, &uhci->resuming_ports); usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port); }
/* * Make sure the controller is completely inactive, unable to * generate interrupts or do DMA. */ static void reset_hc(struct uhci_hcd *uhci) { int port; int timeout = 10; /* Turn off PIRQ enable and SMI enable. (This also turns off the * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, USBLEGSUP_RWC); /* 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, uhci->io_addr + USBCMD); mb(); udelay(5); while (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) { if (--timeout < 0) { dev_warn(uhci_dev(uhci), "HCRESET timed out!\n"); break; } udelay(5); } /* Just to be safe, disable interrupt requests and * make sure the controller is stopped. */ outw(0, uhci->io_addr + USBINTR); outw(0, uhci->io_addr + USBCMD); /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect * bits in the port status and control registers. * We have to clear them by hand. */ for (port = 0; port < uhci->rh_numports; ++port) outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); uhci->port_c_suspend = uhci->suspended_ports = uhci->resuming_ports = 0; uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->poll_rh = 0; }
/* * Finish up a host controller reset and update the recorded state. */ static void finish_reset(struct uhci_hcd *uhci) { int port; /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect * bits in the port status and control registers. * We have to clear them by hand. */ for (port = 0; port < uhci->rh_numports; ++port) outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); uhci->port_c_suspend = uhci->resuming_ports = 0; uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->poll_rh = 0; }
/* * Finish up a host controller reset and update the recorded state. */ static void finish_reset(struct uhci_hcd *uhci) { int port; /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect * bits in the port status and control registers. * We have to clear them by hand. */ for (port = 0; port < uhci->rh_numports; ++port) writew(0, &uhci->regs[port]); uhci->port_c_suspend = uhci->resuming_ports = 0; uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->poll_rh = 0; uhci->dead = 0; /* Full reset resurrects the controller */ }
/* * Finish up a host controller reset and update the recorded state. */ static void finish_reset(struct uhci_hcd *uhci) { int port; /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect * bits in the port status and control registers. * We have to clear them by hand. */ for (port = 0; port < uhci->rh_numports; ++port) uhci_writew(uhci, 0, USBPORTSC1 + (port * 2)); uhci->port_c_suspend = uhci->resuming_ports = 0; uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); }
/* * Store the basic register settings needed by the controller. */ static void configure_hc(struct uhci_hcd *uhci) { /* Set the frame length to the default: 1 ms exactly */ writew(USBSOF_DEFAULT, &uhci->regs->sofmod); /* Store the frame list base address */ writel(uhci->frame_dma_handle, &uhci->regs->flbaseadd); /* Set the current frame number */ writew(uhci->frame_number & UHCI_MAX_SOF_NUMBER, &uhci->regs->frnum); /* Mark controller as not halted before we enable interrupts */ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; mb(); }
static void finish_reset(struct uhci_hcd *uhci) { int port; /* */ for (port = 0; port < uhci->rh_numports; ++port) uhci_writew(uhci, 0, USBPORTSC1 + (port * 2)); uhci->port_c_suspend = uhci->resuming_ports = 0; uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); }
static void uhci_check_ports(struct uhci_hcd *uhci) { unsigned int port; unsigned long port_addr; int status; for (port = 0; port < uhci->rh_numports; ++port) { port_addr = USBPORTSC1 + 2 * port; status = uhci_readw(uhci, port_addr); if (unlikely(status & USBPORTSC_PR)) { if (time_after_eq(jiffies, uhci->ports_timeout)) { CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); /* */ if (uhci->wait_for_hp) wait_for_HP(uhci, port_addr); /* */ CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC); SET_RH_PORTSTAT(USBPORTSC_PE); } } if (unlikely(status & USBPORTSC_RD)) { if (!test_bit(port, &uhci->resuming_ports)) { /* */ set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + msecs_to_jiffies(25); /* */ mod_timer(&uhci_to_hcd(uhci)->rh_timer, uhci->ports_timeout); } else if (time_after_eq(jiffies, uhci->ports_timeout)) { uhci_finish_suspend(uhci, port, port_addr); } } } }
/* * Store the basic register settings needed by the controller. */ static void configure_hc(struct uhci_hcd *uhci) { /* Set the frame length to the default: 1 ms exactly */ outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); /* Store the frame list base address */ outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); /* Set the current frame number */ outw(uhci->frame_number, uhci->io_addr + USBFRNUM); /* Mark controller as running before we enable interrupts */ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; mb(); /* Enable PIRQ */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, USBLEGSUP_DEFAULT); }
uhci->resume_detect_interrupts_are_broken(uhci) : 0; } static int global_suspend_mode_is_broken(struct uhci_hcd *uhci) { return uhci->global_suspend_mode_is_broken ? uhci->global_suspend_mode_is_broken(uhci) : 0; } static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) __releases(uhci->lock) __acquires(uhci->lock) { int auto_stop; int int_enable, egsm_enable, wakeup_enable; struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub; auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); dev_dbg(&rhdev->dev, "%s%s\n", __func__, (auto_stop ? " (auto-stop)" : "")); /* Start off by assuming Resume-Detect interrupts and EGSM work * and that remote wakeups should be enabled. */ egsm_enable = USBCMD_EGSM; uhci->RD_enable = 1; int_enable = USBINTR_RESUME; wakeup_enable = 1; /* In auto-stop mode wakeups must always be detected, but * Resume-Detect interrupts may be prohibited. (In the absence
static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); }
return 1; } } return 0; } static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) __releases(uhci->lock) __acquires(uhci->lock) { int auto_stop; int int_enable, egsm_enable; auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, "%s%s\n", __FUNCTION__, (auto_stop ? " (auto-stop)" : "")); /* If we get a suspend request when we're already auto-stopped * then there's nothing to do. */ if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) { uhci->rh_state = new_state; return; } /* Enable resume-detect interrupts if they work. * Then enter Global Suspend mode if _it_ works, still configured. */ egsm_enable = USBCMD_EGSM;