diff options
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 124 |
1 files changed, 91 insertions, 33 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c020b094fe7..2a5d45b4cb1 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -491,7 +491,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) * Systems: * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 */ -bool xhci_compliance_mode_recovery_timer_quirk_check(void) +static bool xhci_compliance_mode_recovery_timer_quirk_check(void) { const char *dmi_product_name, *dmi_sys_vendor; @@ -653,6 +653,7 @@ int xhci_run(struct usb_hcd *hcd) "Finished xhci_run for USB2 roothub"); return 0; } +EXPORT_SYMBOL_GPL(xhci_run); static void xhci_only_stop_hcd(struct usb_hcd *hcd) { @@ -871,6 +872,8 @@ int xhci_suspend(struct xhci_hcd *xhci) xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -927,6 +930,7 @@ int xhci_suspend(struct xhci_hcd *xhci) return rc; } +EXPORT_SYMBOL_GPL(xhci_suspend); /* * start xHC (not bus-specific) @@ -1075,9 +1079,12 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "%s: starting port polling.\n", __func__); set_bit(HCD_FLAG_POLL_RH, &hcd->flags); usb_hcd_poll_rh_status(hcd); + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + usb_hcd_poll_rh_status(xhci->shared_hcd); return retval; } +EXPORT_SYMBOL_GPL(xhci_resume); #endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ @@ -2887,14 +2894,9 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, * issue a configure endpoint command later. */ if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) { - struct xhci_command *command; - /* Can't sleep if we're called from cleanup_halted_endpoint() */ - command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); - if (!command) - return; xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, "Queueing new dequeue state"); - xhci_queue_new_dequeue_state(xhci, command, udev->slot_id, + xhci_queue_new_dequeue_state(xhci, udev->slot_id, ep_index, ep->stopped_stream, &deq_state); } else { /* Better hope no one uses the input context between now and the @@ -3761,8 +3763,8 @@ disable_slot: /* * Issue an Address Device command and optionally send a corresponding * SetAddress request to the device. - * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so - * we should only issue and wait on one address command at the same time. + * We should be protected by the usb_address0_mutex in hub_wq's hub_port_init, + * so we should only issue and wait on one address command at the same time. */ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, enum xhci_setup_dev setup) @@ -3971,13 +3973,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, int ret; spin_lock_irqsave(&xhci->lock, flags); - if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { + + virt_dev = xhci->devs[udev->slot_id]; + + /* + * virt_dev might not exists yet if xHC resumed from hibernate (S4) and + * xHC was re-initialized. Exit latency will be set later after + * hub_port_finish_reset() is done and xhci->devs[] are re-allocated + */ + + if (!virt_dev || max_exit_latency == virt_dev->current_mel) { spin_unlock_irqrestore(&xhci->lock, flags); return 0; } /* Attempt to issue an Evaluate Context command to change the MEL. */ - virt_dev = xhci->devs[udev->slot_id]; command = xhci->lpm_command; ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); if (!ctrl_ctx) { @@ -4895,6 +4905,76 @@ error: kfree(xhci); return retval; } +EXPORT_SYMBOL_GPL(xhci_gen_setup); + +static const struct hc_driver xhci_hc_driver = { + .description = "xhci-hcd", + .product_desc = "xHCI Host Controller", + .hcd_priv_size = sizeof(struct xhci_hcd *), + + /* + * generic hardware linkage + */ + .irq = xhci_irq, + .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, + + /* + * basic lifecycle operations + */ + .reset = NULL, /* set in xhci_init_driver() */ + .start = xhci_run, + .stop = xhci_stop, + .shutdown = xhci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = xhci_urb_enqueue, + .urb_dequeue = xhci_urb_dequeue, + .alloc_dev = xhci_alloc_dev, + .free_dev = xhci_free_dev, + .alloc_streams = xhci_alloc_streams, + .free_streams = xhci_free_streams, + .add_endpoint = xhci_add_endpoint, + .drop_endpoint = xhci_drop_endpoint, + .endpoint_reset = xhci_endpoint_reset, + .check_bandwidth = xhci_check_bandwidth, + .reset_bandwidth = xhci_reset_bandwidth, + .address_device = xhci_address_device, + .enable_device = xhci_enable_device, + .update_hub_device = xhci_update_hub_device, + .reset_device = xhci_discover_or_reset_device, + + /* + * scheduling support + */ + .get_frame_number = xhci_get_frame, + + /* + * root hub support + */ + .hub_control = xhci_hub_control, + .hub_status_data = xhci_hub_status_data, + .bus_suspend = xhci_bus_suspend, + .bus_resume = xhci_bus_resume, + + /* + * call back when device connected and addressed + */ + .update_device = xhci_update_device, + .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, + .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, + .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, + .find_raw_port_number = xhci_find_raw_port_number, +}; + +void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)) +{ + BUG_ON(!setup_fn); + *drv = xhci_hc_driver; + drv->reset = setup_fn; +} +EXPORT_SYMBOL_GPL(xhci_init_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR(DRIVER_AUTHOR); @@ -4902,18 +4982,6 @@ MODULE_LICENSE("GPL"); static int __init xhci_hcd_init(void) { - int retval; - - retval = xhci_register_pci(); - if (retval < 0) { - pr_debug("Problem registering PCI driver.\n"); - return retval; - } - retval = xhci_register_plat(); - if (retval < 0) { - pr_debug("Problem registering platform driver.\n"); - goto unreg_pci; - } /* * Check the compiler generated sizes of structures that must be laid * out in specific ways for hardware access. @@ -4932,15 +5000,5 @@ static int __init xhci_hcd_init(void) /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */ BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8); return 0; -unreg_pci: - xhci_unregister_pci(); - return retval; } module_init(xhci_hcd_init); - -static void __exit xhci_hcd_cleanup(void) -{ - xhci_unregister_pci(); - xhci_unregister_plat(); -} -module_exit(xhci_hcd_cleanup); |