forked from Minki/linux
USB fixes for 6.1-rc3
Here are 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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCY16Evg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylP7ACbBFKioz4LgbVYYY5f12qJ3MfbfBYAn1EKSYUr jgJxsPv1LeTTicOqGIy9 =Jks2 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c4d25ce6e9
19
MAINTAINERS
19
MAINTAINERS
@ -4101,6 +4101,7 @@ N: bcm7038
|
||||
N: bcm7120
|
||||
|
||||
BROADCOM BDC DRIVER
|
||||
M: Justin Chen <justinpopo6@gmail.com>
|
||||
M: Al Cooper <alcooperx@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
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
|
||||
F: drivers/tty/serial/8250/8250_bcm7271.c
|
||||
|
||||
BROADCOM BRCMSTB USB EHCI DRIVER
|
||||
M: Justin Chen <justinpopo6@gmail.com>
|
||||
M: Al Cooper <alcooperx@gmail.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
@ -4223,6 +4225,7 @@ F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml
|
||||
F: drivers/usb/misc/brcmstb-usb-pinmap.c
|
||||
|
||||
BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
|
||||
M: Justin Chen <justinpopo6@gmail.com>
|
||||
M: Al Cooper <alcooperx@gmail.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
@ -21179,15 +21182,6 @@ S: Maintained
|
||||
F: Documentation/usb/ehci.rst
|
||||
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, ...)
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
@ -21294,13 +21288,6 @@ W: https://github.com/petkan/pegasus
|
||||
T: git https://github.com/petkan/pegasus.git
|
||||
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)
|
||||
M: Pete Zaitcev <zaitcev@redhat.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
@ -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
|
||||
* 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) ||
|
||||
!device_property_read_bool(dwc->dev, "usb-role-switch")) &&
|
||||
!DWC3_VER_IS_PRIOR(DWC3, 330A))
|
||||
@ -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)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -1840,6 +1881,12 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||
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);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
@ -8,7 +8,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb,
|
||||
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)
|
||||
#define ROLE_SWITCH 1
|
||||
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
|
||||
@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc)
|
||||
device_property_read_bool(dwc->dev, "usb-role-switch"))
|
||||
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) {
|
||||
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
||||
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||
|
@ -251,7 +251,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
/* Manage SoftReset */
|
||||
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) {
|
||||
dev_err(&pdev->dev, "failed to find dwc3 core node\n");
|
||||
ret = -ENODEV;
|
||||
|
@ -1292,8 +1292,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
|
||||
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
|
||||
}
|
||||
|
||||
/* always enable Interrupt on Missed ISOC */
|
||||
trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
|
||||
if (!no_interrupt && !chain)
|
||||
trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
|
||||
break;
|
||||
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
@ -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);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
|
||||
/*
|
||||
* 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);
|
||||
dep->resource_index = 0;
|
||||
|
||||
@ -3238,6 +3248,10 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
|
||||
if (event->status & DEPEVT_STATUS_SHORT && !chain)
|
||||
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) ||
|
||||
(trb->ctrl & DWC3_TRB_CTRL_LST))
|
||||
return 1;
|
||||
@ -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
|
||||
* prepared.
|
||||
*/
|
||||
if (dwc->ep0state != EP0_SETUP_PHASE) {
|
||||
if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) {
|
||||
dep->flags |= DWC3_EP_DELAY_STOP;
|
||||
return;
|
||||
}
|
||||
|
@ -304,6 +304,7 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
|
||||
|
||||
queue->sequence = 0;
|
||||
queue->buf_used = 0;
|
||||
queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
|
||||
} else {
|
||||
ret = vb2_streamoff(&queue->queue, queue->queue.type);
|
||||
if (ret < 0)
|
||||
@ -329,10 +330,11 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
|
||||
void uvcg_complete_buffer(struct uvc_video_queue *queue,
|
||||
struct uvc_buffer *buf)
|
||||
{
|
||||
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
|
||||
buf->length != buf->bytesused) {
|
||||
buf->state = UVC_BUF_STATE_QUEUED;
|
||||
if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) {
|
||||
queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
|
||||
buf->state = UVC_BUF_STATE_ERROR;
|
||||
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
|
||||
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
|
||||
struct uvc_buffer *buf)
|
||||
{
|
||||
void *mem = req->buf;
|
||||
struct uvc_request *ureq = req->context;
|
||||
int len = video->req_size;
|
||||
int ret;
|
||||
|
||||
@ -113,13 +114,14 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
|
||||
video->queue.buf_used = 0;
|
||||
buf->state = UVC_BUF_STATE_DONE;
|
||||
list_del(&buf->queue);
|
||||
uvcg_complete_buffer(&video->queue, buf);
|
||||
video->fid ^= UVC_STREAM_FID;
|
||||
ureq->last_buf = buf;
|
||||
|
||||
video->payload_size = 0;
|
||||
}
|
||||
|
||||
if (video->payload_size == video->max_payload_size ||
|
||||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE ||
|
||||
buf->bytesused == video->queue.buf_used)
|
||||
video->payload_size = 0;
|
||||
}
|
||||
@ -155,10 +157,10 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
|
||||
sg = sg_next(sg);
|
||||
|
||||
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;
|
||||
|
||||
sg_left = sg_dma_len(buf->sg) - buf->offset;
|
||||
sg_left = buf->sg->length - buf->offset;
|
||||
part = min_t(unsigned int, len, sg_left);
|
||||
|
||||
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,
|
||||
req->length -= 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;
|
||||
buf->state = UVC_BUF_STATE_DONE;
|
||||
buf->offset = 0;
|
||||
@ -195,6 +198,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
|
||||
struct uvc_buffer *buf)
|
||||
{
|
||||
void *mem = req->buf;
|
||||
struct uvc_request *ureq = req->context;
|
||||
int len = video->req_size;
|
||||
int ret;
|
||||
|
||||
@ -209,12 +213,13 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
|
||||
|
||||
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;
|
||||
buf->state = UVC_BUF_STATE_DONE;
|
||||
list_del(&buf->queue);
|
||||
uvcg_complete_buffer(&video->queue, buf);
|
||||
video->fid ^= UVC_STREAM_FID;
|
||||
ureq->last_buf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,6 +260,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
case 0:
|
||||
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. */
|
||||
uvcg_dbg(&video->uvc->func, "VS request cancelled.\n");
|
||||
uvcg_queue_cancel(queue, 1);
|
||||
@ -431,7 +441,8 @@ static void uvcg_video_pump(struct work_struct *work)
|
||||
|
||||
/* Endpoint now owns the request */
|
||||
req = NULL;
|
||||
video->req_int_count++;
|
||||
if (buf->state != UVC_BUF_STATE_DONE)
|
||||
video->req_int_count++;
|
||||
}
|
||||
|
||||
if (!req)
|
||||
|
@ -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.speed = USB_SPEED_UNKNOWN;
|
||||
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);
|
||||
if (rc != 0)
|
||||
|
@ -151,6 +151,7 @@ static void bdc_uspc_disconnected(struct bdc *bdc, bool reinit)
|
||||
bdc->delayed_status = false;
|
||||
bdc->reinit = reinit;
|
||||
bdc->test_mode = false;
|
||||
usb_gadget_set_state(&bdc->gadget, USB_STATE_NOTATTACHED);
|
||||
}
|
||||
|
||||
/* TNotify wkaeup timer */
|
||||
|
@ -889,15 +889,19 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
||||
if (dev->eps[i].stream_info)
|
||||
xhci_free_stream_info(xhci,
|
||||
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.
|
||||
* We can't drop them anyway, because the udev might have gone
|
||||
* away by this point, and we can't tell what speed it was.
|
||||
/*
|
||||
* Endpoints are normally deleted from the bandwidth list when
|
||||
* endpoints are dropped, before device is freed.
|
||||
* 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 "
|
||||
"not removed from BW list!\n",
|
||||
slot_id, i);
|
||||
|
||||
if (!list_empty(&dev->eps[i].bw_endpoint_list)) {
|
||||
list_del_init(&dev->eps[i].bw_endpoint_list);
|
||||
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 */
|
||||
xhci_free_tt_info(xhci, dev, slot_id);
|
||||
|
@ -58,25 +58,13 @@
|
||||
#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af
|
||||
#define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13
|
||||
#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_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_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
|
||||
|
||||
#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_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_1042A_XHCI 0x1142
|
||||
@ -257,6 +245,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
|
||||
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 &&
|
||||
(pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_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)
|
||||
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_TIGER_LAKE_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))
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI))
|
||||
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
|
||||
@ -306,8 +293,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
||||
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) {
|
||||
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
|
||||
@ -336,15 +329,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
|
||||
xhci->quirks |= XHCI_NO_SOFT_RETRY;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
(pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 ||
|
||||
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))
|
||||
/* xHC spec requires PCI devices to support D3hot and D3cold */
|
||||
if (xhci->hci_version >= 0x120)
|
||||
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
|
||||
|
||||
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
||||
|
@ -810,9 +810,15 @@ void xhci_shutdown(struct usb_hcd *hcd)
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
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);
|
||||
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
|
||||
xhci_cleanup_msix(xhci);
|
||||
|
@ -1897,6 +1897,7 @@ struct xhci_hcd {
|
||||
#define XHCI_BROKEN_D3COLD BIT_ULL(41)
|
||||
#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
|
||||
#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)
|
||||
#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
|
||||
|
||||
unsigned int num_active_eps;
|
||||
unsigned int limit_active_eps;
|
||||
|
@ -183,16 +183,6 @@ out:
|
||||
}
|
||||
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 {
|
||||
@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
|
||||
|
||||
static int ucsi_check_connection(struct ucsi_connector *con)
|
||||
{
|
||||
u8 prev_flags = con->status.flags;
|
||||
u64 command;
|
||||
int ret;
|
||||
|
||||
@ -754,10 +745,13 @@ static int ucsi_check_connection(struct ucsi_connector *con)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (con->status.flags == prev_flags)
|
||||
return 0;
|
||||
|
||||
if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
|
||||
if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
|
||||
UCSI_CONSTAT_PWR_OPMODE_PD)
|
||||
ucsi_partner_task(con, ucsi_check_altmodes, 30, 0);
|
||||
ucsi_register_partner(con);
|
||||
ucsi_pwr_opmode_change(con);
|
||||
ucsi_partner_change(con);
|
||||
} else {
|
||||
ucsi_partner_change(con);
|
||||
ucsi_port_psy_changed(con);
|
||||
@ -1276,6 +1270,28 @@ err:
|
||||
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)
|
||||
{
|
||||
struct ucsi *ucsi = container_of(work, struct ucsi, work.work);
|
||||
|
@ -185,6 +185,15 @@ static int ucsi_acpi_remove(struct platform_device *pdev)
|
||||
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[] = {
|
||||
{ "PNP0CA0", 0 },
|
||||
{ },
|
||||
@ -194,6 +203,7 @@ MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
|
||||
static struct platform_driver ucsi_acpi_platform_driver = {
|
||||
.driver = {
|
||||
.name = "ucsi_acpi",
|
||||
.pm = pm_ptr(&ucsi_acpi_pm_ops),
|
||||
.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
|
||||
},
|
||||
.probe = ucsi_acpi_probe,
|
||||
|
Loading…
Reference in New Issue
Block a user