USB fixes for 5.12-rc3
Here are a small number of USB fixes for 5.12-rc3 to resolve a bunch of reported issues: - usbip fixups for issues found by syzbot - xhci driver fixes and quirk additions - gadget driver fixes - dwc3 QCOM driver fix - usb-serial new ids and fixes - usblp fix for a long-time issue - cdc-acm quirk addition - other tiny fixes for reported problems All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYEzR3A8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylgSQCgjkrg8qFJLTss/PNe0/1zQIFNl2sAn2FyPV0y K34seYUf0LDj3OcXRLGl =72FI -----END PGP SIGNATURE----- Merge tag 'usb-5.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are a small number of USB fixes for 5.12-rc3 to resolve a bunch of reported issues: - usbip fixups for issues found by syzbot - xhci driver fixes and quirk additions - gadget driver fixes - dwc3 QCOM driver fix - usb-serial new ids and fixes - usblp fix for a long-time issue - cdc-acm quirk addition - other tiny fixes for reported problems All of these have been in linux-next for a while with no reported issues" * tag 'usb-5.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (25 commits) xhci: Fix repeated xhci wake after suspend due to uncleared internal wake state usb: xhci: Fix ASMedia ASM1042A and ASM3242 DMA addressing xhci: Improve detection of device initiated wake signal. usb: xhci: do not perform Soft Retry for some xHCI hosts usbip: fix vudc usbip_sockfd_store races leading to gpf usbip: fix vhci_hcd attach_store() races leading to gpf usbip: fix stub_dev usbip_sockfd_store() races leading to gpf usbip: fix vudc to check for stream socket usbip: fix vhci_hcd to check for stream socket usbip: fix stub_dev to check for stream socket usb: dwc3: qcom: Add missing DWC3 OF node refcount decrement USB: usblp: fix a hang in poll() if disconnected USB: gadget: udc: s3c2410_udc: fix return value check in s3c2410_udc_probe() usb: renesas_usbhs: Clear PIPECFG for re-enabling pipe with other EPNUM usb: dwc3: qcom: Honor wakeup enabled/disabled state usb: gadget: f_uac1: stop playback on function disable usb: gadget: f_uac2: always increase endpoint max_packet_size by one audio slot USB: gadget: u_ether: Fix a configfs return code usb: dwc3: qcom: add ACPI device id for sc8180x Goodix Fingerprint device is not a modem ...
This commit is contained in:
commit
5c7bdbf882
|
@ -1935,6 +1935,11 @@ static const struct usb_device_id acm_ids[] = {
|
||||||
.driver_info = SEND_ZERO_PACKET,
|
.driver_info = SEND_ZERO_PACKET,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* Exclude Goodix Fingerprint Reader */
|
||||||
|
{ USB_DEVICE(0x27c6, 0x5395),
|
||||||
|
.driver_info = IGNORE_DEVICE,
|
||||||
|
},
|
||||||
|
|
||||||
/* control interfaces without any protocol set */
|
/* control interfaces without any protocol set */
|
||||||
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
|
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
|
||||||
USB_CDC_PROTO_NONE) },
|
USB_CDC_PROTO_NONE) },
|
||||||
|
|
|
@ -494,16 +494,24 @@ static int usblp_release(struct inode *inode, struct file *file)
|
||||||
/* No kernel lock - fine */
|
/* No kernel lock - fine */
|
||||||
static __poll_t usblp_poll(struct file *file, struct poll_table_struct *wait)
|
static __poll_t usblp_poll(struct file *file, struct poll_table_struct *wait)
|
||||||
{
|
{
|
||||||
__poll_t ret;
|
struct usblp *usblp = file->private_data;
|
||||||
|
__poll_t ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
struct usblp *usblp = file->private_data;
|
|
||||||
/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
|
/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
|
||||||
poll_wait(file, &usblp->rwait, wait);
|
poll_wait(file, &usblp->rwait, wait);
|
||||||
poll_wait(file, &usblp->wwait, wait);
|
poll_wait(file, &usblp->wwait, wait);
|
||||||
|
|
||||||
|
mutex_lock(&usblp->mut);
|
||||||
|
if (!usblp->present)
|
||||||
|
ret |= EPOLLHUP;
|
||||||
|
mutex_unlock(&usblp->mut);
|
||||||
|
|
||||||
spin_lock_irqsave(&usblp->lock, flags);
|
spin_lock_irqsave(&usblp->lock, flags);
|
||||||
ret = ((usblp->bidir && usblp->rcomplete) ? EPOLLIN | EPOLLRDNORM : 0) |
|
if (usblp->bidir && usblp->rcomplete)
|
||||||
((usblp->no_paper || usblp->wcomplete) ? EPOLLOUT | EPOLLWRNORM : 0);
|
ret |= EPOLLIN | EPOLLRDNORM;
|
||||||
|
if (usblp->no_paper || usblp->wcomplete)
|
||||||
|
ret |= EPOLLOUT | EPOLLWRNORM;
|
||||||
spin_unlock_irqrestore(&usblp->lock, flags);
|
spin_unlock_irqrestore(&usblp->lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,8 +358,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
|
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
|
||||||
|
|
||||||
|
if (device_may_wakeup(qcom->dev))
|
||||||
|
dwc3_qcom_enable_interrupts(qcom);
|
||||||
|
|
||||||
qcom->is_suspended = true;
|
qcom->is_suspended = true;
|
||||||
dwc3_qcom_enable_interrupts(qcom);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +374,8 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
|
||||||
if (!qcom->is_suspended)
|
if (!qcom->is_suspended)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dwc3_qcom_disable_interrupts(qcom);
|
if (device_may_wakeup(qcom->dev))
|
||||||
|
dwc3_qcom_disable_interrupts(qcom);
|
||||||
|
|
||||||
for (i = 0; i < qcom->num_clocks; i++) {
|
for (i = 0; i < qcom->num_clocks; i++) {
|
||||||
ret = clk_prepare_enable(qcom->clks[i]);
|
ret = clk_prepare_enable(qcom->clks[i]);
|
||||||
|
@ -650,16 +653,19 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
|
||||||
ret = of_platform_populate(np, NULL, NULL, dev);
|
ret = of_platform_populate(np, NULL, NULL, dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
|
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
|
||||||
return ret;
|
goto node_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
qcom->dwc3 = of_find_device_by_node(dwc3_np);
|
qcom->dwc3 = of_find_device_by_node(dwc3_np);
|
||||||
if (!qcom->dwc3) {
|
if (!qcom->dwc3) {
|
||||||
|
ret = -ENODEV;
|
||||||
dev_err(dev, "failed to get dwc3 platform device\n");
|
dev_err(dev, "failed to get dwc3 platform device\n");
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
node_put:
|
||||||
|
of_node_put(dwc3_np);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_device *
|
static struct platform_device *
|
||||||
|
@ -938,6 +944,8 @@ static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = {
|
||||||
static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
|
static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
|
||||||
{ "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
|
{ "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
|
||||||
{ "QCOM0304", (unsigned long)&sdm845_acpi_urs_pdata },
|
{ "QCOM0304", (unsigned long)&sdm845_acpi_urs_pdata },
|
||||||
|
{ "QCOM0497", (unsigned long)&sdm845_acpi_urs_pdata },
|
||||||
|
{ "QCOM04A6", (unsigned long)&sdm845_acpi_pdata },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
|
MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
|
||||||
|
|
|
@ -499,6 +499,7 @@ static void f_audio_disable(struct usb_function *f)
|
||||||
uac1->as_out_alt = 0;
|
uac1->as_out_alt = 0;
|
||||||
uac1->as_in_alt = 0;
|
uac1->as_in_alt = 0;
|
||||||
|
|
||||||
|
u_audio_stop_playback(&uac1->g_audio);
|
||||||
u_audio_stop_capture(&uac1->g_audio);
|
u_audio_stop_capture(&uac1->g_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -478,7 +478,7 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
|
||||||
}
|
}
|
||||||
|
|
||||||
max_size_bw = num_channels(chmask) * ssize *
|
max_size_bw = num_channels(chmask) * ssize *
|
||||||
DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
|
((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
|
||||||
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
|
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
|
||||||
max_size_ep));
|
max_size_ep));
|
||||||
|
|
||||||
|
|
|
@ -182,12 +182,11 @@ out: \
|
||||||
size_t len) \
|
size_t len) \
|
||||||
{ \
|
{ \
|
||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int ret; \
|
int ret = -EINVAL; \
|
||||||
u8 val; \
|
u8 val; \
|
||||||
\
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
ret = sscanf(page, "%02hhx", &val); \
|
if (sscanf(page, "%02hhx", &val) > 0) { \
|
||||||
if (ret > 0) { \
|
|
||||||
opts->_n_ = val; \
|
opts->_n_ = val; \
|
||||||
ret = len; \
|
ret = len; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -1773,8 +1773,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
||||||
udc_info = dev_get_platdata(&pdev->dev);
|
udc_info = dev_get_platdata(&pdev->dev);
|
||||||
|
|
||||||
base_addr = devm_platform_ioremap_resource(pdev, 0);
|
base_addr = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (!base_addr) {
|
if (IS_ERR(base_addr)) {
|
||||||
retval = -ENOMEM;
|
retval = PTR_ERR(base_addr);
|
||||||
goto err_mem;
|
goto err_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
|
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
|
||||||
#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242
|
#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242
|
||||||
#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142
|
#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142
|
||||||
|
#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242
|
||||||
|
|
||||||
static const char hcd_name[] = "xhci_hcd";
|
static const char hcd_name[] = "xhci_hcd";
|
||||||
|
|
||||||
|
@ -276,11 +277,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||||
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI)
|
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI)
|
||||||
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;
|
||||||
|
xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
|
||||||
|
}
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
||||||
(pdev->device == PCI_DEVICE_ID_ASMEDIA_1142_XHCI ||
|
(pdev->device == PCI_DEVICE_ID_ASMEDIA_1142_XHCI ||
|
||||||
pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI))
|
pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI ||
|
||||||
|
pdev->device == PCI_DEVICE_ID_ASMEDIA_3242_XHCI))
|
||||||
xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
|
xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
|
||||||
|
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
||||||
|
@ -295,6 +299,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||||
pdev->device == 0x9026)
|
pdev->device == 0x9026)
|
||||||
xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
|
xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
|
||||||
|
|
||||||
|
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||||
|
(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2 ||
|
||||||
|
pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
|
||||||
|
xhci->quirks |= XHCI_NO_SOFT_RETRY;
|
||||||
|
|
||||||
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
||||||
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
|
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
|
||||||
"QUIRK: Resetting on resume");
|
"QUIRK: Resetting on resume");
|
||||||
|
|
|
@ -2484,7 +2484,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
break;
|
break;
|
||||||
case COMP_USB_TRANSACTION_ERROR:
|
case COMP_USB_TRANSACTION_ERROR:
|
||||||
if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
|
if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
|
||||||
|
(ep_ring->err_count++ > MAX_SOFT_RETRY) ||
|
||||||
le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
|
le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -883,44 +883,42 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
|
||||||
xhci_set_cmd_ring_deq(xhci);
|
xhci_set_cmd_ring_deq(xhci);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
/*
|
||||||
|
* Disable port wake bits if do_wakeup is not set.
|
||||||
|
*
|
||||||
|
* Also clear a possible internal port wake state left hanging for ports that
|
||||||
|
* detected termination but never successfully enumerated (trained to 0U).
|
||||||
|
* Internal wake causes immediate xHCI wake after suspend. PORT_CSC write done
|
||||||
|
* at enumeration clears this wake, force one here as well for unconnected ports
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void xhci_disable_hub_port_wake(struct xhci_hcd *xhci,
|
||||||
|
struct xhci_hub *rhub,
|
||||||
|
bool do_wakeup)
|
||||||
{
|
{
|
||||||
struct xhci_port **ports;
|
|
||||||
int port_index;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 t1, t2, portsc;
|
u32 t1, t2, portsc;
|
||||||
|
int i;
|
||||||
|
|
||||||
spin_lock_irqsave(&xhci->lock, flags);
|
spin_lock_irqsave(&xhci->lock, flags);
|
||||||
|
|
||||||
/* disable usb3 ports Wake bits */
|
for (i = 0; i < rhub->num_ports; i++) {
|
||||||
port_index = xhci->usb3_rhub.num_ports;
|
portsc = readl(rhub->ports[i]->addr);
|
||||||
ports = xhci->usb3_rhub.ports;
|
t1 = xhci_port_state_to_neutral(portsc);
|
||||||
while (port_index--) {
|
t2 = t1;
|
||||||
t1 = readl(ports[port_index]->addr);
|
|
||||||
portsc = t1;
|
/* clear wake bits if do_wake is not set */
|
||||||
t1 = xhci_port_state_to_neutral(t1);
|
if (!do_wakeup)
|
||||||
t2 = t1 & ~PORT_WAKE_BITS;
|
t2 &= ~PORT_WAKE_BITS;
|
||||||
if (t1 != t2) {
|
|
||||||
writel(t2, ports[port_index]->addr);
|
/* Don't touch csc bit if connected or connect change is set */
|
||||||
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
|
if (!(portsc & (PORT_CSC | PORT_CONNECT)))
|
||||||
xhci->usb3_rhub.hcd->self.busnum,
|
t2 |= PORT_CSC;
|
||||||
port_index + 1, portsc, t2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable usb2 ports Wake bits */
|
|
||||||
port_index = xhci->usb2_rhub.num_ports;
|
|
||||||
ports = xhci->usb2_rhub.ports;
|
|
||||||
while (port_index--) {
|
|
||||||
t1 = readl(ports[port_index]->addr);
|
|
||||||
portsc = t1;
|
|
||||||
t1 = xhci_port_state_to_neutral(t1);
|
|
||||||
t2 = t1 & ~PORT_WAKE_BITS;
|
|
||||||
if (t1 != t2) {
|
if (t1 != t2) {
|
||||||
writel(t2, ports[port_index]->addr);
|
writel(t2, rhub->ports[i]->addr);
|
||||||
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
|
xhci_dbg(xhci, "config port %d-%d wake bits, portsc: 0x%x, write: 0x%x\n",
|
||||||
xhci->usb2_rhub.hcd->self.busnum,
|
rhub->hcd->self.busnum, i + 1, portsc, t2);
|
||||||
port_index + 1, portsc, t2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||||
|
@ -983,8 +981,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Clear root port wake on bits if wakeup not allowed. */
|
/* Clear root port wake on bits if wakeup not allowed. */
|
||||||
if (!do_wakeup)
|
xhci_disable_hub_port_wake(xhci, &xhci->usb3_rhub, do_wakeup);
|
||||||
xhci_disable_port_wake_on_bits(xhci);
|
xhci_disable_hub_port_wake(xhci, &xhci->usb2_rhub, do_wakeup);
|
||||||
|
|
||||||
if (!HCD_HW_ACCESSIBLE(hcd))
|
if (!HCD_HW_ACCESSIBLE(hcd))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1088,6 +1086,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||||
struct usb_hcd *secondary_hcd;
|
struct usb_hcd *secondary_hcd;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
bool comp_timer_running = false;
|
bool comp_timer_running = false;
|
||||||
|
bool pending_portevent = false;
|
||||||
|
|
||||||
if (!hcd->state)
|
if (!hcd->state)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1226,13 +1225,22 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
/* Resume root hubs only when have pending events. */
|
/*
|
||||||
if (xhci_pending_portevent(xhci)) {
|
* Resume roothubs only if there are pending events.
|
||||||
|
* USB 3 devices resend U3 LFPS wake after a 100ms delay if
|
||||||
|
* the first wake signalling failed, give it that chance.
|
||||||
|
*/
|
||||||
|
pending_portevent = xhci_pending_portevent(xhci);
|
||||||
|
if (!pending_portevent) {
|
||||||
|
msleep(120);
|
||||||
|
pending_portevent = xhci_pending_portevent(xhci);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending_portevent) {
|
||||||
usb_hcd_resume_root_hub(xhci->shared_hcd);
|
usb_hcd_resume_root_hub(xhci->shared_hcd);
|
||||||
usb_hcd_resume_root_hub(hcd);
|
usb_hcd_resume_root_hub(hcd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If system is subject to the Quirk, Compliance Mode Timer needs to
|
* If system is subject to the Quirk, Compliance Mode Timer needs to
|
||||||
* be re-initialized Always after a system resume. Ports are subject
|
* be re-initialized Always after a system resume. Ports are subject
|
||||||
|
|
|
@ -1891,6 +1891,7 @@ struct xhci_hcd {
|
||||||
#define XHCI_SKIP_PHY_INIT BIT_ULL(37)
|
#define XHCI_SKIP_PHY_INIT BIT_ULL(37)
|
||||||
#define XHCI_DISABLE_SPARSE BIT_ULL(38)
|
#define XHCI_DISABLE_SPARSE BIT_ULL(38)
|
||||||
#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)
|
#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)
|
||||||
|
#define XHCI_NO_SOFT_RETRY BIT_ULL(40)
|
||||||
|
|
||||||
unsigned int num_active_eps;
|
unsigned int num_active_eps;
|
||||||
unsigned int limit_active_eps;
|
unsigned int limit_active_eps;
|
||||||
|
|
|
@ -746,6 +746,8 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
|
||||||
|
|
||||||
void usbhs_pipe_free(struct usbhs_pipe *pipe)
|
void usbhs_pipe_free(struct usbhs_pipe *pipe)
|
||||||
{
|
{
|
||||||
|
usbhsp_pipe_select(pipe);
|
||||||
|
usbhsp_pipe_cfg_set(pipe, 0xFFFF, 0);
|
||||||
usbhsp_put_pipe(pipe);
|
usbhsp_put_pipe(pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ static const struct usb_device_id id_table[] = {
|
||||||
{ USB_DEVICE(0x1a86, 0x7522) },
|
{ USB_DEVICE(0x1a86, 0x7522) },
|
||||||
{ USB_DEVICE(0x1a86, 0x7523) },
|
{ USB_DEVICE(0x1a86, 0x7523) },
|
||||||
{ USB_DEVICE(0x4348, 0x5523) },
|
{ USB_DEVICE(0x4348, 0x5523) },
|
||||||
|
{ USB_DEVICE(0x9986, 0x7523) },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(usb, id_table);
|
MODULE_DEVICE_TABLE(usb, id_table);
|
||||||
|
|
|
@ -145,6 +145,7 @@ static const struct usb_device_id id_table[] = {
|
||||||
{ USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
|
{ USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
|
||||||
{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
|
{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
|
||||||
{ USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
|
{ USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
|
||||||
|
{ USB_DEVICE(0x10C4, 0x88D8) }, /* Acuity Brands nLight Air Adapter */
|
||||||
{ USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */
|
{ USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */
|
||||||
{ USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */
|
{ USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */
|
||||||
{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
|
{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
|
||||||
|
@ -201,6 +202,8 @@ static const struct usb_device_id id_table[] = {
|
||||||
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
|
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
|
||||||
{ USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */
|
{ USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */
|
||||||
{ USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
|
{ USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
|
||||||
|
{ USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */
|
||||||
|
{ USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */
|
||||||
{ USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */
|
{ USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */
|
||||||
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
|
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
|
||||||
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
||||||
|
|
|
@ -3003,26 +3003,32 @@ static int edge_startup(struct usb_serial *serial)
|
||||||
response = -ENODEV;
|
response = -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_free_urb(edge_serial->interrupt_read_urb);
|
goto error;
|
||||||
kfree(edge_serial->interrupt_in_buffer);
|
|
||||||
|
|
||||||
usb_free_urb(edge_serial->read_urb);
|
|
||||||
kfree(edge_serial->bulk_in_buffer);
|
|
||||||
|
|
||||||
kfree(edge_serial);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start interrupt read for this edgeport this interrupt will
|
/* start interrupt read for this edgeport this interrupt will
|
||||||
* continue as long as the edgeport is connected */
|
* continue as long as the edgeport is connected */
|
||||||
response = usb_submit_urb(edge_serial->interrupt_read_urb,
|
response = usb_submit_urb(edge_serial->interrupt_read_urb,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (response)
|
if (response) {
|
||||||
dev_err(ddev, "%s - Error %d submitting control urb\n",
|
dev_err(ddev, "%s - Error %d submitting control urb\n",
|
||||||
__func__, response);
|
__func__, response);
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
|
error:
|
||||||
|
usb_free_urb(edge_serial->interrupt_read_urb);
|
||||||
|
kfree(edge_serial->interrupt_in_buffer);
|
||||||
|
|
||||||
|
usb_free_urb(edge_serial->read_urb);
|
||||||
|
kfree(edge_serial->bulk_in_buffer);
|
||||||
|
|
||||||
|
kfree(edge_serial);
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -545,37 +545,13 @@ static void xr_close(struct usb_serial_port *port)
|
||||||
|
|
||||||
static int xr_probe(struct usb_serial *serial, const struct usb_device_id *id)
|
static int xr_probe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct usb_driver *driver = serial->type->usb_driver;
|
|
||||||
struct usb_interface *control_interface;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Don't bind to control interface */
|
/* Don't bind to control interface */
|
||||||
if (serial->interface->cur_altsetting->desc.bInterfaceNumber == 0)
|
if (serial->interface->cur_altsetting->desc.bInterfaceNumber == 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* But claim the control interface during data interface probe */
|
|
||||||
control_interface = usb_ifnum_to_if(serial->dev, 0);
|
|
||||||
if (!control_interface)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
ret = usb_driver_claim_interface(driver, control_interface, NULL);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(&serial->interface->dev, "Failed to claim control interface\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xr_disconnect(struct usb_serial *serial)
|
|
||||||
{
|
|
||||||
struct usb_driver *driver = serial->type->usb_driver;
|
|
||||||
struct usb_interface *control_interface;
|
|
||||||
|
|
||||||
control_interface = usb_ifnum_to_if(serial->dev, 0);
|
|
||||||
usb_driver_release_interface(driver, control_interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct usb_device_id id_table[] = {
|
static const struct usb_device_id id_table[] = {
|
||||||
{ USB_DEVICE(0x04e2, 0x1410) }, /* XR21V141X */
|
{ USB_DEVICE(0x04e2, 0x1410) }, /* XR21V141X */
|
||||||
{ }
|
{ }
|
||||||
|
@ -590,7 +566,6 @@ static struct usb_serial_driver xr_device = {
|
||||||
.id_table = id_table,
|
.id_table = id_table,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.probe = xr_probe,
|
.probe = xr_probe,
|
||||||
.disconnect = xr_disconnect,
|
|
||||||
.open = xr_open,
|
.open = xr_open,
|
||||||
.close = xr_close,
|
.close = xr_close,
|
||||||
.break_ctl = xr_break_ctl,
|
.break_ctl = xr_break_ctl,
|
||||||
|
|
|
@ -46,6 +46,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
int sockfd = 0;
|
int sockfd = 0;
|
||||||
struct socket *socket;
|
struct socket *socket;
|
||||||
int rv;
|
int rv;
|
||||||
|
struct task_struct *tcp_rx = NULL;
|
||||||
|
struct task_struct *tcp_tx = NULL;
|
||||||
|
|
||||||
if (!sdev) {
|
if (!sdev) {
|
||||||
dev_err(dev, "sdev is null\n");
|
dev_err(dev, "sdev is null\n");
|
||||||
|
@ -69,23 +71,47 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
}
|
}
|
||||||
|
|
||||||
socket = sockfd_lookup(sockfd, &err);
|
socket = sockfd_lookup(sockfd, &err);
|
||||||
if (!socket)
|
if (!socket) {
|
||||||
|
dev_err(dev, "failed to lookup sock");
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket->type != SOCK_STREAM) {
|
||||||
|
dev_err(dev, "Expecting SOCK_STREAM - found %d",
|
||||||
|
socket->type);
|
||||||
|
goto sock_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock and create threads and get tasks */
|
||||||
|
spin_unlock_irq(&sdev->ud.lock);
|
||||||
|
tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
|
||||||
|
if (IS_ERR(tcp_rx)) {
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
|
||||||
|
if (IS_ERR(tcp_tx)) {
|
||||||
|
kthread_stop(tcp_rx);
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get task structs now */
|
||||||
|
get_task_struct(tcp_rx);
|
||||||
|
get_task_struct(tcp_tx);
|
||||||
|
|
||||||
|
/* lock and update sdev->ud state */
|
||||||
|
spin_lock_irq(&sdev->ud.lock);
|
||||||
sdev->ud.tcp_socket = socket;
|
sdev->ud.tcp_socket = socket;
|
||||||
sdev->ud.sockfd = sockfd;
|
sdev->ud.sockfd = sockfd;
|
||||||
|
sdev->ud.tcp_rx = tcp_rx;
|
||||||
spin_unlock_irq(&sdev->ud.lock);
|
sdev->ud.tcp_tx = tcp_tx;
|
||||||
|
|
||||||
sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
|
|
||||||
"stub_rx");
|
|
||||||
sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
|
|
||||||
"stub_tx");
|
|
||||||
|
|
||||||
spin_lock_irq(&sdev->ud.lock);
|
|
||||||
sdev->ud.status = SDEV_ST_USED;
|
sdev->ud.status = SDEV_ST_USED;
|
||||||
spin_unlock_irq(&sdev->ud.lock);
|
spin_unlock_irq(&sdev->ud.lock);
|
||||||
|
|
||||||
|
wake_up_process(sdev->ud.tcp_rx);
|
||||||
|
wake_up_process(sdev->ud.tcp_tx);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dev_info(dev, "stub down\n");
|
dev_info(dev, "stub down\n");
|
||||||
|
|
||||||
|
@ -100,6 +126,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
sock_err:
|
||||||
|
sockfd_put(socket);
|
||||||
err:
|
err:
|
||||||
spin_unlock_irq(&sdev->ud.lock);
|
spin_unlock_irq(&sdev->ud.lock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -312,6 +312,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||||
struct vhci *vhci;
|
struct vhci *vhci;
|
||||||
int err;
|
int err;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct task_struct *tcp_rx = NULL;
|
||||||
|
struct task_struct *tcp_tx = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @rhport: port number of vhci_hcd
|
* @rhport: port number of vhci_hcd
|
||||||
|
@ -349,12 +351,35 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
/* Extract socket from fd. */
|
/* Extract socket from fd. */
|
||||||
socket = sockfd_lookup(sockfd, &err);
|
socket = sockfd_lookup(sockfd, &err);
|
||||||
if (!socket)
|
if (!socket) {
|
||||||
|
dev_err(dev, "failed to lookup sock");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (socket->type != SOCK_STREAM) {
|
||||||
|
dev_err(dev, "Expecting SOCK_STREAM - found %d",
|
||||||
|
socket->type);
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* now need lock until setting vdev status as used */
|
/* create threads before locking */
|
||||||
|
tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
|
||||||
|
if (IS_ERR(tcp_rx)) {
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
|
||||||
|
if (IS_ERR(tcp_tx)) {
|
||||||
|
kthread_stop(tcp_rx);
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* begin a lock */
|
/* get task structs now */
|
||||||
|
get_task_struct(tcp_rx);
|
||||||
|
get_task_struct(tcp_tx);
|
||||||
|
|
||||||
|
/* now begin lock until setting vdev status set */
|
||||||
spin_lock_irqsave(&vhci->lock, flags);
|
spin_lock_irqsave(&vhci->lock, flags);
|
||||||
spin_lock(&vdev->ud.lock);
|
spin_lock(&vdev->ud.lock);
|
||||||
|
|
||||||
|
@ -364,6 +389,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||||
spin_unlock_irqrestore(&vhci->lock, flags);
|
spin_unlock_irqrestore(&vhci->lock, flags);
|
||||||
|
|
||||||
sockfd_put(socket);
|
sockfd_put(socket);
|
||||||
|
kthread_stop_put(tcp_rx);
|
||||||
|
kthread_stop_put(tcp_tx);
|
||||||
|
|
||||||
dev_err(dev, "port %d already used\n", rhport);
|
dev_err(dev, "port %d already used\n", rhport);
|
||||||
/*
|
/*
|
||||||
|
@ -382,6 +409,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||||
vdev->speed = speed;
|
vdev->speed = speed;
|
||||||
vdev->ud.sockfd = sockfd;
|
vdev->ud.sockfd = sockfd;
|
||||||
vdev->ud.tcp_socket = socket;
|
vdev->ud.tcp_socket = socket;
|
||||||
|
vdev->ud.tcp_rx = tcp_rx;
|
||||||
|
vdev->ud.tcp_tx = tcp_tx;
|
||||||
vdev->ud.status = VDEV_ST_NOTASSIGNED;
|
vdev->ud.status = VDEV_ST_NOTASSIGNED;
|
||||||
usbip_kcov_handle_init(&vdev->ud);
|
usbip_kcov_handle_init(&vdev->ud);
|
||||||
|
|
||||||
|
@ -389,8 +418,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||||
spin_unlock_irqrestore(&vhci->lock, flags);
|
spin_unlock_irqrestore(&vhci->lock, flags);
|
||||||
/* end the lock */
|
/* end the lock */
|
||||||
|
|
||||||
vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
|
wake_up_process(vdev->ud.tcp_rx);
|
||||||
vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
|
wake_up_process(vdev->ud.tcp_tx);
|
||||||
|
|
||||||
rh_port_connect(vdev, speed);
|
rh_port_connect(vdev, speed);
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,9 @@ unlock:
|
||||||
}
|
}
|
||||||
static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
|
static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
|
||||||
|
|
||||||
static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr,
|
static ssize_t usbip_sockfd_store(struct device *dev,
|
||||||
const char *in, size_t count)
|
struct device_attribute *attr,
|
||||||
|
const char *in, size_t count)
|
||||||
{
|
{
|
||||||
struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
|
struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
|
||||||
int rv;
|
int rv;
|
||||||
|
@ -100,6 +101,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
struct socket *socket;
|
struct socket *socket;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct task_struct *tcp_rx = NULL;
|
||||||
|
struct task_struct *tcp_tx = NULL;
|
||||||
|
|
||||||
rv = kstrtoint(in, 0, &sockfd);
|
rv = kstrtoint(in, 0, &sockfd);
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
|
@ -138,24 +141,54 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
goto unlock_ud;
|
goto unlock_ud;
|
||||||
}
|
}
|
||||||
|
|
||||||
udc->ud.tcp_socket = socket;
|
if (socket->type != SOCK_STREAM) {
|
||||||
|
dev_err(dev, "Expecting SOCK_STREAM - found %d",
|
||||||
|
socket->type);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto sock_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock and create threads and get tasks */
|
||||||
spin_unlock_irq(&udc->ud.lock);
|
spin_unlock_irq(&udc->ud.lock);
|
||||||
spin_unlock_irqrestore(&udc->lock, flags);
|
spin_unlock_irqrestore(&udc->lock, flags);
|
||||||
|
|
||||||
udc->ud.tcp_rx = kthread_get_run(&v_rx_loop,
|
tcp_rx = kthread_create(&v_rx_loop, &udc->ud, "vudc_rx");
|
||||||
&udc->ud, "vudc_rx");
|
if (IS_ERR(tcp_rx)) {
|
||||||
udc->ud.tcp_tx = kthread_get_run(&v_tx_loop,
|
sockfd_put(socket);
|
||||||
&udc->ud, "vudc_tx");
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
tcp_tx = kthread_create(&v_tx_loop, &udc->ud, "vudc_tx");
|
||||||
|
if (IS_ERR(tcp_tx)) {
|
||||||
|
kthread_stop(tcp_rx);
|
||||||
|
sockfd_put(socket);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get task structs now */
|
||||||
|
get_task_struct(tcp_rx);
|
||||||
|
get_task_struct(tcp_tx);
|
||||||
|
|
||||||
|
/* lock and update udc->ud state */
|
||||||
spin_lock_irqsave(&udc->lock, flags);
|
spin_lock_irqsave(&udc->lock, flags);
|
||||||
spin_lock_irq(&udc->ud.lock);
|
spin_lock_irq(&udc->ud.lock);
|
||||||
|
|
||||||
|
udc->ud.tcp_socket = socket;
|
||||||
|
udc->ud.tcp_rx = tcp_rx;
|
||||||
|
udc->ud.tcp_rx = tcp_tx;
|
||||||
udc->ud.status = SDEV_ST_USED;
|
udc->ud.status = SDEV_ST_USED;
|
||||||
|
|
||||||
spin_unlock_irq(&udc->ud.lock);
|
spin_unlock_irq(&udc->ud.lock);
|
||||||
|
|
||||||
ktime_get_ts64(&udc->start_time);
|
ktime_get_ts64(&udc->start_time);
|
||||||
v_start_timer(udc);
|
v_start_timer(udc);
|
||||||
udc->connected = 1;
|
udc->connected = 1;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&udc->lock, flags);
|
||||||
|
|
||||||
|
wake_up_process(udc->ud.tcp_rx);
|
||||||
|
wake_up_process(udc->ud.tcp_tx);
|
||||||
|
return count;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!udc->connected) {
|
if (!udc->connected) {
|
||||||
dev_err(dev, "Device not connected");
|
dev_err(dev, "Device not connected");
|
||||||
|
@ -177,6 +210,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
sock_err:
|
||||||
|
sockfd_put(socket);
|
||||||
unlock_ud:
|
unlock_ud:
|
||||||
spin_unlock_irq(&udc->ud.lock);
|
spin_unlock_irq(&udc->ud.lock);
|
||||||
unlock:
|
unlock:
|
||||||
|
|
Loading…
Reference in New Issue