Thread (29 messages) 29 messages, 7 authors, 2008-09-24

Re: [PATCH] usb: add Freescale QE/CPM USB peripheral controller driver

From: Anton Vorontsov <hidden>
Date: 2008-09-01 17:11:20
Also in: lkml
Subsystem: the rest, usb subsystem · Maintainers: Linus Torvalds, Greg Kroah-Hartman

On Thu, Aug 28, 2008 at 05:43:33PM +0800, Li Yang wrote:
Some of Freescale SoC chips have a QE or CPM co-processor which
supports full speed USB.  The driver adds device mode support
of both QE and CPM USB controller to Linux USB gadget.  The
driver is tested with MPC8360 and MPC8272, and should work with
other models having QE/CPM given minor tweaks.

Signed-off-by: Xie Xiaobo <redacted>
Signed-off-by: Li Yang <redacted>
---
This is the second submission of the driver.  This version addressed:
Comments from Anton Vorontsov.
A lot of cosmetic problem.
Sparse and various kernel DEBUG warnings.
Just caught this:

g_ether gadget: high speed config #1: CDC Ethernet (ECM)
BUG: sleeping function called from invalid context at mm/page_alloc.c:1450
in_atomic():1, irqs_disabled():1
Call Trace:
[c03a9c30] [c0008a90] show_stack+0x4c/0x16c (unreliable)
[c03a9c70] [c002cd28] __might_sleep+0xe4/0x114
[c03a9c80] [c006e550] __alloc_pages_internal+0x328/0x42c
[c03a9d00] [c006e67c] __get_free_pages+0x28/0x68
[c03a9d10] [c0090efc] __kmalloc+0xc0/0xe4
[c03a9d30] [c01d8efc] qe_ep_rxbd_update+0x98/0x1e0
[c03a9d50] [c01d90f0] qe_ep_init+0xac/0x37c
[c03a9d70] [c01d9458] qe_ep_enable+0x98/0xb8
[c03a9d80] [c01db268] gether_connect+0xa0/0x178
[c03a9da0] [c01dbba8] ecm_set_alt+0x108/0x12c
[c03a9db0] [c01dc988] composite_setup+0x2ec/0x3a8
[c03a9de0] [c01d8bec] setup_received_handle+0x1e4/0x26c
[c03a9e00] [c01d8ce0] ep0_setup_handle+0x6c/0x74
[c03a9e10] [c01d8e54] qe_ep0_rx+0x16c/0x17c
[c03a9e30] [c01d9db8] rx_irq+0x88/0xc0
[c03a9e40] [c01da32c] qe_udc_irq+0x10c/0x134
[c03a9e60] [c00631f4] handle_IRQ_event+0x5c/0xb0
[c03a9e80] [c006526c] handle_level_irq+0xa8/0x144
[c03a9ea0] [c002a5d0] qe_ic_cascade_low_ipic+0x58/0x70
[c03a9eb0] [c0006820] do_IRQ+0xa4/0xc8
[c03a9ec0] [c0013e14] ret_from_except+0x0/0x14
--- Exception: 501 at cpu_idle+0xa0/0x104
    LR = cpu_idle+0xa0/0x104
[c03a9f80] [c0009d88] cpu_idle+0x50/0x104 (unreliable)
[c03a9fa0] [c029307c] _etext+0x7c/0x90
[c03a9fc0] [c035491c] start_kernel+0x1ac/0x230
[c03a9ff0] [00003438] 0x3438

The workaround is obvious (below), but should we really allocate
things in interrupts? Can we just allocate everything in probe()
and free in remove()?

diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index c1a0beb..c54863b 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -433,7 +433,7 @@ static int qe_ep_rxbd_update(struct qe_ep *ep)
 
 	bd = ep->rxbase;
 
-	ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_KERNEL);
+	ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_ATOMIC);
 	if (ep->rxframe == NULL) {
 		dev_err(ep->udc->dev, "malloc rxframe failed\n");
 		return -ENOMEM;
@@ -447,7 +447,7 @@ static int qe_ep_rxbd_update(struct qe_ep *ep)
 		bdring_len = USB_BDRING_LEN;
 
 	size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1);
-	ep->rxbuffer = kzalloc(size, GFP_KERNEL);
+	ep->rxbuffer = kzalloc(size, GFP_ATOMIC);
 	if (ep->rxbuffer == NULL) {
 		dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n",
 				size);
@@ -680,7 +680,7 @@ static int qe_ep_init(struct qe_udc *udc,
 	}
 
 	if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) {
-		ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_KERNEL);
+		ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_ATOMIC);
 		if (ep->txframe == NULL) {
 			dev_err(udc->dev, "malloc txframe failed\n");
 			goto en_done;
@@ -1930,7 +1930,9 @@ static int reset_queues(struct qe_udc *udc)
 		udc_reset_ep_queue(udc, pipe);
 
 	/* report disconnect; the driver is already quiesced */
+	spin_unlock(&udc->lock);
 	udc->driver->disconnect(&udc->gadget);
+	spin_lock(&udc->lock);
 
 	return 0;
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help