aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2014-03-10 09:10:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-03-17 18:52:06 -0400
commitcc99ecfdac01215594c73907726b12f251c21e20 (patch)
tree00e6eb535d5567a30caa7125b9990656cdb03df2 /drivers
parentb1b94b5d387e3a1f034c308e22f9295828d7174a (diff)
mei: fix memory leak of pending write cb objects
Write callbacks are released on the write completed path but when file handler is closed before the writes are completed those are left dangling on write and write_waiting queues. We add mei_io_list_free function to perform this task Also move static functions to client.c form client.h Cc: stable <stable@vger.kernel.org> # 3.11+ Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/mei/client.c76
-rw-r--r--drivers/misc/mei/client.h18
2 files changed, 55 insertions, 39 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 753608185b77..8c078b808cd3 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -71,23 +71,69 @@ int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
71 71
72 72
73/** 73/**
74 * mei_io_list_flush - removes list entry belonging to cl. 74 * mei_cl_cmp_id - tells if the clients are the same
75 * 75 *
76 * @list: An instance of our list structure 76 * @cl1: host client 1
77 * @cl: host client 77 * @cl2: host client 2
78 *
79 * returns true - if the clients has same host and me ids
80 * false - otherwise
81 */
82static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
83 const struct mei_cl *cl2)
84{
85 return cl1 && cl2 &&
86 (cl1->host_client_id == cl2->host_client_id) &&
87 (cl1->me_client_id == cl2->me_client_id);
88}
89
90/**
91 * mei_io_list_flush - removes cbs belonging to cl.
92 *
93 * @list: an instance of our list structure
94 * @cl: host client, can be NULL for flushing the whole list
95 * @free: whether to free the cbs
78 */ 96 */
79void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) 97static void __mei_io_list_flush(struct mei_cl_cb *list,
98 struct mei_cl *cl, bool free)
80{ 99{
81 struct mei_cl_cb *cb; 100 struct mei_cl_cb *cb;
82 struct mei_cl_cb *next; 101 struct mei_cl_cb *next;
83 102
103 /* enable removing everything if no cl is specified */
84 list_for_each_entry_safe(cb, next, &list->list, list) { 104 list_for_each_entry_safe(cb, next, &list->list, list) {
85 if (cb->cl && mei_cl_cmp_id(cl, cb->cl)) 105 if (!cl || (cb->cl && mei_cl_cmp_id(cl, cb->cl))) {
86 list_del(&cb->list); 106 list_del(&cb->list);
107 if (free)
108 mei_io_cb_free(cb);
109 }
87 } 110 }
88} 111}
89 112
90/** 113/**
114 * mei_io_list_flush - removes list entry belonging to cl.
115 *
116 * @list: An instance of our list structure
117 * @cl: host client
118 */
119static inline void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
120{
121 __mei_io_list_flush(list, cl, false);
122}
123
124
125/**
126 * mei_io_list_free - removes cb belonging to cl and free them
127 *
128 * @list: An instance of our list structure
129 * @cl: host client
130 */
131static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
132{
133 __mei_io_list_flush(list, cl, true);
134}
135
136/**
91 * mei_io_cb_free - free mei_cb_private related memory 137 * mei_io_cb_free - free mei_cb_private related memory
92 * 138 *
93 * @cb: mei callback struct 139 * @cb: mei callback struct
@@ -193,8 +239,8 @@ int mei_cl_flush_queues(struct mei_cl *cl)
193 239
194 cl_dbg(dev, cl, "remove list entry belonging to cl\n"); 240 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
195 mei_io_list_flush(&cl->dev->read_list, cl); 241 mei_io_list_flush(&cl->dev->read_list, cl);
196 mei_io_list_flush(&cl->dev->write_list, cl); 242 mei_io_list_free(&cl->dev->write_list, cl);
197 mei_io_list_flush(&cl->dev->write_waiting_list, cl); 243 mei_io_list_free(&cl->dev->write_waiting_list, cl);
198 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 244 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
199 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 245 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
200 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); 246 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
@@ -956,20 +1002,8 @@ void mei_cl_all_wakeup(struct mei_device *dev)
956 */ 1002 */
957void mei_cl_all_write_clear(struct mei_device *dev) 1003void mei_cl_all_write_clear(struct mei_device *dev)
958{ 1004{
959 struct mei_cl_cb *cb, *next; 1005 mei_io_list_free(&dev->write_list, NULL);
960 struct list_head *list; 1006 mei_io_list_free(&dev->write_waiting_list, NULL);
961
962 list = &dev->write_list.list;
963 list_for_each_entry_safe(cb, next, list, list) {
964 list_del(&cb->list);
965 mei_io_cb_free(cb);
966 }
967
968 list = &dev->write_waiting_list.list;
969 list_for_each_entry_safe(cb, next, list, list) {
970 list_del(&cb->list);
971 mei_io_cb_free(cb);
972 }
973} 1007}
974 1008
975 1009
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index c11b663358a4..81393938ad06 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -45,8 +45,6 @@ static inline void mei_io_list_init(struct mei_cl_cb *list)
45{ 45{
46 INIT_LIST_HEAD(&list->list); 46 INIT_LIST_HEAD(&list->list);
47} 47}
48void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
49
50/* 48/*
51 * MEI Host Client Functions 49 * MEI Host Client Functions
52 */ 50 */
@@ -61,22 +59,6 @@ int mei_cl_unlink(struct mei_cl *cl);
61int mei_cl_flush_queues(struct mei_cl *cl); 59int mei_cl_flush_queues(struct mei_cl *cl);
62struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl); 60struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl);
63 61
64/**
65 * mei_cl_cmp_id - tells if file private data have same id
66 *
67 * @fe1: private data of 1. file object
68 * @fe2: private data of 2. file object
69 *
70 * returns true - if ids are the same and not NULL
71 */
72static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
73 const struct mei_cl *cl2)
74{
75 return cl1 && cl2 &&
76 (cl1->host_client_id == cl2->host_client_id) &&
77 (cl1->me_client_id == cl2->me_client_id);
78}
79
80 62
81int mei_cl_flow_ctrl_creds(struct mei_cl *cl); 63int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
82 64