usb: fixes for v3.19-rc2
First set of fixes for current -rc cycle. There are a couple of build break fixes after Tony Lindgren's recent MUSB patchset, some memory leak fixes also with MUSB, a use-after-free fix with the UAC1 function. Atmel UDC got a fix for a possible hang and another for DMA setting, while dwc2 learned to kill requests in ->udc_stop() which fixes a few leaks too. One new device support here, dwc3 now supports Intel's Sunrise Point. Signed-off-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUmZ1EAAoJEIaOsuA1yqREbmIP/2QAi4dxa7XqDql4Tzn7IeKC 7e7F7v/bOO/bXubgMn4MkghC8/hF/0FPJFxv1CrGVNEtjFToOtB55aswaIrmKvYI WZmuhEfDNfhc3BtzNz3aINEdW5Jr2bIOxymi8QryX3zIclTqSk147E8nbjQvmfbu hAlQIM3uPujoIKW9yHjsq9Ou/E0SL9/HeH9whB2wziOpk47WpVTW7K03OizDBbop VmO+y2Ifsv7BNc52qB76N//aU6kPeO5qIN3ksVY1n/cPTeNB8iwkHN9mhEkLwLCU qA4pY3G5gUH4OyyHSUuYTIvZAI86XaQAqKfm0uwkmO0DadrQwFTGyAkU2KG4TRlL W+XLdGQ3Pt0PF81MVKoOldjq5bjDHvvq5HuuXHbPtnkCtViJD9Q78OLZS/vJx/lt TA5uqZXniNId+jrhiODlz2F+wF0Neewah8B2KRqF8x88SR281IzlOoDt0QAMIxGr AHia77YwApVPotKtj3i1VETQUZ1P2JBC2jQbMRrs/4X4j6JltE1HiPzziMdMDOF5 g58jkd+HppypzRCdxVMi219gBkkqsbU0i6HjK5lDW4emCPvO8qQPkSoaiPEKuIQT VVgFTsqwRa8xMzlf1amZuiYlZpdn41VZ7KjoteCKp78gNIQjKLhK7HH3V8c72XQj TM5CmOMdTlImil//DgPK =9r9T -----END PGP SIGNATURE----- Merge tag 'fixes-for-v3.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: usb: fixes for v3.19-rc2 First set of fixes for current -rc cycle. There are a couple of build break fixes after Tony Lindgren's recent MUSB patchset, some memory leak fixes also with MUSB, a use-after-free fix with the UAC1 function. Atmel UDC got a fix for a possible hang and another for DMA setting, while dwc2 learned to kill requests in ->udc_stop() which fixes a few leaks too. One new device support here, dwc3 now supports Intel's Sunrise Point. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
commit
b3ee8bdcd2
12 changed files with 45 additions and 31 deletions
|
@ -2567,7 +2567,7 @@ error:
|
||||||
* s3c_hsotg_ep_disable - disable given endpoint
|
* s3c_hsotg_ep_disable - disable given endpoint
|
||||||
* @ep: The endpoint to disable.
|
* @ep: The endpoint to disable.
|
||||||
*/
|
*/
|
||||||
static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
static int s3c_hsotg_ep_disable_force(struct usb_ep *ep, bool force)
|
||||||
{
|
{
|
||||||
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
|
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
|
||||||
struct dwc2_hsotg *hsotg = hs_ep->parent;
|
struct dwc2_hsotg *hsotg = hs_ep->parent;
|
||||||
|
@ -2588,7 +2588,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
|
|
||||||
spin_lock_irqsave(&hsotg->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
/* terminate all requests with shutdown */
|
/* terminate all requests with shutdown */
|
||||||
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
|
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, force);
|
||||||
|
|
||||||
hsotg->fifo_map &= ~(1<<hs_ep->fifo_index);
|
hsotg->fifo_map &= ~(1<<hs_ep->fifo_index);
|
||||||
hs_ep->fifo_index = 0;
|
hs_ep->fifo_index = 0;
|
||||||
|
@ -2609,6 +2609,10 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
|
{
|
||||||
|
return s3c_hsotg_ep_disable_force(ep, false);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* on_list - check request is on the given endpoint
|
* on_list - check request is on the given endpoint
|
||||||
* @ep: The endpoint to check.
|
* @ep: The endpoint to check.
|
||||||
|
@ -2924,7 +2928,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
|
||||||
|
|
||||||
/* all endpoints should be shutdown */
|
/* all endpoints should be shutdown */
|
||||||
for (ep = 1; ep < hsotg->num_of_eps; ep++)
|
for (ep = 1; ep < hsotg->num_of_eps; ep++)
|
||||||
s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
|
s3c_hsotg_ep_disable_force(&hsotg->eps[ep].ep, true);
|
||||||
|
|
||||||
spin_lock_irqsave(&hsotg->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
|
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
|
||||||
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
|
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
|
||||||
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
|
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
|
||||||
|
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
|
||||||
|
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
|
||||||
|
|
||||||
struct dwc3_pci {
|
struct dwc3_pci {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@ -219,6 +221,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
|
||||||
{ } /* Terminating Entry */
|
{ } /* Terminating Entry */
|
||||||
};
|
};
|
||||||
|
|
|
@ -399,8 +399,9 @@ static int hidg_setup(struct usb_function *f,
|
||||||
value = __le16_to_cpu(ctrl->wValue);
|
value = __le16_to_cpu(ctrl->wValue);
|
||||||
length = __le16_to_cpu(ctrl->wLength);
|
length = __le16_to_cpu(ctrl->wLength);
|
||||||
|
|
||||||
VDBG(cdev, "hid_setup crtl_request : bRequestType:0x%x bRequest:0x%x "
|
VDBG(cdev,
|
||||||
"Value:0x%x\n", ctrl->bRequestType, ctrl->bRequest, value);
|
"%s crtl_request : bRequestType:0x%x bRequest:0x%x Value:0x%x\n",
|
||||||
|
__func__, ctrl->bRequestType, ctrl->bRequest, value);
|
||||||
|
|
||||||
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
|
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
|
||||||
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
||||||
|
|
|
@ -520,7 +520,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
|
||||||
req = midi_alloc_ep_req(ep, midi->buflen);
|
req = midi_alloc_ep_req(ep, midi->buflen);
|
||||||
|
|
||||||
if (!req) {
|
if (!req) {
|
||||||
ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");
|
ERROR(midi, "%s: alloc_ep_request failed\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->length = 0;
|
req->length = 0;
|
||||||
|
|
|
@ -897,7 +897,6 @@ static void f_audio_free_inst(struct usb_function_instance *f)
|
||||||
struct f_uac1_opts *opts;
|
struct f_uac1_opts *opts;
|
||||||
|
|
||||||
opts = container_of(f, struct f_uac1_opts, func_inst);
|
opts = container_of(f, struct f_uac1_opts, func_inst);
|
||||||
gaudio_cleanup(opts->card);
|
|
||||||
if (opts->fn_play_alloc)
|
if (opts->fn_play_alloc)
|
||||||
kfree(opts->fn_play);
|
kfree(opts->fn_play);
|
||||||
if (opts->fn_cap_alloc)
|
if (opts->fn_cap_alloc)
|
||||||
|
@ -935,6 +934,7 @@ static void f_audio_free(struct usb_function *f)
|
||||||
struct f_audio *audio = func_to_audio(f);
|
struct f_audio *audio = func_to_audio(f);
|
||||||
struct f_uac1_opts *opts;
|
struct f_uac1_opts *opts;
|
||||||
|
|
||||||
|
gaudio_cleanup(&audio->card);
|
||||||
opts = container_of(f->fi, struct f_uac1_opts, func_inst);
|
opts = container_of(f->fi, struct f_uac1_opts, func_inst);
|
||||||
kfree(audio);
|
kfree(audio);
|
||||||
mutex_lock(&opts->lock);
|
mutex_lock(&opts->lock);
|
||||||
|
|
|
@ -449,6 +449,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
data->name, len, (int) value);
|
data->name, len, (int) value);
|
||||||
free1:
|
free1:
|
||||||
mutex_unlock(&data->lock);
|
mutex_unlock(&data->lock);
|
||||||
|
kfree (kbuf);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -716,10 +716,10 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
|
||||||
req->using_dma = 1;
|
req->using_dma = 1;
|
||||||
req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
|
req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
|
||||||
| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
|
| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
|
||||||
| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
|
| USBA_DMA_END_BUF_EN;
|
||||||
|
|
||||||
if (ep->is_in)
|
if (!ep->is_in)
|
||||||
req->ctrl |= USBA_DMA_END_BUF_EN;
|
req->ctrl |= USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add this request to the queue and submit for DMA if
|
* Add this request to the queue and submit for DMA if
|
||||||
|
@ -1563,7 +1563,6 @@ static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
|
||||||
if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
|
if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
|
||||||
DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
|
DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
|
||||||
receive_data(ep);
|
receive_data(ep);
|
||||||
usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,8 @@ config USB_MUSB_DA8XX
|
||||||
|
|
||||||
config USB_MUSB_TUSB6010
|
config USB_MUSB_TUSB6010
|
||||||
tristate "TUSB6010"
|
tristate "TUSB6010"
|
||||||
|
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||||
|
depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules
|
||||||
|
|
||||||
config USB_MUSB_OMAP2PLUS
|
config USB_MUSB_OMAP2PLUS
|
||||||
tristate "OMAP2430 and onwards"
|
tristate "OMAP2430 and onwards"
|
||||||
|
@ -85,6 +87,7 @@ config USB_MUSB_AM35X
|
||||||
config USB_MUSB_DSPS
|
config USB_MUSB_DSPS
|
||||||
tristate "TI DSPS platforms"
|
tristate "TI DSPS platforms"
|
||||||
select USB_MUSB_AM335X_CHILD
|
select USB_MUSB_AM335X_CHILD
|
||||||
|
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||||
depends on OF_IRQ
|
depends on OF_IRQ
|
||||||
|
|
||||||
config USB_MUSB_BLACKFIN
|
config USB_MUSB_BLACKFIN
|
||||||
|
@ -93,6 +96,7 @@ config USB_MUSB_BLACKFIN
|
||||||
|
|
||||||
config USB_MUSB_UX500
|
config USB_MUSB_UX500
|
||||||
tristate "Ux500 platforms"
|
tristate "Ux500 platforms"
|
||||||
|
depends on ARCH_U8500 || COMPILE_TEST
|
||||||
|
|
||||||
config USB_MUSB_JZ4740
|
config USB_MUSB_JZ4740
|
||||||
tristate "JZ4740"
|
tristate "JZ4740"
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void bfin_writew(void __iomem *addr, unsigned offset, u16 data)
|
||||||
bfin_write16(addr + offset, data);
|
bfin_write16(addr + offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void binf_writel(void __iomem *addr, unsigned offset, u32 data)
|
static void bfin_writel(void __iomem *addr, unsigned offset, u32 data)
|
||||||
{
|
{
|
||||||
bfin_write16(addr + offset, (u16)data);
|
bfin_write16(addr + offset, (u16)data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -628,9 +628,9 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
|
||||||
ret = of_property_read_string_index(np, "dma-names", i, &str);
|
ret = of_property_read_string_index(np, "dma-names", i, &str);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
if (!strncmp(str, "tx", 2))
|
if (strstarts(str, "tx"))
|
||||||
is_tx = 1;
|
is_tx = 1;
|
||||||
else if (!strncmp(str, "rx", 2))
|
else if (strstarts(str, "rx"))
|
||||||
is_tx = 0;
|
is_tx = 0;
|
||||||
else {
|
else {
|
||||||
dev_err(dev, "Wrong dmatype %s\n", str);
|
dev_err(dev, "Wrong dmatype %s\n", str);
|
||||||
|
|
|
@ -59,20 +59,12 @@ static const struct musb_register_map musb_regmap[] = {
|
||||||
{ "RxMaxPp", MUSB_RXMAXP, 16 },
|
{ "RxMaxPp", MUSB_RXMAXP, 16 },
|
||||||
{ "RxCSR", MUSB_RXCSR, 16 },
|
{ "RxCSR", MUSB_RXCSR, 16 },
|
||||||
{ "RxCount", MUSB_RXCOUNT, 16 },
|
{ "RxCount", MUSB_RXCOUNT, 16 },
|
||||||
{ "ConfigData", MUSB_CONFIGDATA,8 },
|
|
||||||
{ "IntrRxE", MUSB_INTRRXE, 16 },
|
{ "IntrRxE", MUSB_INTRRXE, 16 },
|
||||||
{ "IntrTxE", MUSB_INTRTXE, 16 },
|
{ "IntrTxE", MUSB_INTRTXE, 16 },
|
||||||
{ "IntrUsbE", MUSB_INTRUSBE, 8 },
|
{ "IntrUsbE", MUSB_INTRUSBE, 8 },
|
||||||
{ "DevCtl", MUSB_DEVCTL, 8 },
|
{ "DevCtl", MUSB_DEVCTL, 8 },
|
||||||
{ "BabbleCtl", MUSB_BABBLE_CTL,8 },
|
|
||||||
{ "TxFIFOsz", MUSB_TXFIFOSZ, 8 },
|
|
||||||
{ "RxFIFOsz", MUSB_RXFIFOSZ, 8 },
|
|
||||||
{ "TxFIFOadd", MUSB_TXFIFOADD, 16 },
|
|
||||||
{ "RxFIFOadd", MUSB_RXFIFOADD, 16 },
|
|
||||||
{ "VControl", 0x68, 32 },
|
{ "VControl", 0x68, 32 },
|
||||||
{ "HWVers", 0x69, 16 },
|
{ "HWVers", 0x69, 16 },
|
||||||
{ "EPInfo", MUSB_EPINFO, 8 },
|
|
||||||
{ "RAMInfo", MUSB_RAMINFO, 8 },
|
|
||||||
{ "LinkInfo", MUSB_LINKINFO, 8 },
|
{ "LinkInfo", MUSB_LINKINFO, 8 },
|
||||||
{ "VPLen", MUSB_VPLEN, 8 },
|
{ "VPLen", MUSB_VPLEN, 8 },
|
||||||
{ "HS_EOF1", MUSB_HS_EOF1, 8 },
|
{ "HS_EOF1", MUSB_HS_EOF1, 8 },
|
||||||
|
@ -103,6 +95,16 @@ static const struct musb_register_map musb_regmap[] = {
|
||||||
{ "DMA_CNTLch7", 0x274, 16 },
|
{ "DMA_CNTLch7", 0x274, 16 },
|
||||||
{ "DMA_ADDRch7", 0x278, 32 },
|
{ "DMA_ADDRch7", 0x278, 32 },
|
||||||
{ "DMA_COUNTch7", 0x27C, 32 },
|
{ "DMA_COUNTch7", 0x27C, 32 },
|
||||||
|
#ifndef CONFIG_BLACKFIN
|
||||||
|
{ "ConfigData", MUSB_CONFIGDATA,8 },
|
||||||
|
{ "BabbleCtl", MUSB_BABBLE_CTL,8 },
|
||||||
|
{ "TxFIFOsz", MUSB_TXFIFOSZ, 8 },
|
||||||
|
{ "RxFIFOsz", MUSB_RXFIFOSZ, 8 },
|
||||||
|
{ "TxFIFOadd", MUSB_TXFIFOADD, 16 },
|
||||||
|
{ "RxFIFOadd", MUSB_RXFIFOADD, 16 },
|
||||||
|
{ "EPInfo", MUSB_EPINFO, 8 },
|
||||||
|
{ "RAMInfo", MUSB_RAMINFO, 8 },
|
||||||
|
#endif
|
||||||
{ } /* Terminating Entry */
|
{ } /* Terminating Entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,30 +199,30 @@ static ssize_t musb_test_mode_write(struct file *file,
|
||||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (!strncmp(buf, "force host", 9))
|
if (strstarts(buf, "force host"))
|
||||||
test = MUSB_TEST_FORCE_HOST;
|
test = MUSB_TEST_FORCE_HOST;
|
||||||
|
|
||||||
if (!strncmp(buf, "fifo access", 11))
|
if (strstarts(buf, "fifo access"))
|
||||||
test = MUSB_TEST_FIFO_ACCESS;
|
test = MUSB_TEST_FIFO_ACCESS;
|
||||||
|
|
||||||
if (!strncmp(buf, "force full-speed", 15))
|
if (strstarts(buf, "force full-speed"))
|
||||||
test = MUSB_TEST_FORCE_FS;
|
test = MUSB_TEST_FORCE_FS;
|
||||||
|
|
||||||
if (!strncmp(buf, "force high-speed", 15))
|
if (strstarts(buf, "force high-speed"))
|
||||||
test = MUSB_TEST_FORCE_HS;
|
test = MUSB_TEST_FORCE_HS;
|
||||||
|
|
||||||
if (!strncmp(buf, "test packet", 10)) {
|
if (strstarts(buf, "test packet")) {
|
||||||
test = MUSB_TEST_PACKET;
|
test = MUSB_TEST_PACKET;
|
||||||
musb_load_testpacket(musb);
|
musb_load_testpacket(musb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(buf, "test K", 6))
|
if (strstarts(buf, "test K"))
|
||||||
test = MUSB_TEST_K;
|
test = MUSB_TEST_K;
|
||||||
|
|
||||||
if (!strncmp(buf, "test J", 6))
|
if (strstarts(buf, "test J"))
|
||||||
test = MUSB_TEST_J;
|
test = MUSB_TEST_J;
|
||||||
|
|
||||||
if (!strncmp(buf, "test SE0 NAK", 12))
|
if (strstarts(buf, "test SE0 NAK"))
|
||||||
test = MUSB_TEST_SE0_NAK;
|
test = MUSB_TEST_SE0_NAK;
|
||||||
|
|
||||||
musb_writeb(musb->mregs, MUSB_TESTMODE, test);
|
musb_writeb(musb->mregs, MUSB_TESTMODE, test);
|
||||||
|
|
|
@ -2663,7 +2663,6 @@ void musb_host_cleanup(struct musb *musb)
|
||||||
if (musb->port_mode == MUSB_PORT_MODE_GADGET)
|
if (musb->port_mode == MUSB_PORT_MODE_GADGET)
|
||||||
return;
|
return;
|
||||||
usb_remove_hcd(musb->hcd);
|
usb_remove_hcd(musb->hcd);
|
||||||
musb->hcd = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void musb_host_free(struct musb *musb)
|
void musb_host_free(struct musb *musb)
|
||||||
|
|
Loading…
Add table
Reference in a new issue