Commit 9b5ff3c9 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB driver fixes from Greg KH:
 "Here are a number of small bugfixes for reported issues in some USB
  drivers. They include:

   - typec bugfixes

   - xhci bugfixes and lockdep warning fixes

   - cdc-acm driver regression fix

   - kernel doc fixes

   - cdns3 driver bugfixes for a bunch of reported issues

   - other tiny USB driver fixes

  All have been in linux-next with no reported issues"

* tag 'usb-5.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: cdns3: gadget: own the lock wrongly at the suspend routine
  usb: cdns3: Fix on-chip memory overflow issue
  usb: cdns3: gadget: suspicious implicit sign extension
  xhci: Don't create stream debugfs files with spinlock held.
  usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
  xhci: Fix sizeof() mismatch
  usb: typec: stusb160x: fix signedness comparison issue with enum variables
  usb: typec: add missing MODULE_DEVICE_TABLE() to stusb160x
  USB: apple-mfi-fastcharge: don't probe unhandled devices
  usbcore: Check both id_table and match() when both available
  usb: host: ehci-tegra: Fix error handling in tegra_ehci_probe()
  usb: typec: stusb160x: fix an IS_ERR() vs NULL check in probe
  usb: typec: tcpm: reset hard_reset_count for any disconnect
  usb: cdc-acm: fix cooldown mechanism
  usb: host: fsl-mph-dr-of: check return of dma_set_mask()
  usb: fix kernel-doc markups
  usb: typec: stusb160x: fix some signedness bugs
  usb: cdns3: Variable 'length' set but not used
parents 2d38c80d 00c27a1d
...@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, ...@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev,
struct usb_ctrlrequest *ctrl_req) struct usb_ctrlrequest *ctrl_req)
{ {
enum usb_device_state device_state = priv_dev->gadget.state; enum usb_device_state device_state = priv_dev->gadget.state;
struct cdns3_endpoint *priv_ep;
u32 config = le16_to_cpu(ctrl_req->wValue); u32 config = le16_to_cpu(ctrl_req->wValue);
int result = 0; int result = 0;
int i;
switch (device_state) { switch (device_state) {
case USB_STATE_ADDRESS: case USB_STATE_ADDRESS:
/* Configure non-control EPs */
for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
priv_ep = priv_dev->eps[i];
if (!priv_ep)
continue;
if (priv_ep->flags & EP_CLAIMED)
cdns3_ep_config(priv_ep);
}
result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
if (result) if (result || !config)
return result; goto reset_config;
if (!config) {
cdns3_hw_reset_eps_config(priv_dev);
usb_gadget_set_state(&priv_dev->gadget,
USB_STATE_ADDRESS);
}
break; break;
case USB_STATE_CONFIGURED: case USB_STATE_CONFIGURED:
result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
if (!config && !result)
goto reset_config;
if (!config && !result) {
cdns3_hw_reset_eps_config(priv_dev);
usb_gadget_set_state(&priv_dev->gadget,
USB_STATE_ADDRESS);
}
break; break;
default: default:
result = -EINVAL; return -EINVAL;
} }
return 0;
reset_config:
if (result != USB_GADGET_DELAYED_STATUS)
cdns3_hw_reset_eps_config(priv_dev);
usb_gadget_set_state(&priv_dev->gadget,
USB_STATE_ADDRESS);
return result; return result;
} }
...@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, ...@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
u8 zlp = 0; u8 zlp = 0;
int i;
spin_lock_irqsave(&priv_dev->lock, flags); spin_lock_irqsave(&priv_dev->lock, flags);
trace_cdns3_ep0_queue(priv_dev, request); trace_cdns3_ep0_queue(priv_dev, request);
...@@ -720,6 +709,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, ...@@ -720,6 +709,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
u32 val; u32 val;
cdns3_select_ep(priv_dev, 0x00); cdns3_select_ep(priv_dev, 0x00);
/*
* Configure all non-control EPs which are not enabled by class driver
*/
for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
priv_ep = priv_dev->eps[i];
if (priv_ep && priv_ep->flags & EP_CLAIMED &&
!(priv_ep->flags & EP_ENABLED))
cdns3_ep_config(priv_ep, 0);
}
cdns3_set_hw_configuration(priv_dev); cdns3_set_hw_configuration(priv_dev);
cdns3_ep0_complete_setup(priv_dev, 0, 1); cdns3_ep0_complete_setup(priv_dev, 0, 1);
/* wait until configuration set */ /* wait until configuration set */
...@@ -811,6 +811,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) ...@@ -811,6 +811,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
struct cdns3_usb_regs __iomem *regs; struct cdns3_usb_regs __iomem *regs;
struct cdns3_endpoint *priv_ep; struct cdns3_endpoint *priv_ep;
u32 max_packet_size = 64; u32 max_packet_size = 64;
u32 ep_cfg;
regs = priv_dev->regs; regs = priv_dev->regs;
...@@ -842,8 +843,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) ...@@ -842,8 +843,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
BIT(0) | BIT(16)); BIT(0) | BIT(16));
} }
writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size);
&regs->ep_cfg);
if (!(priv_ep->flags & EP_CONFIGURED))
writel(ep_cfg, &regs->ep_cfg);
writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN, writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN,
&regs->ep_sts_en); &regs->ep_sts_en);
...@@ -851,8 +854,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) ...@@ -851,8 +854,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
/* init ep in */ /* init ep in */
cdns3_select_ep(priv_dev, USB_DIR_IN); cdns3_select_ep(priv_dev, USB_DIR_IN);
writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), if (!(priv_ep->flags & EP_CONFIGURED))
&regs->ep_cfg); writel(ep_cfg, &regs->ep_cfg);
priv_ep->flags |= EP_CONFIGURED;
writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, &regs->ep_sts_en); writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, &regs->ep_sts_en);
......
...@@ -296,6 +296,8 @@ static void cdns3_ep_stall_flush(struct cdns3_endpoint *priv_ep) ...@@ -296,6 +296,8 @@ static void cdns3_ep_stall_flush(struct cdns3_endpoint *priv_ep)
*/ */
void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev) void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
{ {
int i;
writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf); writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf);
cdns3_allow_enable_l1(priv_dev, 0); cdns3_allow_enable_l1(priv_dev, 0);
...@@ -304,6 +306,10 @@ void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev) ...@@ -304,6 +306,10 @@ void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
priv_dev->out_mem_is_allocated = 0; priv_dev->out_mem_is_allocated = 0;
priv_dev->wait_for_setup = 0; priv_dev->wait_for_setup = 0;
priv_dev->using_streams = 0; priv_dev->using_streams = 0;
for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++)
if (priv_dev->eps[i])
priv_dev->eps[i]->flags &= ~EP_CONFIGURED;
} }
/** /**
...@@ -506,7 +512,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, ...@@ -506,7 +512,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
while (!list_empty(&priv_ep->wa2_descmiss_req_list)) { while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
int chunk_end; int chunk_end;
int length;
descmiss_priv_req = descmiss_priv_req =
cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
...@@ -517,7 +522,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, ...@@ -517,7 +522,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
break; break;
chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH;
length = request->actual + descmiss_req->actual;
request->status = descmiss_req->status; request->status = descmiss_req->status;
__cdns3_descmiss_copy_data(request, descmiss_req); __cdns3_descmiss_copy_data(request, descmiss_req);
list_del_init(&descmiss_priv_req->list); list_del_init(&descmiss_priv_req->list);
...@@ -1746,11 +1750,8 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) ...@@ -1746,11 +1750,8 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)
static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev) static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
{ {
if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect) { if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect)
spin_unlock(&priv_dev->lock);
priv_dev->gadget_driver->disconnect(&priv_dev->gadget); priv_dev->gadget_driver->disconnect(&priv_dev->gadget);
spin_lock(&priv_dev->lock);
}
} }
/** /**
...@@ -1761,6 +1762,7 @@ static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev) ...@@ -1761,6 +1762,7 @@ static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
*/ */
static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev, static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
u32 usb_ists) u32 usb_ists)
__must_hold(&priv_dev->lock)
{ {
int speed = 0; int speed = 0;
...@@ -1785,7 +1787,9 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev, ...@@ -1785,7 +1787,9 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
/* Disconnection detected */ /* Disconnection detected */
if (usb_ists & (USB_ISTS_DIS2I | USB_ISTS_DISI)) { if (usb_ists & (USB_ISTS_DIS2I | USB_ISTS_DISI)) {
spin_unlock(&priv_dev->lock);
cdns3_disconnect_gadget(priv_dev); cdns3_disconnect_gadget(priv_dev);
spin_lock(&priv_dev->lock);
priv_dev->gadget.speed = USB_SPEED_UNKNOWN; priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED); usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
cdns3_hw_reset_eps_config(priv_dev); cdns3_hw_reset_eps_config(priv_dev);
...@@ -1979,27 +1983,6 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev, ...@@ -1979,27 +1983,6 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
return 0; return 0;
} }
static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep)
{
if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
return;
if (priv_dev->dev_ver >= DEV_VER_V3) {
u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
/*
* Stream capable endpoints are handled by using ep_tdl
* register. Other endpoints use TDL from TRB feature.
*/
cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb, mask);
}
/* Enable Stream Bit TDL chk and SID chk */
cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_STREAM_EN |
EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
}
static void cdns3_configure_dmult(struct cdns3_device *priv_dev, static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep) struct cdns3_endpoint *priv_ep)
{ {
...@@ -2037,8 +2020,9 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev, ...@@ -2037,8 +2020,9 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
/** /**
* cdns3_ep_config Configure hardware endpoint * cdns3_ep_config Configure hardware endpoint
* @priv_ep: extended endpoint object * @priv_ep: extended endpoint object
* @enable: set EP_CFG_ENABLE bit in ep_cfg register.
*/ */
void cdns3_ep_config(struct cdns3_endpoint *priv_ep) int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
{ {
bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC); bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC);
struct cdns3_device *priv_dev = priv_ep->cdns3_dev; struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
...@@ -2099,7 +2083,7 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep) ...@@ -2099,7 +2083,7 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
break; break;
default: default:
/* all other speed are not supported */ /* all other speed are not supported */
return; return -EINVAL;
} }
if (max_packet_size == 1024) if (max_packet_size == 1024)
...@@ -2109,11 +2093,33 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep) ...@@ -2109,11 +2093,33 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
else else
priv_ep->trb_burst_size = 16; priv_ep->trb_burst_size = 16;
ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1, /* onchip buffer is only allocated before configuration */
!!priv_ep->dir); if (!priv_dev->hw_configured_flag) {
if (ret) { ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n"); !!priv_ep->dir);
return; if (ret) {
dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
return ret;
}
}
if (enable)
ep_cfg |= EP_CFG_ENABLE;
if (priv_ep->use_streams && priv_dev->gadget.speed >= USB_SPEED_SUPER) {
if (priv_dev->dev_ver >= DEV_VER_V3) {
u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
/*
* Stream capable endpoints are handled by using ep_tdl
* register. Other endpoints use TDL from TRB feature.
*/
cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb,
mask);
}
/* Enable Stream Bit TDL chk and SID chk */
ep_cfg |= EP_CFG_STREAM_EN | EP_CFG_TDL_CHK | EP_CFG_SID_CHK;
} }
ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) | ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) |
...@@ -2123,9 +2129,12 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep) ...@@ -2123,9 +2129,12 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
cdns3_select_ep(priv_dev, bEndpointAddress); cdns3_select_ep(priv_dev, bEndpointAddress);
writel(ep_cfg, &priv_dev->regs->ep_cfg); writel(ep_cfg, &priv_dev->regs->ep_cfg);
priv_ep->flags |= EP_CONFIGURED;
dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n", dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n",
priv_ep->name, ep_cfg); priv_ep->name, ep_cfg);
return 0;
} }
/* Find correct direction for HW endpoint according to description */ /* Find correct direction for HW endpoint according to description */
...@@ -2266,7 +2275,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, ...@@ -2266,7 +2275,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
u32 bEndpointAddress; u32 bEndpointAddress;
unsigned long flags; unsigned long flags;
int enable = 1; int enable = 1;
int ret; int ret = 0;
int val; int val;
priv_ep = ep_to_cdns3_ep(ep); priv_ep = ep_to_cdns3_ep(ep);
...@@ -2305,6 +2314,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, ...@@ -2305,6 +2314,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
bEndpointAddress = priv_ep->num | priv_ep->dir; bEndpointAddress = priv_ep->num | priv_ep->dir;
cdns3_select_ep(priv_dev, bEndpointAddress); cdns3_select_ep(priv_dev, bEndpointAddress);
/*
* For some versions of controller at some point during ISO OUT traffic
* DMA reads Transfer Ring for the EP which has never got doorbell.
* This issue was detected only on simulation, but to avoid this issue
* driver add protection against it. To fix it driver enable ISO OUT
* endpoint before setting DRBL. This special treatment of ISO OUT
* endpoints are recommended by controller specification.
*/
if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir)
enable = 0;
if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) { if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) {
/* /*
* Enable stream support (SS mode) related interrupts * Enable stream support (SS mode) related interrupts
...@@ -2315,13 +2335,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, ...@@ -2315,13 +2335,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
EP_STS_EN_SIDERREN | EP_STS_EN_MD_EXITEN | EP_STS_EN_SIDERREN | EP_STS_EN_MD_EXITEN |
EP_STS_EN_STREAMREN; EP_STS_EN_STREAMREN;
priv_ep->use_streams = true; priv_ep->use_streams = true;
cdns3_stream_ep_reconfig(priv_dev, priv_ep); ret = cdns3_ep_config(priv_ep, enable);
priv_dev->using_streams |= true; priv_dev->using_streams |= true;
} }
} else {
ret = cdns3_ep_config(priv_ep, enable);
} }
ret = cdns3_allocate_trb_pool(priv_ep); if (ret)
goto exit;
ret = cdns3_allocate_trb_pool(priv_ep);
if (ret) if (ret)
goto exit; goto exit;
...@@ -2351,20 +2375,6 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, ...@@ -2351,20 +2375,6 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
writel(reg, &priv_dev->regs->ep_sts_en); writel(reg, &priv_dev->regs->ep_sts_en);
/*
* For some versions of controller at some point during ISO OUT traffic
* DMA reads Transfer Ring for the EP which has never got doorbell.
* This issue was detected only on simulation, but to avoid this issue
* driver add protection against it. To fix it driver enable ISO OUT
* endpoint before setting DRBL. This special treatment of ISO OUT
* endpoints are recommended by controller specification.
*/
if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir)
enable = 0;
if (enable)
cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE);
ep->desc = desc; ep->desc = desc;
priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING | priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING |
EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN); EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN);
...@@ -3265,10 +3275,13 @@ static int __cdns3_gadget_init(struct cdns3 *cdns) ...@@ -3265,10 +3275,13 @@ static int __cdns3_gadget_init(struct cdns3 *cdns)
} }
static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup) static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
__must_hold(&cdns->lock)
{ {
struct cdns3_device *priv_dev = cdns->gadget_dev; struct cdns3_device *priv_dev = cdns->gadget_dev;
spin_unlock(&cdns->lock);
cdns3_disconnect_gadget(priv_dev); cdns3_disconnect_gadget(priv_dev);
spin_lock(&cdns->lock);
priv_dev->gadget.speed = USB_SPEED_UNKNOWN; priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED); usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
......
...@@ -1072,7 +1072,7 @@ struct cdns3_trb { ...@@ -1072,7 +1072,7 @@ struct cdns3_trb {
#define TRB_TDL_SS_SIZE_GET(p) (((p) & GENMASK(23, 17)) >> 17) #define TRB_TDL_SS_SIZE_GET(p) (((p) & GENMASK(23, 17)) >> 17)
/* transfer_len bitmasks - bits 31:24 */ /* transfer_len bitmasks - bits 31:24 */
#define TRB_BURST_LEN(p) (((p) << 24) & GENMASK(31, 24)) #define TRB_BURST_LEN(p) ((unsigned int)((p) << 24) & GENMASK(31, 24))
#define TRB_BURST_LEN_GET(p) (((p) & GENMASK(31, 24)) >> 24) #define TRB_BURST_LEN_GET(p) (((p) & GENMASK(31, 24)) >> 24)
/* Data buffer pointer bitmasks*/ /* Data buffer pointer bitmasks*/
...@@ -1159,6 +1159,7 @@ struct cdns3_endpoint { ...@@ -1159,6 +1159,7 @@ struct cdns3_endpoint {
#define EP_QUIRK_EXTRA_BUF_DET BIT(12) #define EP_QUIRK_EXTRA_BUF_DET BIT(12)
#define EP_QUIRK_EXTRA_BUF_EN BIT(13) #define EP_QUIRK_EXTRA_BUF_EN BIT(13)
#define EP_TDLCHK_EN BIT(15) #define EP_TDLCHK_EN BIT(15)
#define EP_CONFIGURED BIT(16)
u32 flags; u32 flags;
struct cdns3_request *descmis_req; struct cdns3_request *descmis_req;
...@@ -1360,7 +1361,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, ...@@ -1360,7 +1361,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
int cdns3_init_ep0(struct cdns3_device *priv_dev, int cdns3_init_ep0(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep); struct cdns3_endpoint *priv_ep);
void cdns3_ep0_config(struct cdns3_device *priv_dev); void cdns3_ep0_config(struct cdns3_device *priv_dev);
void cdns3_ep_config(struct cdns3_endpoint *priv_ep); int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable);
void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir); void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir);
int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev); int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev);
......
...@@ -508,6 +508,7 @@ static void acm_read_bulk_callback(struct urb *urb) ...@@ -508,6 +508,7 @@ static void acm_read_bulk_callback(struct urb *urb)
"%s - cooling babbling device\n", __func__); "%s - cooling babbling device\n", __func__);
usb_mark_last_busy(acm->dev); usb_mark_last_busy(acm->dev);
set_bit(rb->index, &acm->urbs_in_error_delay); set_bit(rb->index, &acm->urbs_in_error_delay);
set_bit(ACM_ERROR_DELAY, &acm->flags);
cooldown = true; cooldown = true;
break; break;
default: default:
...@@ -533,7 +534,7 @@ static void acm_read_bulk_callback(struct urb *urb) ...@@ -533,7 +534,7 @@ static void acm_read_bulk_callback(struct urb *urb)
if (stopped || stalled || cooldown) { if (stopped || stalled || cooldown) {
if (stalled) if (stalled)
schedule_work(&acm->work); schedule_delayed_work(&acm->dwork, 0);
else if (cooldown) else if (cooldown)
schedule_delayed_work(&acm->dwork, HZ / 2); schedule_delayed_work(&acm->dwork, HZ / 2);
return; return;
...@@ -563,13 +564,13 @@ static void acm_write_bulk(struct urb *urb) ...@@ -563,13 +564,13 @@ static void acm_write_bulk(struct urb *urb)
acm_write_done(acm, wb); acm_write_done(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags); spin_unlock_irqrestore(&acm->write_lock, flags);
set_bit(EVENT_TTY_WAKEUP, &acm->flags); set_bit(EVENT_TTY_WAKEUP, &acm->flags);
schedule_work(&acm->work); schedule_delayed_work(&acm->dwork, 0);
} }
static void acm_softint(struct work_struct *work) static void acm_softint(struct work_struct *work)
{ {
int i; int i;
struct acm *acm = container_of(work, struct acm, work); struct acm *acm = container_of(work, struct acm, dwork.work);
if (test_bit(EVENT_RX_STALL, &acm->flags)) { if (test_bit(EVENT_RX_STALL, &acm->flags)) {
smp_mb(); /* against acm_suspend() */ smp_mb(); /* against acm_suspend() */
...@@ -585,7 +586,7 @@ static void acm_softint(struct work_struct *work) ...@@ -585,7 +586,7 @@ static void acm_softint(struct work_struct *work)
if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) { if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
for (i = 0; i < acm->rx_buflimit; i++) for (i = 0; i < acm->rx_buflimit; i++)
if (test_and_clear_bit(i, &acm->urbs_in_error_delay)) if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
acm_submit_read_urb(acm, i, GFP_NOIO); acm_submit_read_urb(acm, i, GFP_KERNEL);
} }
if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags)) if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
...@@ -1351,7 +1352,6 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1351,7 +1352,6 @@ static int acm_probe(struct usb_interface *intf,
acm->ctrlsize = ctrlsize; acm->ctrlsize = ctrlsize;
acm->readsize = readsize; acm->readsize = readsize;
acm->rx_buflimit = num_rx_buf; acm->rx_buflimit = num_rx_buf;
INIT_WORK(&acm->work, acm_softint);
INIT_DELAYED_WORK(&acm->dwork, acm_softint); INIT_DELAYED_WORK(&acm->dwork, acm_softint);
init_waitqueue_head(&acm->wioctl); init_waitqueue_head(&acm->wioctl);
spin_lock_init(&acm->write_lock); spin_lock_init(&acm->write_lock);
...@@ -1561,7 +1561,6 @@ static void acm_disconnect(struct usb_interface *intf) ...@@ -1561,7 +1561,6 @@ static void acm_disconnect(struct usb_interface *intf)
} }
acm_kill_urbs(acm); acm_kill_urbs(acm);
cancel_work_sync(&acm->work);
cancel_delayed_work_sync(&acm->dwork); cancel_delayed_work_sync(&acm->dwork);
tty_unregister_device(acm_tty_driver, acm->minor); tty_unregister_device(acm_tty_driver, acm->minor);
...@@ -1604,7 +1603,6 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1604,7 +1603,6 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
return 0; return 0;
acm_kill_urbs(acm); acm_kill_urbs(acm);
cancel_work_sync(&acm->work);
cancel_delayed_work_sync(&acm->dwork); cancel_delayed_work_sync(&acm->dwork);
acm->urbs_in_error_delay = 0; acm->urbs_in_error_delay = 0;
......
...@@ -112,8 +112,7 @@ struct acm { ...@@ -112,8 +112,7 @@ struct acm {
# define ACM_ERROR_DELAY 3 # define ACM_ERROR_DELAY 3
unsigned long urbs_in_error_delay; /* these need to be restarted after a delay */ unsigned long urbs_in_error_delay; /* these need to be restarted after a delay */
struct usb_cdc_line_coding line; /* bits, stop, parity */ struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for various purposes*/ struct delayed_work dwork; /* work queue entry for various purposes */
struct delayed_work dwork; /* for cool downs needed in error recovery */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */ unsigned int ctrlout; /* output control lines (DTR, RTS) */
struct async_icount iocount; /* counters for control line changes */ struct async_icount iocount; /* counters for control line changes */
......
...@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev, ...@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
return NULL; return NULL;
} }
bool usb_driver_applicable(struct usb_device *udev,
struct usb_device_driver *udrv)
{
if (udrv->id_table && udrv->match)
return usb_device_match_id(udev, udrv->id_table) != NULL &&
udrv->match(udev);
if (udrv->id_table)
return usb_device_match_id(udev, udrv->id_table) != NULL;
if (udrv->match)
return udrv->match(udev);
return false;
}
static int usb_device_match(struct device *dev, struct device_driver *drv) static int usb_device_match(struct device *dev, struct device_driver *drv)
{ {
/* devices and interfaces are handled separately */ /* devices and interfaces are handled separately */
...@@ -853,17 +869,14 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) ...@@ -853,17 +869,14 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
udev = to_usb_device(dev); udev = to_usb_device(dev);
udrv = to_usb_device_driver(drv); udrv = to_usb_device_driver(drv);
if (udrv->id_table)
return usb_device_match_id(udev, udrv->id_table) != NULL;
if (udrv->match)
return udrv->match(udev);
/* If the device driver under consideration does not have a /* If the device driver under consideration does not have a
* id_table or a match function, then let the driver's probe * id_table or a match function, then let the driver's probe
* function decide. * function decide.
*/ */
return 1; if (!udrv->id_table && !udrv->match)
return 1;
return usb_driver_applicable(udev, udrv);
} else if (is_usb_interface(dev)) { } else if (is_usb_interface(dev)) {
struct usb_interface *intf; struct usb_interface *intf;
...@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(struct device *dev, void *data) ...@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(struct device *dev, void *data)
return 0; return 0;
udev = to_usb_device(dev); udev = to_usb_device(dev);
if (usb_device_match_id(udev, new_udriver->id_table) == NULL && if (!usb_driver_applicable(udev, new_udriver))
(!new_udriver->match || new_udriver->match(udev) == 0))
return 0; return 0;
ret = device_reprobe(dev); ret = device_reprobe(dev);
......
...@@ -205,9 +205,7 @@ static int __check_for_non_generic_match(struct device_driver *drv, void *data) ...@@ -205,9 +205,7 @@ static int __check_for_non_generic_match(struct device_driver *drv, void *data)
udrv = to_usb_device_driver(drv); udrv = to_usb_device_driver(drv);
if (udrv == &usb_generic_driver) if (udrv == &usb_generic_driver)
return 0; return 0;
if (usb_device_match_id(udev, udrv->id_table) != NULL) return usb_driver_applicable(udev, udrv);
return 1;
return (udrv->match && udrv->match(udev));
} }
static bool usb_generic_driver_match(struct usb_device *udev) static bool usb_generic_driver_match(struct usb_device *udev)
......
...@@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_device *dev, ...@@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_device *dev,
const struct usb_device_id *id); const struct usb_device_id *id);
extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev, extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
const struct usb_device_id *id); const struct usb_device_id *id);
extern bool usb_driver_applicable(struct usb_device *udev,
struct usb_device_driver *udrv);
extern void usb_forced_unbind_intf(struct usb_interface *intf); extern void usb_forced_unbind_intf(struct usb_interface *intf);
extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev); extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/** /*
* core.c - DesignWare USB3 DRD Controller Core file * core.c - DesignWare USB3 DRD Controller Core file
* *
* Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
......
...@@ -1277,7 +1277,7 @@ struct dwc3_event_type { ...@@ -1277,7 +1277,7 @@ struct dwc3_event_type {
#define DWC3_DEPEVT_EPCMDCMPLT 0x07 #define DWC3_DEPEVT_EPCMDCMPLT 0x07
/** /**
* struct dwc3_event_depvt - Device Endpoint Events * struct dwc3_event_depevt - Device Endpoint Events
* @one_bit: indicates this is an endpoint event (not used) * @one_bit: indicates this is an endpoint event (not used)
* @endpoint_number: number of the endpoint * @endpoint_number: number of the endpoint
* @endpoint_event: The event we have: * @endpoint_event: The event we have:
......
...@@ -1245,7 +1245,7 @@ int usb_string_id(struct usb_composite_dev *cdev) ...@@ -1245,7 +1245,7 @@ int usb_string_id(struct usb_composite_dev *cdev)
EXPORT_SYMBOL_GPL(usb_string_id); EXPORT_SYMBOL_GPL(usb_string_id);
/** /**
* usb_string_ids() - allocate unused string IDs in batch * usb_string_ids_tab() - allocate unused string IDs in batch
* @cdev: the device whose string descriptor IDs are being allocated * @cdev: the device whose string descriptor IDs are being allocated
* @str: an array of usb_string objects to assign numbers to * @str: an array of usb_string objects to assign numbers to
* Context: single threaded during gadget setup * Context: single threaded during gadget setup
......
...@@ -479,8 +479,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) ...@@ -479,8 +479,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
u_phy->otg->host = hcd_to_bus(hcd); u_phy->otg->host = hcd_to_bus(hcd);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (!irq) { if (irq < 0) {
err = -ENODEV; err = irq;
goto cleanup_phy; goto cleanup_phy;
} }
......
...@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_device_register( ...@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_device_register(
pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask) {
pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
else } else {
dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (retval)
goto error;
}
retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
if (retval) if (retval)
......
...@@ -2252,8 +2252,8 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci, ...@@ -2252,8 +2252,8 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
if (!rhub->num_ports) if (!rhub->num_ports)
return; return;
rhub->ports = kcalloc_node(rhub->num_ports, sizeof(rhub->ports), flags, rhub->ports = kcalloc_node(rhub->num_ports, sizeof(*rhub->ports),
dev_to_node(dev)); flags, dev_to_node(dev));
for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
if (xhci->hw_ports[i].rhub != rhub || if (xhci->hw_ports[i].rhub != rhub ||
xhci->hw_ports[i].hcd_portnum == DUPLICATE_ENTRY) xhci->hw_ports[i].hcd_portnum == DUPLICATE_ENTRY)
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#define SSIC_PORT_CFG2_OFFSET 0x30 #define SSIC_PORT_CFG2_OFFSET 0x30
#define PROG_DONE (1 << 30) #define PROG_DONE (1 << 30)
#define SSIC_PORT_UNUSED (1 << 31) #define SSIC_PORT_UNUSED (1 << 31)
#define SPARSE_DISABLE_BIT 17
#define SPARSE_CNTL_ENABLE 0xC12C
/* Device for a quirk */ /* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
...@@ -161,6 +163,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -161,6 +163,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
(pdev->device == 0x15e0 || pdev->device == 0x15e1)) (pdev->device == 0x15e0 || pdev->device == 0x15e1))
xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
xhci->quirks |= XHCI_DISABLE_SPARSE;
if (pdev->vendor == PCI_VENDOR_ID_AMD) if (pdev->vendor == PCI_VENDOR_ID_AMD)
xhci->quirks |= XHCI_TRUST_TX_LENGTH; xhci->quirks |= XHCI_TRUST_TX_LENGTH;
...@@ -498,6 +503,15 @@ static void xhci_pme_quirk(struct usb_hcd *hcd) ...@@ -498,6 +503,15 @@ static void xhci_pme_quirk(struct usb_hcd *hcd)
readl(reg); readl(reg);
} }
static void xhci_sparse_control_quirk(struct usb_hcd *hcd)
{
u32 reg;
reg = readl(hcd->regs + SPARSE_CNTL_ENABLE);
reg &= ~BIT(SPARSE_DISABLE_BIT);
writel(reg, hcd->regs + SPARSE_CNTL_ENABLE);
}
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{ {
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
...@@ -517,6 +531,9 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) ...@@ -517,6 +531,9 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED) if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
xhci_ssic_port_unused_quirk(hcd, true); xhci_ssic_port_unused_quirk(hcd, true);
if (xhci->quirks & XHCI_DISABLE_SPARSE)
xhci_sparse_control_quirk(hcd);
ret = xhci_suspend(xhci, do_wakeup); ret = xhci_suspend(xhci, do_wakeup);
if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED)) if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
xhci_ssic_port_unused_quirk(hcd, false); xhci_ssic_port_unused_quirk(hcd, false);
......
...@@ -3533,11 +3533,14 @@ static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -3533,11 +3533,14 @@ static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n", xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n",
udev->slot_id, ep_index); udev->slot_id, ep_index);
vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS; vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS;
xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
} }
xhci_free_command(xhci, config_cmd); xhci_free_command(xhci, config_cmd);
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
for (i = 0; i < num_eps; i++) {
ep_index = xhci_get_endpoint_index(&eps[i]->desc);
xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
}
/* Subtract 1 for stream 0, which drivers can't use */ /* Subtract 1 for stream 0, which drivers can't use */
return num_streams - 1; return num_streams - 1;
......
...@@ -1877,6 +1877,7 @@ struct xhci_hcd { ...@@ -1877,6 +1877,7 @@ struct xhci_hcd {
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
#define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) #define XHCI_RENESAS_FW_QUIRK BIT_ULL(36)
#define XHCI_SKIP_PHY_INIT BIT_ULL(37) #define XHCI_SKIP_PHY_INIT BIT_ULL(37)
#define XHCI_DISABLE_SPARSE BIT_ULL(38)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
......
...@@ -163,17 +163,23 @@ static const struct power_supply_desc apple_mfi_fc_desc = { ...@@ -163,17 +163,23 @@ static const struct power_supply_desc apple_mfi_fc_desc = {
.property_is_writeable = apple_mfi_fc_property_is_writeable .property_is_writeable = apple_mfi_fc_property_is_writeable
}; };
static bool mfi_fc_match(struct usb_device *udev)
{
int idProduct;
idProduct = le16_to_cpu(udev->descriptor.idProduct);
/* See comment above mfi_fc_id_table[] */
return (idProduct >= 0x1200 && idProduct <= 0x12ff);
}
static int mfi_fc_probe(struct usb_device *udev) static int mfi_fc_probe(struct usb_device *udev)
{ {
struct power_supply_config battery_cfg = {}; struct power_supply_config battery_cfg = {};
struct mfi_device *mfi = NULL; struct mfi_device *mfi = NULL;
int err, idProduct; int err;
idProduct = le16_to_cpu(udev->descriptor.idProduct); if (!mfi_fc_match(udev))
/* See comment above mfi_fc_id_table[] */
if (idProduct < 0x1200 || idProduct > 0x12ff) {
return -ENODEV; return -ENODEV;
}
mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL); mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL);
if (!mfi) { if (!mfi) {
...@@ -220,6 +226,7 @@ static struct usb_device_driver mfi_fc_driver = { ...@@ -220,6 +226,7 @@ static struct usb_device_driver mfi_fc_driver = {
.probe = mfi_fc_probe, .probe = mfi_fc_probe,
.disconnect = mfi_fc_disconnect, .disconnect = mfi_fc_disconnect,
.id_table = mfi_fc_id_table, .id_table = mfi_fc_id_table,
.match = mfi_fc_match,
.generic_subclass = 1, .generic_subclass = 1,
}; };
......
...@@ -71,7 +71,7 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode) ...@@ -71,7 +71,7 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
/** /**
* typec_put_switch - Release USB Type-C orientation switch * typec_switch_put - Release USB Type-C orientation switch
* @sw: USB Type-C orientation switch * @sw: USB Type-C orientation switch
* *
* Decrement reference count for @sw. * Decrement reference count for @sw.
......
...@@ -544,11 +544,10 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip, ...@@ -544,11 +544,10 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip,
*/ */
ret = fwnode_property_read_string(fwnode, "power-role", &cap_str); ret = fwnode_property_read_string(fwnode, "power-role", &cap_str);
if (!ret) { if (!ret) {
chip->port_type = typec_find_port_power_role(cap_str); ret = typec_find_port_power_role(cap_str);
if (chip->port_type < 0) { if (ret < 0)
ret = chip->port_type;
return ret; return ret;
} chip->port_type = ret;
} }
chip->capability.type = chip->port_type; chip->capability.type = chip->port_type;
...@@ -565,15 +564,13 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip, ...@@ -565,15 +564,13 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip,
*/ */
ret = fwnode_property_read_string(fwnode, "power-opmode", &cap_str); ret = fwnode_property_read_string(fwnode, "power-opmode", &cap_str);
if (!ret) { if (!ret) {
chip->pwr_opmode = typec_find_pwr_opmode(cap_str); ret = typec_find_pwr_opmode(cap_str);
/* Power delivery not yet supported */ /* Power delivery not yet supported */
if (chip->pwr_opmode < 0 || if (ret < 0 || ret == TYPEC_PWR_MODE_PD) {
chip->pwr_opmode == TYPEC_PWR_MODE_PD) { dev_err(chip->dev, "bad power operation mode: %d\n", ret);
ret = chip->pwr_opmode < 0 ? chip->pwr_opmode : -EINVAL; return -EINVAL;
dev_err(chip->dev, "bad power operation mode: %d\n",
chip->pwr_opmode);
return ret;
} }
chip->pwr_opmode = ret;
} }
return 0; return 0;
...@@ -632,6 +629,7 @@ static const struct of_device_id stusb160x_of_match[] = { ...@@ -632,6 +629,7 @@ static const struct of_device_id stusb160x_of_match[] = {
{ .compatible = "st,stusb1600", .data = &stusb1600_regmap_config}, { .compatible = "st,stusb1600", .data = &stusb1600_regmap_config},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, stusb160x_of_match);
static int stusb160x_probe(struct i2c_client *client) static int stusb160x_probe(struct i2c_client *client)
{ {
...@@ -729,8 +727,8 @@ static int stusb160x_probe(struct i2c_client *client) ...@@ -729,8 +727,8 @@ static int stusb160x_probe(struct i2c_client *client)
} }
chip->port = typec_register_port(chip->dev, &chip->capability); chip->port = typec_register_port(chip->dev, &chip->capability);
if (!chip->port) { if (IS_ERR(chip->port)) {
ret = -ENODEV; ret = PTR_ERR(chip->port);
goto all_reg_disable; goto all_reg_disable;
} }
......
...@@ -2890,6 +2890,9 @@ static void tcpm_reset_port(struct tcpm_port *port) ...@@ -2890,6 +2890,9 @@ static void tcpm_reset_port(struct tcpm_port *port)
static void tcpm_detach(struct tcpm_port *port) static void tcpm_detach(struct tcpm_port *port)
{ {
if (tcpm_port_is_disconnected(port))
port->hard_reset_count = 0;
if (!port->attached) if (!port->attached)
return; return;
...@@ -2898,9 +2901,6 @@ static void tcpm_detach(struct tcpm_port *port) ...@@ -2898,9 +2901,6 @@ static void tcpm_detach(struct tcpm_port *port)
port->tcpc->set_bist_data(port->tcpc, false); port->tcpc->set_bist_data(port->tcpc, false);
} }
if (tcpm_port_is_disconnected(port))
port->hard_reset_count = 0;
tcpm_reset_port(port); tcpm_reset_port(port);
} }
......
...@@ -437,7 +437,7 @@ static inline struct usb_composite_driver *to_cdriver( ...@@ -437,7 +437,7 @@ static inline struct usb_composite_driver *to_cdriver(
#define OS_STRING_IDX 0xEE #define OS_STRING_IDX 0xEE
/** /**
* struct usb_composite_device - represents one composite usb gadget * struct usb_composite_dev - represents one composite usb gadget
* @gadget: read-only, abstracts the gadget's usb peripheral controller * @gadget: read-only, abstracts the gadget's usb peripheral controller
* @req: used for control responses; buffer is pre-allocated * @req: used for control responses; buffer is pre-allocated
* @os_desc_req: used for OS descriptors responses; buffer is pre-allocated * @os_desc_req: used for OS descriptors responses; buffer is pre-allocated
......
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