Merge tag 'usb-6.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are some USB driver fixes for 6.16-rc5. I originally wanted this to get into -rc4, but there were some regressions that had to be handled first. Now all looks good. Included in here are the following fixes: - cdns3 driver fixes - xhci driver fixes - typec driver fixes - USB hub fixes (this is what took the longest to get right) - new USB driver quirks added - chipidea driver fixes All of these have been in linux-next for a while and now we have no more reported problems with them" * tag 'usb-6.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits) usb: hub: Fix flushing of delayed work used for post resume purposes xhci: dbc: Flush queued requests before stopping dbc xhci: dbctty: disable ECHO flag by default xhci: Disable stream for xHC controller with XHCI_BROKEN_STREAMS usb: xhci: quirk for data loss in ISOC transfers usb: dwc3: gadget: Fix TRB reclaim logic for short transfers and ZLPs usb: hub: Fix flushing and scheduling of delayed work that tunes runtime pm usb: typec: displayport: Fix potential deadlock usb: typec: altmodes/displayport: do not index invalid pin_assignments usb: cdnsp: Fix issue with CV Bad Descriptor test usb: typec: tcpm: apply vbus before data bringup in tcpm_src_attach Revert "usb: xhci: Implement xhci_handshake_check_state() helper" usb: xhci: Skip xhci_reset in xhci_resume if xhci is being removed usb: gadget: u_serial: Fix race condition in TTY wakeup Revert "usb: gadget: u_serial: Add null pointer check in gs_start_io" usb: chipidea: udc: disconnect/reconnect from host when do suspend/resume usb: acpi: fix device link removal usb: hub: fix detection of high tier USB3 devices behind suspended hubs Logitech C-270 even more broken usb: dwc3: Abort suspend on soft disconnect failure ...
This commit is contained in:
@@ -327,12 +327,13 @@ static inline const char *cdnsp_decode_trb(char *str, size_t size, u32 field0,
|
||||
case TRB_RESET_EP:
|
||||
case TRB_HALT_ENDPOINT:
|
||||
ret = scnprintf(str, size,
|
||||
"%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c",
|
||||
"%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c %c",
|
||||
cdnsp_trb_type_string(type),
|
||||
ep_num, ep_id % 2 ? "out" : "in",
|
||||
TRB_TO_EP_INDEX(field3), field1, field0,
|
||||
TRB_TO_SLOT_ID(field3),
|
||||
field3 & TRB_CYCLE ? 'C' : 'c');
|
||||
field3 & TRB_CYCLE ? 'C' : 'c',
|
||||
field3 & TRB_ESP ? 'P' : 'p');
|
||||
break;
|
||||
case TRB_STOP_RING:
|
||||
ret = scnprintf(str, size,
|
||||
|
||||
@@ -414,6 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
|
||||
void cdnsp_setup_analyze(struct cdnsp_device *pdev)
|
||||
{
|
||||
struct usb_ctrlrequest *ctrl = &pdev->setup;
|
||||
struct cdnsp_ep *pep;
|
||||
int ret = -EINVAL;
|
||||
u16 len;
|
||||
|
||||
@@ -427,10 +428,21 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
pep = &pdev->eps[0];
|
||||
|
||||
/* Restore the ep0 to Stopped/Running state. */
|
||||
if (pdev->eps[0].ep_state & EP_HALTED) {
|
||||
trace_cdnsp_ep0_halted("Restore to normal state");
|
||||
cdnsp_halt_endpoint(pdev, &pdev->eps[0], 0);
|
||||
if (pep->ep_state & EP_HALTED) {
|
||||
if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED)
|
||||
cdnsp_halt_endpoint(pdev, pep, 0);
|
||||
|
||||
/*
|
||||
* Halt Endpoint Command for SSP2 for ep0 preserve current
|
||||
* endpoint state and driver has to synchronize the
|
||||
* software endpoint state with endpoint output context
|
||||
* state.
|
||||
*/
|
||||
pep->ep_state &= ~EP_HALTED;
|
||||
pep->ep_state |= EP_STOPPED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -987,6 +987,12 @@ enum cdnsp_setup_dev {
|
||||
#define STREAM_ID_FOR_TRB(p) ((((p)) << 16) & GENMASK(31, 16))
|
||||
#define SCT_FOR_TRB(p) (((p) << 1) & 0x7)
|
||||
|
||||
/*
|
||||
* Halt Endpoint Command TRB field.
|
||||
* The ESP bit only exists in the SSP2 controller.
|
||||
*/
|
||||
#define TRB_ESP BIT(9)
|
||||
|
||||
/* Link TRB specific fields. */
|
||||
#define TRB_TC BIT(1)
|
||||
|
||||
|
||||
@@ -772,7 +772,9 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
|
||||
}
|
||||
|
||||
if (port_id != old_port) {
|
||||
cdnsp_disable_slot(pdev);
|
||||
if (pdev->slot_id)
|
||||
cdnsp_disable_slot(pdev);
|
||||
|
||||
pdev->active_port = port;
|
||||
cdnsp_enable_slot(pdev);
|
||||
}
|
||||
@@ -2483,7 +2485,8 @@ void cdnsp_queue_halt_endpoint(struct cdnsp_device *pdev, unsigned int ep_index)
|
||||
{
|
||||
cdnsp_queue_command(pdev, 0, 0, 0, TRB_TYPE(TRB_HALT_ENDPOINT) |
|
||||
SLOT_ID_FOR_TRB(pdev->slot_id) |
|
||||
EP_ID_FOR_TRB(ep_index));
|
||||
EP_ID_FOR_TRB(ep_index) |
|
||||
(!ep_index ? TRB_ESP : 0));
|
||||
}
|
||||
|
||||
void cdnsp_force_header_wakeup(struct cdnsp_device *pdev, int intf_num)
|
||||
|
||||
@@ -2374,6 +2374,10 @@ static void udc_suspend(struct ci_hdrc *ci)
|
||||
*/
|
||||
if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
|
||||
hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
|
||||
|
||||
if (ci->gadget.connected &&
|
||||
(!ci->suspended || !device_may_wakeup(ci->dev)))
|
||||
usb_gadget_disconnect(&ci->gadget);
|
||||
}
|
||||
|
||||
static void udc_resume(struct ci_hdrc *ci, bool power_lost)
|
||||
@@ -2384,6 +2388,9 @@ static void udc_resume(struct ci_hdrc *ci, bool power_lost)
|
||||
OTGSC_BSVIS | OTGSC_BSVIE);
|
||||
if (ci->vbus_active)
|
||||
usb_gadget_vbus_disconnect(&ci->gadget);
|
||||
} else if (ci->vbus_active && ci->driver &&
|
||||
!ci->gadget.connected) {
|
||||
usb_gadget_connect(&ci->gadget);
|
||||
}
|
||||
|
||||
/* Restore value 0 if it was set for power lost check */
|
||||
|
||||
@@ -68,6 +68,12 @@
|
||||
*/
|
||||
#define USB_SHORT_SET_ADDRESS_REQ_TIMEOUT 500 /* ms */
|
||||
|
||||
/*
|
||||
* Give SS hubs 200ms time after wake to train downstream links before
|
||||
* assuming no port activity and allowing hub to runtime suspend back.
|
||||
*/
|
||||
#define USB_SS_PORT_U0_WAKE_TIME 200 /* ms */
|
||||
|
||||
/* Protect struct usb_device->state and ->children members
|
||||
* Note: Both are also protected by ->dev.sem, except that ->state can
|
||||
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
|
||||
@@ -1095,6 +1101,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
goto init2;
|
||||
goto init3;
|
||||
}
|
||||
|
||||
hub_get(hub);
|
||||
|
||||
/* The superspeed hub except for root hub has to use Hub Depth
|
||||
@@ -1343,6 +1350,17 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
device_unlock(&hdev->dev);
|
||||
}
|
||||
|
||||
if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) {
|
||||
/* give usb3 downstream links training time after hub resume */
|
||||
usb_autopm_get_interface_no_resume(
|
||||
to_usb_interface(hub->intfdev));
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->post_resume_work,
|
||||
msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME));
|
||||
return;
|
||||
}
|
||||
|
||||
hub_put(hub);
|
||||
}
|
||||
|
||||
@@ -1361,6 +1379,14 @@ static void hub_init_func3(struct work_struct *ws)
|
||||
hub_activate(hub, HUB_INIT3);
|
||||
}
|
||||
|
||||
static void hub_post_resume(struct work_struct *ws)
|
||||
{
|
||||
struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work);
|
||||
|
||||
usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
|
||||
hub_put(hub);
|
||||
}
|
||||
|
||||
enum hub_quiescing_type {
|
||||
HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
|
||||
};
|
||||
@@ -1386,6 +1412,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
|
||||
|
||||
/* Stop hub_wq and related activity */
|
||||
timer_delete_sync(&hub->irq_urb_retry);
|
||||
flush_delayed_work(&hub->post_resume_work);
|
||||
usb_kill_urb(hub->urb);
|
||||
if (hub->has_indicators)
|
||||
cancel_delayed_work_sync(&hub->leds);
|
||||
@@ -1944,6 +1971,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
hub->hdev = hdev;
|
||||
INIT_DELAYED_WORK(&hub->leds, led_work);
|
||||
INIT_DELAYED_WORK(&hub->init_work, NULL);
|
||||
INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume);
|
||||
INIT_WORK(&hub->events, hub_event);
|
||||
INIT_LIST_HEAD(&hub->onboard_devs);
|
||||
spin_lock_init(&hub->irq_urb_lock);
|
||||
@@ -2337,6 +2365,9 @@ void usb_disconnect(struct usb_device **pdev)
|
||||
usb_remove_ep_devs(&udev->ep0);
|
||||
usb_unlock_device(udev);
|
||||
|
||||
if (udev->usb4_link)
|
||||
device_link_del(udev->usb4_link);
|
||||
|
||||
/* Unregister the device. The device driver is responsible
|
||||
* for de-configuring the device and invoking the remove-device
|
||||
* notifier chain (used by usbfs and possibly others).
|
||||
|
||||
@@ -70,6 +70,7 @@ struct usb_hub {
|
||||
u8 indicator[USB_MAXCHILDREN];
|
||||
struct delayed_work leds;
|
||||
struct delayed_work init_work;
|
||||
struct delayed_work post_resume_work;
|
||||
struct work_struct events;
|
||||
spinlock_t irq_urb_lock;
|
||||
struct timer_list irq_urb_retry;
|
||||
|
||||
@@ -227,7 +227,8 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* Logitech HD Webcam C270 */
|
||||
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME |
|
||||
USB_QUIRK_NO_LPM},
|
||||
|
||||
/* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */
|
||||
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
|
||||
@@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
|
||||
*/
|
||||
static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
|
||||
{
|
||||
const struct device_link *link;
|
||||
struct device_link *link;
|
||||
struct usb_port *port_dev;
|
||||
struct usb_hub *hub;
|
||||
|
||||
@@ -188,6 +188,8 @@ static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
|
||||
dev_dbg(&port_dev->dev, "Created device link from %s to %s\n",
|
||||
dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev));
|
||||
|
||||
udev->usb4_link = link;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2422,6 +2422,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
{
|
||||
u32 reg;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) {
|
||||
dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
|
||||
@@ -2440,7 +2441,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
if (pm_runtime_suspended(dwc->dev))
|
||||
break;
|
||||
dwc3_gadget_suspend(dwc);
|
||||
ret = dwc3_gadget_suspend(dwc);
|
||||
if (ret)
|
||||
return ret;
|
||||
synchronize_irq(dwc->irq_gadget);
|
||||
dwc3_core_exit(dwc);
|
||||
break;
|
||||
@@ -2475,7 +2478,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
break;
|
||||
|
||||
if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
|
||||
dwc3_gadget_suspend(dwc);
|
||||
ret = dwc3_gadget_suspend(dwc);
|
||||
if (ret)
|
||||
return ret;
|
||||
synchronize_irq(dwc->irq_gadget);
|
||||
}
|
||||
|
||||
|
||||
+10
-14
@@ -3516,7 +3516,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
|
||||
* We're going to do that here to avoid problems of HW trying
|
||||
* to use bogus TRBs for transfers.
|
||||
*/
|
||||
if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO))
|
||||
if (trb->ctrl & DWC3_TRB_CTRL_HWO)
|
||||
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
|
||||
|
||||
/*
|
||||
@@ -4821,8 +4821,15 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
|
||||
int ret;
|
||||
|
||||
ret = dwc3_gadget_soft_disconnect(dwc);
|
||||
if (ret)
|
||||
goto err;
|
||||
/*
|
||||
* Attempt to reset the controller's state. Likely no
|
||||
* communication can be established until the host
|
||||
* performs a port reset.
|
||||
*/
|
||||
if (ret && dwc->softconnect) {
|
||||
dwc3_gadget_soft_connect(dwc);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
if (dwc->gadget_driver)
|
||||
@@ -4830,17 +4837,6 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/*
|
||||
* Attempt to reset the controller's state. Likely no
|
||||
* communication can be established until the host
|
||||
* performs a port reset.
|
||||
*/
|
||||
if (dwc->softconnect)
|
||||
dwc3_gadget_soft_connect(dwc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dwc3_gadget_resume(struct dwc3 *dwc)
|
||||
|
||||
@@ -295,8 +295,8 @@ __acquires(&port->port_lock)
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_tty_wake && port->port.tty)
|
||||
tty_wakeup(port->port.tty);
|
||||
if (do_tty_wake)
|
||||
tty_port_tty_wakeup(&port->port);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -544,20 +544,16 @@ static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
|
||||
static int gs_start_io(struct gs_port *port)
|
||||
{
|
||||
struct list_head *head = &port->read_pool;
|
||||
struct usb_ep *ep;
|
||||
struct usb_ep *ep = port->port_usb->out;
|
||||
int status;
|
||||
unsigned started;
|
||||
|
||||
if (!port->port_usb || !port->port.tty)
|
||||
return -EIO;
|
||||
|
||||
/* Allocate RX and TX I/O buffers. We can't easily do this much
|
||||
* earlier (with GFP_KERNEL) because the requests are coupled to
|
||||
* endpoints, as are the packet sizes we'll be using. Different
|
||||
* configurations may use different endpoints with a given port;
|
||||
* and high speed vs full speed changes packet sizes too.
|
||||
*/
|
||||
ep = port->port_usb->out;
|
||||
status = gs_alloc_requests(ep, head, gs_read_complete,
|
||||
&port->read_allocated);
|
||||
if (status)
|
||||
@@ -578,7 +574,7 @@ static int gs_start_io(struct gs_port *port)
|
||||
gs_start_tx(port);
|
||||
/* Unblock any pending writes into our circular buffer, in case
|
||||
* we didn't in gs_start_tx() */
|
||||
tty_wakeup(port->port.tty);
|
||||
tty_port_tty_wakeup(&port->port);
|
||||
} else {
|
||||
/* Free reqs only if we are still connected */
|
||||
if (port->port_usb) {
|
||||
|
||||
@@ -652,6 +652,10 @@ static void xhci_dbc_stop(struct xhci_dbc *dbc)
|
||||
case DS_DISABLED:
|
||||
return;
|
||||
case DS_CONFIGURED:
|
||||
spin_lock(&dbc->lock);
|
||||
xhci_dbc_flush_requests(dbc);
|
||||
spin_unlock(&dbc->lock);
|
||||
|
||||
if (dbc->driver->disconnect)
|
||||
dbc->driver->disconnect(dbc);
|
||||
break;
|
||||
|
||||
@@ -617,6 +617,7 @@ int dbc_tty_init(void)
|
||||
dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
dbc_tty_driver->init_termios = tty_std_termios;
|
||||
dbc_tty_driver->init_termios.c_lflag &= ~ECHO;
|
||||
dbc_tty_driver->init_termios.c_cflag =
|
||||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
dbc_tty_driver->init_termios.c_ispeed = 9600;
|
||||
|
||||
@@ -1449,6 +1449,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
||||
/* Periodic endpoint bInterval limit quirk */
|
||||
if (usb_endpoint_xfer_int(&ep->desc) ||
|
||||
usb_endpoint_xfer_isoc(&ep->desc)) {
|
||||
if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_9) &&
|
||||
interval >= 9) {
|
||||
interval = 8;
|
||||
}
|
||||
if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) &&
|
||||
udev->speed >= USB_SPEED_HIGH &&
|
||||
interval >= 7) {
|
||||
|
||||
@@ -71,12 +71,22 @@
|
||||
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI 0x15ec
|
||||
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI 0x15f0
|
||||
|
||||
#define PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI 0x13ed
|
||||
#define PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI 0x13ee
|
||||
#define PCI_DEVICE_ID_AMD_STARSHIP_XHCI 0x148c
|
||||
#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI 0x15d4
|
||||
#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI 0x15d5
|
||||
#define PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI 0x15e0
|
||||
#define PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI 0x15e1
|
||||
#define PCI_DEVICE_ID_AMD_RAVEN2_XHCI 0x15e5
|
||||
#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
|
||||
|
||||
#define PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI 0x7316
|
||||
|
||||
#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042
|
||||
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
|
||||
#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242
|
||||
@@ -280,6 +290,21 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
if (pdev->vendor == PCI_VENDOR_ID_NEC)
|
||||
xhci->quirks |= XHCI_NEC_HOST;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
(pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_STARSHIP_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_RAVEN2_XHCI))
|
||||
xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ATI &&
|
||||
pdev->device == PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI)
|
||||
xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96)
|
||||
xhci->quirks |= XHCI_AMD_0x96_HOST;
|
||||
|
||||
|
||||
@@ -328,7 +328,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
|
||||
}
|
||||
|
||||
usb3_hcd = xhci_get_usb3_hcd(xhci);
|
||||
if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
||||
if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
|
||||
!(xhci->quirks & XHCI_BROKEN_STREAMS))
|
||||
usb3_hcd->can_do_streams = 1;
|
||||
|
||||
if (xhci->shared_hcd) {
|
||||
|
||||
@@ -518,9 +518,8 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
|
||||
* In the future we should distinguish between -ENODEV and -ETIMEDOUT
|
||||
* and try to recover a -ETIMEDOUT with a host controller reset.
|
||||
*/
|
||||
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
|
||||
CMD_RING_RUNNING, 0, 5 * 1000 * 1000,
|
||||
XHCI_STATE_REMOVING);
|
||||
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
|
||||
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
|
||||
if (ret < 0) {
|
||||
xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
|
||||
xhci_halt(xhci);
|
||||
|
||||
+5
-26
@@ -84,29 +84,6 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* xhci_handshake_check_state - same as xhci_handshake but takes an additional
|
||||
* exit_state parameter, and bails out with an error immediately when xhc_state
|
||||
* has exit_state flag set.
|
||||
*/
|
||||
int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
u32 mask, u32 done, int usec, unsigned int exit_state)
|
||||
{
|
||||
u32 result;
|
||||
int ret;
|
||||
|
||||
ret = readl_poll_timeout_atomic(ptr, result,
|
||||
(result & mask) == done ||
|
||||
result == U32_MAX ||
|
||||
xhci->xhc_state & exit_state,
|
||||
1, usec);
|
||||
|
||||
if (result == U32_MAX || xhci->xhc_state & exit_state)
|
||||
return -ENODEV;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable interrupts and begin the xHCI halting process.
|
||||
*/
|
||||
@@ -227,8 +204,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
|
||||
if (xhci->quirks & XHCI_INTEL_HOST)
|
||||
udelay(1000);
|
||||
|
||||
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
|
||||
CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING);
|
||||
ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1182,7 +1158,10 @@ int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume)
|
||||
xhci_dbg(xhci, "Stop HCD\n");
|
||||
xhci_halt(xhci);
|
||||
xhci_zero_64b_regs(xhci);
|
||||
retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
|
||||
if (xhci->xhc_state & XHCI_STATE_REMOVING)
|
||||
retval = -ENODEV;
|
||||
else
|
||||
retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
@@ -1643,6 +1643,7 @@ struct xhci_hcd {
|
||||
#define XHCI_WRITE_64_HI_LO BIT_ULL(47)
|
||||
#define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48)
|
||||
#define XHCI_ETRON_HOST BIT_ULL(49)
|
||||
#define XHCI_LIMIT_ENDPOINT_INTERVAL_9 BIT_ULL(50)
|
||||
|
||||
unsigned int num_active_eps;
|
||||
unsigned int limit_active_eps;
|
||||
@@ -1868,8 +1869,6 @@ void xhci_skip_sec_intr_events(struct xhci_hcd *xhci,
|
||||
/* xHCI host controller glue */
|
||||
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
|
||||
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us);
|
||||
int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
u32 mask, u32 done, int usec, unsigned int exit_state);
|
||||
void xhci_quiesce(struct xhci_hcd *xhci);
|
||||
int xhci_halt(struct xhci_hcd *xhci);
|
||||
int xhci_start(struct xhci_hcd *xhci);
|
||||
|
||||
@@ -394,8 +394,7 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
|
||||
case CMDT_RSP_NAK:
|
||||
switch (cmd) {
|
||||
case DP_CMD_STATUS_UPDATE:
|
||||
if (typec_altmode_exit(alt))
|
||||
dev_err(&dp->alt->dev, "Exit Mode Failed!\n");
|
||||
dp->state = DP_STATE_EXIT;
|
||||
break;
|
||||
case DP_CMD_CONFIGURE:
|
||||
dp->data.conf = 0;
|
||||
@@ -677,7 +676,7 @@ static ssize_t pin_assignment_show(struct device *dev,
|
||||
|
||||
assignments = get_current_pin_assignments(dp);
|
||||
|
||||
for (i = 0; assignments; assignments >>= 1, i++) {
|
||||
for (i = 0; assignments && i < DP_PIN_ASSIGN_MAX; assignments >>= 1, i++) {
|
||||
if (assignments & 1) {
|
||||
if (i == cur)
|
||||
len += sprintf(buf + len, "[%s] ",
|
||||
|
||||
@@ -4410,17 +4410,6 @@ static int tcpm_src_attach(struct tcpm_port *port)
|
||||
|
||||
tcpm_enable_auto_vbus_discharge(port, true);
|
||||
|
||||
ret = tcpm_set_roles(port, true, TYPEC_STATE_USB,
|
||||
TYPEC_SOURCE, tcpm_data_role_for_source(port));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (port->pd_supported) {
|
||||
ret = port->tcpc->set_pd_rx(port->tcpc, true);
|
||||
if (ret < 0)
|
||||
goto out_disable_mux;
|
||||
}
|
||||
|
||||
/*
|
||||
* USB Type-C specification, version 1.2,
|
||||
* chapter 4.5.2.2.8.1 (Attached.SRC Requirements)
|
||||
@@ -4430,13 +4419,24 @@ static int tcpm_src_attach(struct tcpm_port *port)
|
||||
(polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) {
|
||||
ret = tcpm_set_vconn(port, true);
|
||||
if (ret < 0)
|
||||
goto out_disable_pd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tcpm_set_vbus(port, true);
|
||||
if (ret < 0)
|
||||
goto out_disable_vconn;
|
||||
|
||||
ret = tcpm_set_roles(port, true, TYPEC_STATE_USB, TYPEC_SOURCE,
|
||||
tcpm_data_role_for_source(port));
|
||||
if (ret < 0)
|
||||
goto out_disable_vbus;
|
||||
|
||||
if (port->pd_supported) {
|
||||
ret = port->tcpc->set_pd_rx(port->tcpc, true);
|
||||
if (ret < 0)
|
||||
goto out_disable_mux;
|
||||
}
|
||||
|
||||
port->pd_capable = false;
|
||||
|
||||
port->partner = NULL;
|
||||
@@ -4447,14 +4447,14 @@ static int tcpm_src_attach(struct tcpm_port *port)
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_vconn:
|
||||
tcpm_set_vconn(port, false);
|
||||
out_disable_pd:
|
||||
if (port->pd_supported)
|
||||
port->tcpc->set_pd_rx(port->tcpc, false);
|
||||
out_disable_mux:
|
||||
tcpm_mux_set(port, TYPEC_STATE_SAFE, USB_ROLE_NONE,
|
||||
TYPEC_ORIENTATION_NONE);
|
||||
out_disable_vbus:
|
||||
tcpm_set_vbus(port, false);
|
||||
out_disable_vconn:
|
||||
tcpm_set_vconn(port, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -614,6 +614,7 @@ struct usb3_lpm_parameters {
|
||||
* FIXME -- complete doc
|
||||
* @authenticated: Crypto authentication passed
|
||||
* @tunnel_mode: Connection native or tunneled over USB4
|
||||
* @usb4_link: device link to the USB4 host interface
|
||||
* @lpm_capable: device supports LPM
|
||||
* @lpm_devinit_allow: Allow USB3 device initiated LPM, exit latency is in range
|
||||
* @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
|
||||
@@ -724,6 +725,7 @@ struct usb_device {
|
||||
unsigned reset_resume:1;
|
||||
unsigned port_is_suspended:1;
|
||||
enum usb_link_tunnel_mode tunnel_mode;
|
||||
struct device_link *usb4_link;
|
||||
|
||||
int slot_id;
|
||||
struct usb2_lpm_parameters l1_params;
|
||||
|
||||
@@ -57,6 +57,7 @@ enum {
|
||||
DP_PIN_ASSIGN_D,
|
||||
DP_PIN_ASSIGN_E,
|
||||
DP_PIN_ASSIGN_F, /* Not supported after v1.0b */
|
||||
DP_PIN_ASSIGN_MAX,
|
||||
};
|
||||
|
||||
/* DisplayPort alt mode specific commands */
|
||||
|
||||
Reference in New Issue
Block a user