ChangeSet 1.1722.97.49, 2004/06/07 16:58:23-07:00, david-b@pacbell.net [PATCH] USB: rndis (2/4) fix memory leaks Tao Huang wrote: > I'm writing udc driver for S3C2410. I found RNDIS almost not call my > driver's free_request and free_buffer. So after run my driver about 3 > hours the system will out of memory. > > This patch will fix the memory leak. > > There will still have memory leak when driver unload, but I don't known > where is the proper place to fix it. > 1) rndis.c should free resp_queue when it unload > 2) ether.c should free tx_reqs and rx_reqs when it unload (as > eth_reset_config) Thanks ... this is a nice patch to have. From: Tao Huang Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman drivers/usb/gadget/ether.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-) diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c Fri Jun 18 10:59:46 2004 +++ b/drivers/usb/gadget/ether.c Fri Jun 18 10:59:46 2004 @@ -1345,14 +1345,11 @@ static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req) { - struct eth_dev *dev = ep->driver_data; - if (req->status || req->actual != req->length) DEBUG (dev, "rndis response complete --> %d, %d/%d\n", req->status, req->actual, req->length); /* done sending after CDC_GET_ENCAPSULATED_RESPONSE */ - rndis_free_response (dev->rndis_config, req->buf); } static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) @@ -1580,6 +1577,7 @@ if (buf) { memcpy (req->buf, buf, value); req->complete = rndis_response_complete; + rndis_free_response(dev->rndis_config, buf); } /* else stalls ... spec says to avoid that */ } @@ -2064,6 +2062,16 @@ } } +static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) +{ + if (req->status || req->actual != req->length) + DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n", + req->status, req->actual, req->length); + + usb_ep_free_buffer(ep, req->buf, req->dma, 8); + usb_ep_free_request(ep, req); +} + static int rndis_control_ack (struct net_device *net) { struct eth_dev *dev = (struct eth_dev *) net->priv; @@ -2095,7 +2103,7 @@ * CDC_NOTIFY_RESPONSE_AVAILABLE should work too */ resp->length = 8; - resp->complete = rndis_response_complete; + resp->complete = rndis_control_ack_complete; *((u32 *) resp->buf) = __constant_cpu_to_le32 (1); *((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); @@ -2103,7 +2111,7 @@ length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); if (length < 0) { resp->status = 0; - rndis_response_complete (dev->status_ep, resp); + rndis_control_ack_complete (dev->status_ep, resp); } return 0;