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.
I rebuilt the patch in standard form (patch -p1 from treetop)
and signed off on the result, which I attached.
- Dave
From: Tao Huang <[EMAIL PROTECTED]>
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
--- 1.45/drivers/usb/gadget/ether.c Tue Jun 1 05:30:11 2004
+++ edited/drivers/usb/gadget/ether.c Sun Jun 6 13:34:51 2004
@@ -1346,14 +1346,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)
@@ -1583,6 +1580,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 */
}
@@ -2067,6 +2065,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;
@@ -2098,7 +2106,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);
@@ -2106,7 +2114,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;