Commit c4d25ce6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "A few small USB fixes for 6.1-rc3. Include in here are:

   - MAINTAINERS update, including a big one for the USB gadget
     subsystem. Many thanks to Felipe for all of the years of hard work
     he has done on this codebase, it was greatly appreciated.

   - dwc3 driver fixes for reported problems.

   - xhci driver fixes for reported problems.

   - typec driver fixes for minor issues

   - uvc gadget driver change, and then revert as it wasn't relevant for
     6.1-final, as it is a new feature and people are still reviewing
     and modifying it.

  All of these have been in the linux-next tree with no reported issues"

* tag 'usb-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: dwc3: gadget: Don't set IMI for no_interrupt
  usb: dwc3: gadget: Stop processing more requests on IMI
  Revert "usb: gadget: uvc: limit isoc_sg to super speed gadgets"
  xhci: Remove device endpoints from bandwidth list when freeing the device
  xhci-pci: Set runtime PM as default policy on all xHC 1.2 or later devices
  xhci: Add quirk to reset host back to default state at shutdown
  usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96 controller
  usb: dwc3: st: Rely on child's compatible instead of name
  usb: gadget: uvc: limit isoc_sg to super speed gadgets
  usb: bdc: change state when port disconnected
  usb: typec: ucsi: acpi: Implement resume callback
  usb: typec: ucsi: Check the connection on resume
  usb: gadget: aspeed: Fix probe regression
  usb: gadget: uvc: fix sg handling during video encode
  usb: gadget: uvc: fix sg handling in error case
  usb: gadget: uvc: fix dropped frame after missed isoc
  usb: dwc3: gadget: Don't delay End Transfer on delayed_status
  usb: dwc3: Don't switch OTG -> peripheral if extcon is present
  MAINTAINERS: Update maintainers for broadcom USB
  MAINTAINERS: move USB gadget and phy entries under the main USB entry
parents ef3c0949 308c316d
...@@ -4101,6 +4101,7 @@ N: bcm7038 ...@@ -4101,6 +4101,7 @@ N: bcm7038
N: bcm7120 N: bcm7120
BROADCOM BDC DRIVER BROADCOM BDC DRIVER
M: Justin Chen <justinpopo6@gmail.com>
M: Al Cooper <alcooperx@gmail.com> M: Al Cooper <alcooperx@gmail.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
...@@ -4207,6 +4208,7 @@ F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml ...@@ -4207,6 +4208,7 @@ F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
F: drivers/tty/serial/8250/8250_bcm7271.c F: drivers/tty/serial/8250/8250_bcm7271.c
BROADCOM BRCMSTB USB EHCI DRIVER BROADCOM BRCMSTB USB EHCI DRIVER
M: Justin Chen <justinpopo6@gmail.com>
M: Al Cooper <alcooperx@gmail.com> M: Al Cooper <alcooperx@gmail.com>
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
...@@ -4223,6 +4225,7 @@ F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml ...@@ -4223,6 +4225,7 @@ F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml
F: drivers/usb/misc/brcmstb-usb-pinmap.c F: drivers/usb/misc/brcmstb-usb-pinmap.c
BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
M: Justin Chen <justinpopo6@gmail.com>
M: Al Cooper <alcooperx@gmail.com> M: Al Cooper <alcooperx@gmail.com>
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
...@@ -21179,15 +21182,6 @@ S: Maintained ...@@ -21179,15 +21182,6 @@ S: Maintained
F: Documentation/usb/ehci.rst F: Documentation/usb/ehci.rst
F: drivers/usb/host/ehci* F: drivers/usb/host/ehci*
USB GADGET/PERIPHERAL SUBSYSTEM
M: Felipe Balbi <balbi@kernel.org>
L: linux-usb@vger.kernel.org
S: Maintained
W: http://www.linux-usb.org/gadget
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
F: drivers/usb/gadget/
F: include/linux/usb/gadget*
USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
M: Jiri Kosina <jikos@kernel.org> M: Jiri Kosina <jikos@kernel.org>
M: Benjamin Tissoires <benjamin.tissoires@redhat.com> M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
...@@ -21294,13 +21288,6 @@ W: https://github.com/petkan/pegasus ...@@ -21294,13 +21288,6 @@ W: https://github.com/petkan/pegasus
T: git https://github.com/petkan/pegasus.git T: git https://github.com/petkan/pegasus.git
F: drivers/net/usb/pegasus.* F: drivers/net/usb/pegasus.*
USB PHY LAYER
M: Felipe Balbi <balbi@kernel.org>
L: linux-usb@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
F: drivers/usb/phy/
USB PRINTER DRIVER (usblp) USB PRINTER DRIVER (usblp)
M: Pete Zaitcev <zaitcev@redhat.com> M: Pete Zaitcev <zaitcev@redhat.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -85,7 +86,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) ...@@ -85,7 +86,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
* mode. If the controller supports DRD but the dr_mode is not * mode. If the controller supports DRD but the dr_mode is not
* specified or set to OTG, then set the mode to peripheral. * specified or set to OTG, then set the mode to peripheral.
*/ */
if (mode == USB_DR_MODE_OTG && if (mode == USB_DR_MODE_OTG && !dwc->edev &&
(!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
!device_property_read_bool(dwc->dev, "usb-role-switch")) && !device_property_read_bool(dwc->dev, "usb-role-switch")) &&
!DWC3_VER_IS_PRIOR(DWC3, 330A)) !DWC3_VER_IS_PRIOR(DWC3, 330A))
...@@ -1690,6 +1691,46 @@ static void dwc3_check_params(struct dwc3 *dwc) ...@@ -1690,6 +1691,46 @@ static void dwc3_check_params(struct dwc3 *dwc)
} }
} }
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
struct device_node *np_phy;
struct extcon_dev *edev = NULL;
const char *name;
if (device_property_read_bool(dev, "extcon"))
return extcon_get_edev_by_phandle(dev, 0);
/*
* Device tree platforms should get extcon via phandle.
* On ACPI platforms, we get the name from a device property.
* This device property is for kernel internal use only and
* is expected to be set by the glue code.
*/
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
return extcon_get_extcon_dev(name);
/*
* Try to get an extcon device from the USB PHY controller's "port"
* node. Check if it has the "port" node first, to avoid printing the
* error message from underlying code, as it's a valid case: extcon
* device (and "port" node) may be missing in case of "usb-role-switch"
* or OTG mode.
*/
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
if (of_graph_is_present(np_phy)) {
struct device_node *np_conn;
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
if (np_conn)
edev = extcon_find_edev_by_node(np_conn);
of_node_put(np_conn);
}
of_node_put(np_phy);
return edev;
}
static int dwc3_probe(struct platform_device *pdev) static int dwc3_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -1840,6 +1881,12 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -1840,6 +1881,12 @@ static int dwc3_probe(struct platform_device *pdev)
goto err2; goto err2;
} }
dwc->edev = dwc3_get_extcon(dwc);
if (IS_ERR(dwc->edev)) {
ret = dev_err_probe(dwc->dev, PTR_ERR(dwc->edev), "failed to get extcon\n");
goto err3;
}
ret = dwc3_get_dr_mode(dwc); ret = dwc3_get_dr_mode(dwc);
if (ret) if (ret)
goto err3; goto err3;
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
*/ */
#include <linux/extcon.h> #include <linux/extcon.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h> #include <linux/property.h>
...@@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb, ...@@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
struct device_node *np_phy;
struct extcon_dev *edev = NULL;
const char *name;
if (device_property_read_bool(dev, "extcon"))
return extcon_get_edev_by_phandle(dev, 0);
/*
* Device tree platforms should get extcon via phandle.
* On ACPI platforms, we get the name from a device property.
* This device property is for kernel internal use only and
* is expected to be set by the glue code.
*/
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
edev = extcon_get_extcon_dev(name);
if (!edev)
return ERR_PTR(-EPROBE_DEFER);
return edev;
}
/*
* Try to get an extcon device from the USB PHY controller's "port"
* node. Check if it has the "port" node first, to avoid printing the
* error message from underlying code, as it's a valid case: extcon
* device (and "port" node) may be missing in case of "usb-role-switch"
* or OTG mode.
*/
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
if (of_graph_is_present(np_phy)) {
struct device_node *np_conn;
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
if (np_conn)
edev = extcon_find_edev_by_node(np_conn);
of_node_put(np_conn);
}
of_node_put(np_phy);
return edev;
}
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) #if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
#define ROLE_SWITCH 1 #define ROLE_SWITCH 1
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
...@@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc) ...@@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc)
device_property_read_bool(dwc->dev, "usb-role-switch")) device_property_read_bool(dwc->dev, "usb-role-switch"))
return dwc3_setup_role_switch(dwc); return dwc3_setup_role_switch(dwc);
dwc->edev = dwc3_get_extcon(dwc);
if (IS_ERR(dwc->edev))
return PTR_ERR(dwc->edev);
if (dwc->edev) { if (dwc->edev) {
dwc->edev_nb.notifier_call = dwc3_drd_notifier; dwc->edev_nb.notifier_call = dwc3_drd_notifier;
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
......
...@@ -251,7 +251,7 @@ static int st_dwc3_probe(struct platform_device *pdev) ...@@ -251,7 +251,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
/* Manage SoftReset */ /* Manage SoftReset */
reset_control_deassert(dwc3_data->rstc_rst); reset_control_deassert(dwc3_data->rstc_rst);
child = of_get_child_by_name(node, "usb"); child = of_get_compatible_child(node, "snps,dwc3");
if (!child) { if (!child) {
dev_err(&pdev->dev, "failed to find dwc3 core node\n"); dev_err(&pdev->dev, "failed to find dwc3 core node\n");
ret = -ENODEV; ret = -ENODEV;
......
...@@ -1292,8 +1292,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, ...@@ -1292,8 +1292,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
} }
/* always enable Interrupt on Missed ISOC */ if (!no_interrupt && !chain)
trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
break; break;
case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_BULK:
...@@ -1698,6 +1698,16 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int ...@@ -1698,6 +1698,16 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params); ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
/*
* If the End Transfer command was timed out while the device is
* not in SETUP phase, it's possible that an incoming Setup packet
* may prevent the command's completion. Let's retry when the
* ep0state returns to EP0_SETUP_PHASE.
*/
if (ret == -ETIMEDOUT && dep->dwc->ep0state != EP0_SETUP_PHASE) {
dep->flags |= DWC3_EP_DELAY_STOP;
return 0;
}
WARN_ON_ONCE(ret); WARN_ON_ONCE(ret);
dep->resource_index = 0; dep->resource_index = 0;
...@@ -3238,6 +3248,10 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, ...@@ -3238,6 +3248,10 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
if (event->status & DEPEVT_STATUS_SHORT && !chain) if (event->status & DEPEVT_STATUS_SHORT && !chain)
return 1; return 1;
if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) &&
DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC)
return 1;
if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
(trb->ctrl & DWC3_TRB_CTRL_LST)) (trb->ctrl & DWC3_TRB_CTRL_LST))
return 1; return 1;
...@@ -3719,7 +3733,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, ...@@ -3719,7 +3733,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
* timeout. Delay issuing the End Transfer command until the Setup TRB is * timeout. Delay issuing the End Transfer command until the Setup TRB is
* prepared. * prepared.
*/ */
if (dwc->ep0state != EP0_SETUP_PHASE) { if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) {
dep->flags |= DWC3_EP_DELAY_STOP; dep->flags |= DWC3_EP_DELAY_STOP;
return; return;
} }
......
...@@ -304,6 +304,7 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) ...@@ -304,6 +304,7 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
queue->sequence = 0; queue->sequence = 0;
queue->buf_used = 0; queue->buf_used = 0;
queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
} else { } else {
ret = vb2_streamoff(&queue->queue, queue->queue.type); ret = vb2_streamoff(&queue->queue, queue->queue.type);
if (ret < 0) if (ret < 0)
...@@ -329,10 +330,11 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) ...@@ -329,10 +330,11 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
void uvcg_complete_buffer(struct uvc_video_queue *queue, void uvcg_complete_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf) struct uvc_buffer *buf)
{ {
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) {
buf->length != buf->bytesused) { queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
buf->state = UVC_BUF_STATE_QUEUED; buf->state = UVC_BUF_STATE_ERROR;
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
return; return;
} }
......
...@@ -88,6 +88,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, ...@@ -88,6 +88,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf) struct uvc_buffer *buf)
{ {
void *mem = req->buf; void *mem = req->buf;
struct uvc_request *ureq = req->context;
int len = video->req_size; int len = video->req_size;
int ret; int ret;
...@@ -113,13 +114,14 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, ...@@ -113,13 +114,14 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
video->queue.buf_used = 0; video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE; buf->state = UVC_BUF_STATE_DONE;
list_del(&buf->queue); list_del(&buf->queue);
uvcg_complete_buffer(&video->queue, buf);
video->fid ^= UVC_STREAM_FID; video->fid ^= UVC_STREAM_FID;
ureq->last_buf = buf;
video->payload_size = 0; video->payload_size = 0;
} }
if (video->payload_size == video->max_payload_size || if (video->payload_size == video->max_payload_size ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE ||
buf->bytesused == video->queue.buf_used) buf->bytesused == video->queue.buf_used)
video->payload_size = 0; video->payload_size = 0;
} }
...@@ -155,10 +157,10 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, ...@@ -155,10 +157,10 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
sg = sg_next(sg); sg = sg_next(sg);
for_each_sg(sg, iter, ureq->sgt.nents - 1, i) { for_each_sg(sg, iter, ureq->sgt.nents - 1, i) {
if (!len || !buf->sg || !sg_dma_len(buf->sg)) if (!len || !buf->sg || !buf->sg->length)
break; break;
sg_left = sg_dma_len(buf->sg) - buf->offset; sg_left = buf->sg->length - buf->offset;
part = min_t(unsigned int, len, sg_left); part = min_t(unsigned int, len, sg_left);
sg_set_page(iter, sg_page(buf->sg), part, buf->offset); sg_set_page(iter, sg_page(buf->sg), part, buf->offset);
...@@ -180,7 +182,8 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, ...@@ -180,7 +182,8 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
req->length -= len; req->length -= len;
video->queue.buf_used += req->length - header_len; video->queue.buf_used += req->length - header_len;
if (buf->bytesused == video->queue.buf_used || !buf->sg) { if (buf->bytesused == video->queue.buf_used || !buf->sg ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
video->queue.buf_used = 0; video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE; buf->state = UVC_BUF_STATE_DONE;
buf->offset = 0; buf->offset = 0;
...@@ -195,6 +198,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, ...@@ -195,6 +198,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf) struct uvc_buffer *buf)
{ {
void *mem = req->buf; void *mem = req->buf;
struct uvc_request *ureq = req->context;
int len = video->req_size; int len = video->req_size;
int ret; int ret;
...@@ -209,12 +213,13 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, ...@@ -209,12 +213,13 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
req->length = video->req_size - len; req->length = video->req_size - len;
if (buf->bytesused == video->queue.buf_used) { if (buf->bytesused == video->queue.buf_used ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
video->queue.buf_used = 0; video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE; buf->state = UVC_BUF_STATE_DONE;
list_del(&buf->queue); list_del(&buf->queue);
uvcg_complete_buffer(&video->queue, buf);
video->fid ^= UVC_STREAM_FID; video->fid ^= UVC_STREAM_FID;
ureq->last_buf = buf;
} }
} }
...@@ -255,6 +260,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -255,6 +260,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
case 0: case 0:
break; break;
case -EXDEV:
uvcg_dbg(&video->uvc->func, "VS request missed xfer.\n");
queue->flags |= UVC_QUEUE_DROP_INCOMPLETE;
break;
case -ESHUTDOWN: /* disconnect from host. */ case -ESHUTDOWN: /* disconnect from host. */
uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); uvcg_dbg(&video->uvc->func, "VS request cancelled.\n");
uvcg_queue_cancel(queue, 1); uvcg_queue_cancel(queue, 1);
...@@ -431,7 +441,8 @@ static void uvcg_video_pump(struct work_struct *work) ...@@ -431,7 +441,8 @@ static void uvcg_video_pump(struct work_struct *work)
/* Endpoint now owns the request */ /* Endpoint now owns the request */
req = NULL; req = NULL;
video->req_int_count++; if (buf->state != UVC_BUF_STATE_DONE)
video->req_int_count++;
} }
if (!req) if (!req)
......
...@@ -591,6 +591,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) ...@@ -591,6 +591,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
d->gadget.max_speed = USB_SPEED_HIGH; d->gadget.max_speed = USB_SPEED_HIGH;
d->gadget.speed = USB_SPEED_UNKNOWN; d->gadget.speed = USB_SPEED_UNKNOWN;
d->gadget.dev.of_node = vhub->pdev->dev.of_node; d->gadget.dev.of_node = vhub->pdev->dev.of_node;
d->gadget.dev.of_node_reused = true;
rc = usb_add_gadget_udc(d->port_dev, &d->gadget); rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
if (rc != 0) if (rc != 0)
......
...@@ -151,6 +151,7 @@ static void bdc_uspc_disconnected(struct bdc *bdc, bool reinit) ...@@ -151,6 +151,7 @@ static void bdc_uspc_disconnected(struct bdc *bdc, bool reinit)
bdc->delayed_status = false; bdc->delayed_status = false;
bdc->reinit = reinit; bdc->reinit = reinit;
bdc->test_mode = false; bdc->test_mode = false;
usb_gadget_set_state(&bdc->gadget, USB_STATE_NOTATTACHED);
} }
/* TNotify wkaeup timer */ /* TNotify wkaeup timer */
......
...@@ -889,15 +889,19 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) ...@@ -889,15 +889,19 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
if (dev->eps[i].stream_info) if (dev->eps[i].stream_info)
xhci_free_stream_info(xhci, xhci_free_stream_info(xhci,
dev->eps[i].stream_info); dev->eps[i].stream_info);
/* Endpoints on the TT/root port lists should have been removed /*
* when usb_disable_device() was called for the device. * Endpoints are normally deleted from the bandwidth list when
* We can't drop them anyway, because the udev might have gone * endpoints are dropped, before device is freed.
* away by this point, and we can't tell what speed it was. * If host is dying or being removed then endpoints aren't
* dropped cleanly, so delete the endpoint from list here.
* Only applicable for hosts with software bandwidth checking.
*/ */
if (!list_empty(&dev->eps[i].bw_endpoint_list))
xhci_warn(xhci, "Slot %u endpoint %u " if (!list_empty(&dev->eps[i].bw_endpoint_list)) {
"not removed from BW list!\n", list_del_init(&dev->eps[i].bw_endpoint_list);
slot_id, i); xhci_dbg(xhci, "Slot %u endpoint %u not removed from BW list!\n",
slot_id, i);
}
} }
/* If this is a hub, free the TT(s) from the TT list */ /* If this is a hub, free the TT(s) from the TT list */
xhci_free_tt_info(xhci, dev, slot_id); xhci_free_tt_info(xhci, dev, slot_id);
......
...@@ -58,25 +58,13 @@ ...@@ -58,25 +58,13 @@
#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af
#define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13
#define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI 0x7ec0
#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 0x161a
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 0x161b
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 0x161d
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f
#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
...@@ -257,6 +245,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -257,6 +245,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS; xhci->quirks |= XHCI_MISSING_CAS;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI)
xhci->quirks |= XHCI_RESET_TO_DEFAULT;
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI || (pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI ||
...@@ -268,12 +260,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -268,12 +260,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI))
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON && if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
...@@ -306,8 +293,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -306,8 +293,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
} }
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) {
/*
* try to tame the ASMedia 1042 controller which reports 0.96
* but appears to behave more like 1.0
*/
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
xhci->quirks |= XHCI_BROKEN_STREAMS; xhci->quirks |= XHCI_BROKEN_STREAMS;
}
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) { pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) {
xhci->quirks |= XHCI_TRUST_TX_LENGTH; xhci->quirks |= XHCI_TRUST_TX_LENGTH;
...@@ -336,15 +329,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -336,15 +329,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
xhci->quirks |= XHCI_NO_SOFT_RETRY; xhci->quirks |= XHCI_NO_SOFT_RETRY;
if (pdev->vendor == PCI_VENDOR_ID_AMD && /* xHC spec requires PCI devices to support D3hot and D3cold */
(pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 || if (xhci->hci_version >= 0x120)
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (xhci->quirks & XHCI_RESET_ON_RESUME) if (xhci->quirks & XHCI_RESET_ON_RESUME)
......
...@@ -810,9 +810,15 @@ void xhci_shutdown(struct usb_hcd *hcd) ...@@ -810,9 +810,15 @@ void xhci_shutdown(struct usb_hcd *hcd)
spin_lock_irq(&xhci->lock); spin_lock_irq(&xhci->lock);
xhci_halt(xhci); xhci_halt(xhci);
/* Workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) /*
* Workaround for spurious wakeps at shutdown with HSW, and for boot
* firmware delay in ADL-P PCH if port are left in U3 at shutdown
*/
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP ||
xhci->quirks & XHCI_RESET_TO_DEFAULT)
xhci_reset(xhci, XHCI_RESET_SHORT_USEC); xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
spin_unlock_irq(&xhci->lock); spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci); xhci_cleanup_msix(xhci);
......
...@@ -1897,6 +1897,7 @@ struct xhci_hcd { ...@@ -1897,6 +1897,7 @@ struct xhci_hcd {
#define XHCI_BROKEN_D3COLD BIT_ULL(41) #define XHCI_BROKEN_D3COLD BIT_ULL(41)
#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)
#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
......
...@@ -183,16 +183,6 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, ...@@ -183,16 +183,6 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command,
} }
EXPORT_SYMBOL_GPL(ucsi_send_command); EXPORT_SYMBOL_GPL(ucsi_send_command);
int ucsi_resume(struct ucsi *ucsi)
{
u64 command;
/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
return ucsi_send_command(ucsi, command, NULL, 0);
}
EXPORT_SYMBOL_GPL(ucsi_resume);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
struct ucsi_work { struct ucsi_work {
...@@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con) ...@@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
static int ucsi_check_connection(struct ucsi_connector *con) static int ucsi_check_connection(struct ucsi_connector *con)
{ {
u8 prev_flags = con->status.flags;
u64 command; u64 command;
int ret; int ret;
...@@ -754,10 +745,13 @@ static int ucsi_check_connection(struct ucsi_connector *con) ...@@ -754,10 +745,13 @@ static int ucsi_check_connection(struct ucsi_connector *con)
return ret; return ret;
} }
if (con->status.flags == prev_flags)
return 0;
if (con->status.flags & UCSI_CONSTAT_CONNECTED) { if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == ucsi_register_partner(con);
UCSI_CONSTAT_PWR_OPMODE_PD) ucsi_pwr_opmode_change(con);
ucsi_partner_task(con, ucsi_check_altmodes, 30, 0); ucsi_partner_change(con);
} else { } else {
ucsi_partner_change(con); ucsi_partner_change(con);
ucsi_port_psy_changed(con); ucsi_port_psy_changed(con);
...@@ -1276,6 +1270,28 @@ static int ucsi_init(struct ucsi *ucsi) ...@@ -1276,6 +1270,28 @@ static int ucsi_init(struct ucsi *ucsi)
return ret; return ret;
} }
int ucsi_resume(struct ucsi *ucsi)
{
struct ucsi_connector *con;
u64 command;
int ret;
/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
return ret;
for (con = ucsi->connector; con->port; con++) {
mutex_lock(&con->lock);
ucsi_check_connection(con);
mutex_unlock(&con->lock);
}
return 0;
}
EXPORT_SYMBOL_GPL(ucsi_resume);
static void ucsi_init_work(struct work_struct *work) static void ucsi_init_work(struct work_struct *work)
{ {
struct ucsi *ucsi = container_of(work, struct ucsi, work.work); struct ucsi *ucsi = container_of(work, struct ucsi, work.work);
......
...@@ -185,6 +185,15 @@ static int ucsi_acpi_remove(struct platform_device *pdev) ...@@ -185,6 +185,15 @@ static int ucsi_acpi_remove(struct platform_device *pdev)
return 0; return 0;
} }
static int ucsi_acpi_resume(struct device *dev)
{
struct ucsi_acpi *ua = dev_get_drvdata(dev);
return ucsi_resume(ua->ucsi);
}
static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_acpi_pm_ops, NULL, ucsi_acpi_resume);
static const struct acpi_device_id ucsi_acpi_match[] = { static const struct acpi_device_id ucsi_acpi_match[] = {
{ "PNP0CA0", 0 }, { "PNP0CA0", 0 },
{ }, { },
...@@ -194,6 +203,7 @@ MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match); ...@@ -194,6 +203,7 @@ MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
static struct platform_driver ucsi_acpi_platform_driver = { static struct platform_driver ucsi_acpi_platform_driver = {
.driver = { .driver = {
.name = "ucsi_acpi", .name = "ucsi_acpi",
.pm = pm_ptr(&ucsi_acpi_pm_ops),
.acpi_match_table = ACPI_PTR(ucsi_acpi_match), .acpi_match_table = ACPI_PTR(ucsi_acpi_match),
}, },
.probe = ucsi_acpi_probe, .probe = ucsi_acpi_probe,
......
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