input: synaptics_i2c_rmi4: Add check to avoid memory leak
Add conditions to check if fhandler already exists in the list
or not. If exists, then free the memory allocated to the new
fhandler. Otherwise add the fhandler to the list.
Change the location of INIT_LIST_HEAD() call to avoid
memory leak.
CRs-fixed: 575094
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
Change-Id: Iaf1429b911baffa53f968c0ca986fec190100ded
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index d21b6c1..723b331 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -2051,6 +2051,30 @@
return 0;
}
+/*
+* This function checks whether the fhandler already existis in the
+* support_fn_list or not.
+* If it exists then return 1 as found or return 0 as not found.
+*
+* Called by synaptics_rmi4_query_device().
+*/
+static int synaptics_rmi4_check_fn_list(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int found = 0;
+ struct synaptics_rmi4_fn *new_fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ if (!list_empty(&rmi->support_fn_list))
+ list_for_each_entry(new_fhandler, &rmi->support_fn_list, link)
+ if (new_fhandler->fn_number == fhandler->fn_number)
+ found = 1;
+
+ return found;
+}
+
/**
* synaptics_rmi4_query_device()
*
@@ -2066,7 +2090,7 @@
*/
static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
{
- int retval;
+ int retval, found;
unsigned char ii;
unsigned char page_number;
unsigned char intr_count = 0;
@@ -2080,8 +2104,6 @@
rmi = &(rmi4_data->rmi4_mod_info);
- INIT_LIST_HEAD(&rmi->support_fn_list);
-
/* Scan the page description tables of the pages to service */
for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
@@ -2096,7 +2118,7 @@
return retval;
fhandler = NULL;
-
+ found = 0;
if (rmi_fd.fn_number == 0) {
dev_dbg(&rmi4_data->i2c_client->dev,
"%s: Reached end of PDT\n",
@@ -2215,8 +2237,28 @@
intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
if (fhandler && rmi_fd.intr_src_count) {
- list_add_tail(&fhandler->link,
+ /* Want to check whether the fhandler already
+ exists in the support_fn_list or not.
+ If not found then add it to the list, otherwise
+ free the memory allocated to it.
+ */
+ found = synaptics_rmi4_check_fn_list(rmi4_data,
+ fhandler);
+
+ if (!found) {
+ list_add_tail(&fhandler->link,
&rmi->support_fn_list);
+ } else {
+ if (fhandler->fn_number ==
+ SYNAPTICS_RMI4_F1A) {
+ synaptics_rmi4_f1a_kfree(
+ fhandler);
+ } else {
+ kfree(fhandler->data);
+ kfree(fhandler->extra);
+ }
+ kfree(fhandler);
+ }
}
}
}
@@ -2851,6 +2893,8 @@
init_waitqueue_head(&rmi4_data->wait);
mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
+ INIT_LIST_HEAD(&rmi->support_fn_list);
+
retval = synaptics_rmi4_query_device(rmi4_data);
if (retval < 0) {
dev_err(&client->dev,