diff options
author | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2020-12-01 18:21:40 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2020-12-01 18:21:40 +0300 |
commit | 67e061f044e46c9823e59ca7981786f858bfa292 (patch) | |
tree | 6a7a4e19aa0742ba825dc6a455687d967f77c055 /drivers/usb/cdns3/ep0.c | |
parent | a3f132df0e5f25399c9592c2d14997975ddbf290 (diff) | |
parent | b65054597872ce3aefbc6a666385eabdf9e288da (diff) | |
download | linux-67e061f044e46c9823e59ca7981786f858bfa292.tar.xz |
Merge tag 'v5.10-rc6' into patchwork
Linux 5.10-rc6
* tag 'v5.10-rc6': (1815 commits)
Linux 5.10-rc6
sock: set sk_err to ee_errno on dequeue from errq
mptcp: fix NULL ptr dereference on bad MPJ
net: openvswitch: fix TTL decrement action netlink message format
perf probe: Change function definition check due to broken DWARF
perf probe: Fix to die_entrypc() returns error correctly
perf stat: Use proper cpu for shadow stats
perf record: Synthesize cgroup events only if needed
perf diff: Fix error return value in __cmd_diff()
perf tools: Update copy of libbpf's hashmap.c
x86/mce: Do not overwrite no_way_out if mce_end() fails
kvm: x86/mmu: Fix get_mmio_spte() on CPUs supporting 5-level PT
KVM: x86: Fix split-irqchip vs interrupt injection window request
KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
usb: typec: stusb160x: fix power-opmode property with typec-power-opmode
printk: finalize records with trailing newlines
can: af_can: can_rx_unregister(): remove WARN() statement from list operation sanity check
can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from request_threaded_irq()'s flags
...
Diffstat (limited to 'drivers/usb/cdns3/ep0.c')
-rw-r--r-- | drivers/usb/cdns3/ep0.c | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c index 4761c852d9c4..d3121a32cc68 100644 --- a/drivers/usb/cdns3/ep0.c +++ b/drivers/usb/cdns3/ep0.c @@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, struct usb_ctrlrequest *ctrl_req) { enum usb_device_state device_state = priv_dev->gadget.state; - struct cdns3_endpoint *priv_ep; u32 config = le16_to_cpu(ctrl_req->wValue); int result = 0; - int i; switch (device_state) { 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); - if (result) - return result; - - if (!config) { - cdns3_hw_reset_eps_config(priv_dev); - usb_gadget_set_state(&priv_dev->gadget, - USB_STATE_ADDRESS); - } + if (result || !config) + goto reset_config; break; case USB_STATE_CONFIGURED: 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; 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; } @@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, unsigned long flags; int ret = 0; u8 zlp = 0; + int i; spin_lock_irqsave(&priv_dev->lock, flags); trace_cdns3_ep0_queue(priv_dev, request); @@ -720,6 +709,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, u32 val; 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_ep0_complete_setup(priv_dev, 0, 1); /* wait until configuration set */ @@ -811,6 +811,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) struct cdns3_usb_regs __iomem *regs; struct cdns3_endpoint *priv_ep; u32 max_packet_size = 64; + u32 ep_cfg; regs = priv_dev->regs; @@ -842,8 +843,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) BIT(0) | BIT(16)); } - writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), - ®s->ep_cfg); + ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size); + + if (!(priv_ep->flags & EP_CONFIGURED)) + writel(ep_cfg, ®s->ep_cfg); writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN, ®s->ep_sts_en); @@ -851,8 +854,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) /* init ep in */ cdns3_select_ep(priv_dev, USB_DIR_IN); - writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), - ®s->ep_cfg); + if (!(priv_ep->flags & EP_CONFIGURED)) + writel(ep_cfg, ®s->ep_cfg); + + priv_ep->flags |= EP_CONFIGURED; writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, ®s->ep_sts_en); |