USB: rmnet: Free device context memory only during cleanup
Device context is currently allocated only once during
initialization and it gets freed during function unbind.
This causes memory corruption issue as device context is
accessed again after compostion switch.
Fix this issue by freeing the memory only at the time of
cleaning up the function driver resources.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index f1575bd..671b84c 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -216,6 +216,11 @@
return frmnet_init_port(MAX_RMNET_INSTANCES);
}
+static void rmnet_function_cleanup(struct android_usb_function *f)
+{
+ frmnet_cleanup();
+}
+
static int rmnet_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
@@ -259,6 +264,7 @@
static struct android_usb_function rmnet_function = {
.name = "rmnet",
.init = rmnet_function_init,
+ .cleanup = rmnet_function_cleanup,
.bind_config = rmnet_function_bind_config,
.attributes = rmnet_function_attributes,
};
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index dcb43a2..cf7a798 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -292,7 +292,6 @@
frmnet_free_req(dev->notify, dev->notify_req);
kfree(f->name);
- kfree(dev);
}
static void frmnet_disable(struct usb_function *f)
@@ -715,7 +714,6 @@
pr_err("%s: usb add function failed: %d\n",
__func__, status);
kfree(f->name);
- kfree(dev);
return status;
}
@@ -724,6 +722,16 @@
return status;
}
+static void frmnet_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < nr_rmnet_ports; i++)
+ kfree(rmnet_ports[i].port);
+
+ nr_rmnet_ports = 0;
+}
+
static int frmnet_init_port(int instances)
{
int i;
@@ -732,6 +740,12 @@
pr_debug("%s: instances :%d\n", __func__, instances);
+ if (instances > NR_RMNET_PORTS) {
+ pr_err("%s: Max-%d instances supported\n", __func__,
+ NR_RMNET_PORTS);
+ return -EINVAL;
+ }
+
for (i = 0; i < instances; i++) {
dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
if (!dev) {