mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
USB fixes for 6.8-rc6
Here are some small USB fixes for 6.8-rc6 to resolve some reported problems. These include: - regression fixes with typec tpcm code as reported by many - cdnsp and cdns3 driver fixes - usb role setting code bugfixes - build fix for uhci driver - ncm gadget driver bugfix - MAINTAINERS entry update All of these have been in linux-next all week with no reported issues and there is at least one fix in here that is in Thorsten's regression list that is being tracked. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZdtGEA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymzsgCg2IsWqIR72XUGsa5rrbRnskOP/G4An24BmUb6 t34d0VjiHagZTFlfRx6g =eOL1 -----END PGP SIGNATURE----- Merge tag 'usb-6.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are some small USB fixes for 6.8-rc6 to resolve some reported problems. These include: - regression fixes with typec tpcm code as reported by many - cdnsp and cdns3 driver fixes - usb role setting code bugfixes - build fix for uhci driver - ncm gadget driver bugfix - MAINTAINERS entry update All of these have been in linux-next all week with no reported issues and there is at least one fix in here that is in Thorsten's regression list that is being tracked" * tag 'usb-6.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: typec: tpcm: Fix issues with power being removed during reset MAINTAINERS: Drop myself as maintainer of TYPEC port controller drivers usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs Revert "usb: typec: tcpm: reset counter when enter into unattached state after try role" usb: gadget: omap_udc: fix USB gadget regression on Palm TE usb: dwc3: gadget: Don't disconnect if not started usb: cdns3: fix memory double free when handle zero packet usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable() usb: roles: don't get/set_role() when usb_role_switch is unregistered usb: roles: fix NULL pointer issue when put module's reference usb: cdnsp: fixed issue with incorrect detecting CDNSP family controllers usb: cdnsp: blocked some cdns3 specific code usb: uhci-grlib: Explicitly include linux/platform_device.h
This commit is contained in:
commit
c46ac50ebe
@ -22880,9 +22880,8 @@ S: Maintained
|
||||
F: drivers/usb/typec/mux/pi3usb30532.c
|
||||
|
||||
USB TYPEC PORT CONTROLLER DRIVERS
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/usb/typec/tcpm/
|
||||
|
||||
USB UHCI DRIVER
|
||||
|
@ -828,7 +828,11 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
|
||||
return;
|
||||
}
|
||||
|
||||
if (request->complete) {
|
||||
/*
|
||||
* zlp request is appended by driver, needn't call usb_gadget_giveback_request() to notify
|
||||
* gadget composite driver.
|
||||
*/
|
||||
if (request->complete && request->buf != priv_dev->zlp_buf) {
|
||||
spin_unlock(&priv_dev->lock);
|
||||
usb_gadget_giveback_request(&priv_ep->endpoint,
|
||||
request);
|
||||
@ -2540,11 +2544,11 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep)
|
||||
|
||||
while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
|
||||
priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
|
||||
list_del_init(&priv_req->list);
|
||||
|
||||
kfree(priv_req->request.buf);
|
||||
cdns3_gadget_ep_free_request(&priv_ep->endpoint,
|
||||
&priv_req->request);
|
||||
list_del_init(&priv_req->list);
|
||||
--priv_ep->wa2_counter;
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,6 @@ static int cdns_role_set(struct usb_role_switch *sw, enum usb_role role)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cdns_wakeup_irq - interrupt handler for wakeup events
|
||||
* @irq: irq number for cdns3/cdnsp core device
|
||||
|
@ -156,7 +156,8 @@ bool cdns_is_device(struct cdns *cdns)
|
||||
*/
|
||||
static void cdns_otg_disable_irq(struct cdns *cdns)
|
||||
{
|
||||
writel(0, &cdns->otg_irq_regs->ien);
|
||||
if (cdns->version)
|
||||
writel(0, &cdns->otg_irq_regs->ien);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -422,15 +423,20 @@ int cdns_drd_init(struct cdns *cdns)
|
||||
|
||||
cdns->otg_regs = (void __iomem *)&cdns->otg_v1_regs->cmd;
|
||||
|
||||
if (readl(&cdns->otg_cdnsp_regs->did) == OTG_CDNSP_DID) {
|
||||
state = readl(&cdns->otg_cdnsp_regs->did);
|
||||
|
||||
if (OTG_CDNSP_CHECK_DID(state)) {
|
||||
cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)
|
||||
&cdns->otg_cdnsp_regs->ien;
|
||||
cdns->version = CDNSP_CONTROLLER_V2;
|
||||
} else {
|
||||
} else if (OTG_CDNS3_CHECK_DID(state)) {
|
||||
cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)
|
||||
&cdns->otg_v1_regs->ien;
|
||||
writel(1, &cdns->otg_v1_regs->simulate);
|
||||
cdns->version = CDNS3_CONTROLLER_V1;
|
||||
} else {
|
||||
dev_err(cdns->dev, "not supporte DID=0x%08x\n", state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n",
|
||||
@ -483,7 +489,6 @@ int cdns_drd_exit(struct cdns *cdns)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Indicate the cdns3 core was power lost before */
|
||||
bool cdns_power_is_lost(struct cdns *cdns)
|
||||
{
|
||||
|
@ -79,7 +79,11 @@ struct cdnsp_otg_regs {
|
||||
__le32 susp_timing_ctrl;
|
||||
};
|
||||
|
||||
#define OTG_CDNSP_DID 0x0004034E
|
||||
/* CDNSP driver supports 0x000403xx Cadence USB controller family. */
|
||||
#define OTG_CDNSP_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040300)
|
||||
|
||||
/* CDNS3 driver supports 0x000402xx Cadence USB controller family. */
|
||||
#define OTG_CDNS3_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040200)
|
||||
|
||||
/*
|
||||
* Common registers interface for both CDNS3 and CDNSP version of DRD.
|
||||
|
@ -18,6 +18,11 @@
|
||||
#include "../host/xhci.h"
|
||||
#include "../host/xhci-plat.h"
|
||||
|
||||
/*
|
||||
* The XECP_PORT_CAP_REG and XECP_AUX_CTRL_REG1 exist only
|
||||
* in Cadence USB3 dual-role controller, so it can't be used
|
||||
* with Cadence CDNSP dual-role controller.
|
||||
*/
|
||||
#define XECP_PORT_CAP_REG 0x8000
|
||||
#define XECP_AUX_CTRL_REG1 0x8120
|
||||
|
||||
@ -57,6 +62,8 @@ static const struct xhci_plat_priv xhci_plat_cdns3_xhci = {
|
||||
.resume_quirk = xhci_cdns3_resume_quirk,
|
||||
};
|
||||
|
||||
static const struct xhci_plat_priv xhci_plat_cdnsp_xhci;
|
||||
|
||||
static int __cdns_host_init(struct cdns *cdns)
|
||||
{
|
||||
struct platform_device *xhci;
|
||||
@ -81,8 +88,13 @@ static int __cdns_host_init(struct cdns *cdns)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci,
|
||||
sizeof(struct xhci_plat_priv), GFP_KERNEL);
|
||||
if (cdns->version < CDNSP_CONTROLLER_V2)
|
||||
cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci,
|
||||
sizeof(struct xhci_plat_priv), GFP_KERNEL);
|
||||
else
|
||||
cdns->xhci_plat_data = kmemdup(&xhci_plat_cdnsp_xhci,
|
||||
sizeof(struct xhci_plat_priv), GFP_KERNEL);
|
||||
|
||||
if (!cdns->xhci_plat_data) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
|
@ -2650,6 +2650,11 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
if (!dwc->pullups_connected) {
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwc->connected = false;
|
||||
|
||||
/*
|
||||
|
@ -1338,7 +1338,15 @@ static int ncm_unwrap_ntb(struct gether *port,
|
||||
"Parsed NTB with %d frames\n", dgram_counter);
|
||||
|
||||
to_process -= block_len;
|
||||
if (to_process != 0) {
|
||||
|
||||
/*
|
||||
* Windows NCM driver avoids USB ZLPs by adding a 1-byte
|
||||
* zero pad as needed.
|
||||
*/
|
||||
if (to_process == 1 &&
|
||||
(*(unsigned char *)(ntb_ptr + block_len) == 0x00)) {
|
||||
to_process--;
|
||||
} else if (to_process > 0) {
|
||||
ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
|
||||
goto parse_ntb;
|
||||
}
|
||||
|
@ -2036,7 +2036,8 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
|
||||
|
||||
static inline int machine_without_vbus_sense(void)
|
||||
{
|
||||
return machine_is_omap_osk() || machine_is_sx1();
|
||||
return machine_is_omap_osk() || machine_is_omap_palmte() ||
|
||||
machine_is_sx1();
|
||||
}
|
||||
|
||||
static int omap_udc_start(struct usb_gadget *g,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static int uhci_grlib_init(struct usb_hcd *hcd)
|
||||
{
|
||||
|
@ -21,7 +21,9 @@ static const struct class role_class = {
|
||||
struct usb_role_switch {
|
||||
struct device dev;
|
||||
struct mutex lock; /* device lock*/
|
||||
struct module *module; /* the module this device depends on */
|
||||
enum usb_role role;
|
||||
bool registered;
|
||||
|
||||
/* From descriptor */
|
||||
struct device *usb2_port;
|
||||
@ -48,6 +50,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
|
||||
if (IS_ERR_OR_NULL(sw))
|
||||
return 0;
|
||||
|
||||
if (!sw->registered)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&sw->lock);
|
||||
|
||||
ret = sw->set(sw, role);
|
||||
@ -73,7 +78,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
|
||||
{
|
||||
enum usb_role role;
|
||||
|
||||
if (IS_ERR_OR_NULL(sw))
|
||||
if (IS_ERR_OR_NULL(sw) || !sw->registered)
|
||||
return USB_ROLE_NONE;
|
||||
|
||||
mutex_lock(&sw->lock);
|
||||
@ -135,7 +140,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
|
||||
usb_role_switch_match);
|
||||
|
||||
if (!IS_ERR_OR_NULL(sw))
|
||||
WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
|
||||
WARN_ON(!try_module_get(sw->module));
|
||||
|
||||
return sw;
|
||||
}
|
||||
@ -157,7 +162,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
|
||||
sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
|
||||
NULL, usb_role_switch_match);
|
||||
if (!IS_ERR_OR_NULL(sw))
|
||||
WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
|
||||
WARN_ON(!try_module_get(sw->module));
|
||||
|
||||
return sw;
|
||||
}
|
||||
@ -172,7 +177,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
|
||||
void usb_role_switch_put(struct usb_role_switch *sw)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(sw)) {
|
||||
module_put(sw->dev.parent->driver->owner);
|
||||
module_put(sw->module);
|
||||
put_device(&sw->dev);
|
||||
}
|
||||
}
|
||||
@ -189,15 +194,18 @@ struct usb_role_switch *
|
||||
usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct device *dev;
|
||||
struct usb_role_switch *sw = NULL;
|
||||
|
||||
if (!fwnode)
|
||||
return NULL;
|
||||
|
||||
dev = class_find_device_by_fwnode(&role_class, fwnode);
|
||||
if (dev)
|
||||
WARN_ON(!try_module_get(dev->parent->driver->owner));
|
||||
if (dev) {
|
||||
sw = to_role_switch(dev);
|
||||
WARN_ON(!try_module_get(sw->module));
|
||||
}
|
||||
|
||||
return dev ? to_role_switch(dev) : NULL;
|
||||
return sw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
|
||||
|
||||
@ -338,6 +346,7 @@ usb_role_switch_register(struct device *parent,
|
||||
sw->set = desc->set;
|
||||
sw->get = desc->get;
|
||||
|
||||
sw->module = parent->driver->owner;
|
||||
sw->dev.parent = parent;
|
||||
sw->dev.fwnode = desc->fwnode;
|
||||
sw->dev.class = &role_class;
|
||||
@ -352,6 +361,8 @@ usb_role_switch_register(struct device *parent,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
sw->registered = true;
|
||||
|
||||
/* TODO: Symlinks for the host port and the device controller. */
|
||||
|
||||
return sw;
|
||||
@ -366,8 +377,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register);
|
||||
*/
|
||||
void usb_role_switch_unregister(struct usb_role_switch *sw)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(sw))
|
||||
if (!IS_ERR_OR_NULL(sw)) {
|
||||
sw->registered = false;
|
||||
device_unregister(&sw->dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
|
||||
|
||||
|
@ -3743,9 +3743,6 @@ static void tcpm_detach(struct tcpm_port *port)
|
||||
if (tcpm_port_is_disconnected(port))
|
||||
port->hard_reset_count = 0;
|
||||
|
||||
port->try_src_count = 0;
|
||||
port->try_snk_count = 0;
|
||||
|
||||
if (!port->attached)
|
||||
return;
|
||||
|
||||
@ -4876,7 +4873,8 @@ static void run_state_machine(struct tcpm_port *port)
|
||||
break;
|
||||
case PORT_RESET:
|
||||
tcpm_reset_port(port);
|
||||
tcpm_set_cc(port, TYPEC_CC_OPEN);
|
||||
tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ?
|
||||
TYPEC_CC_RD : tcpm_rp_cc(port));
|
||||
tcpm_set_state(port, PORT_RESET_WAIT_OFF,
|
||||
PD_T_ERROR_RECOVERY);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user