aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-02-10 03:39:31 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-01 22:36:59 -0500
commitb7d885145538ddedb1ae23b782ab7c7c0a856e9f (patch)
tree9470b5807362a068e85487a429fb3b3f543af53e /drivers/misc
parente9395e3f8952110bda60b54ad03ec52c6e9c7dbd (diff)
mei: revamp me clients list handling
1. Use rw lock to access the me_clients list 2. Reuse already defined find functions also when removing particular me client 3. Add wrappers for addition and deletion Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/client.c194
-rw-r--r--drivers/misc/mei/client.h5
-rw-r--r--drivers/misc/mei/debugfs.c19
-rw-r--r--drivers/misc/mei/hbm.c3
-rw-r--r--drivers/misc/mei/init.c1
-rw-r--r--drivers/misc/mei/mei_dev.h2
6 files changed, 162 insertions, 62 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index dfbddfe1c7a0..48813c27a47c 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -48,14 +48,14 @@ void mei_me_cl_init(struct mei_me_client *me_cl)
48 */ 48 */
49struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl) 49struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)
50{ 50{
51 if (me_cl) 51 if (me_cl && kref_get_unless_zero(&me_cl->refcnt))
52 kref_get(&me_cl->refcnt); 52 return me_cl;
53 53
54 return me_cl; 54 return NULL;
55} 55}
56 56
57/** 57/**
58 * mei_me_cl_release - unlink and free me client 58 * mei_me_cl_release - free me client
59 * 59 *
60 * Locking: called under "dev->device_lock" lock 60 * Locking: called under "dev->device_lock" lock
61 * 61 *
@@ -65,9 +65,10 @@ static void mei_me_cl_release(struct kref *ref)
65{ 65{
66 struct mei_me_client *me_cl = 66 struct mei_me_client *me_cl =
67 container_of(ref, struct mei_me_client, refcnt); 67 container_of(ref, struct mei_me_client, refcnt);
68 list_del(&me_cl->list); 68
69 kfree(me_cl); 69 kfree(me_cl);
70} 70}
71
71/** 72/**
72 * mei_me_cl_put - decrease me client refcount and free client if necessary 73 * mei_me_cl_put - decrease me client refcount and free client if necessary
73 * 74 *
@@ -82,51 +83,146 @@ void mei_me_cl_put(struct mei_me_client *me_cl)
82} 83}
83 84
84/** 85/**
85 * mei_me_cl_by_uuid - locate me client by uuid 86 * __mei_me_cl_del - delete me client form the list and decrease
87 * reference counter
88 *
89 * @dev: mei device
90 * @me_cl: me client
91 *
92 * Locking: dev->me_clients_rwsem
93 */
94static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
95{
96 if (!me_cl)
97 return;
98
99 list_del(&me_cl->list);
100 mei_me_cl_put(me_cl);
101}
102
103/**
104 * mei_me_cl_add - add me client to the list
105 *
106 * @dev: mei device
107 * @me_cl: me client
108 */
109void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
110{
111 down_write(&dev->me_clients_rwsem);
112 list_add(&me_cl->list, &dev->me_clients);
113 up_write(&dev->me_clients_rwsem);
114}
115
116/**
117 * __mei_me_cl_by_uuid - locate me client by uuid
86 * increases ref count 118 * increases ref count
87 * 119 *
88 * @dev: mei device 120 * @dev: mei device
89 * @uuid: me client uuid 121 * @uuid: me client uuid
90 * 122 *
91 * Locking: called under "dev->device_lock" lock
92 *
93 * Return: me client or NULL if not found 123 * Return: me client or NULL if not found
124 *
125 * Locking: dev->me_clients_rwsem
94 */ 126 */
95struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev, 127static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
96 const uuid_le *uuid) 128 const uuid_le *uuid)
97{ 129{
98 struct mei_me_client *me_cl; 130 struct mei_me_client *me_cl;
131 const uuid_le *pn;
132
133 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
99 134
100 list_for_each_entry(me_cl, &dev->me_clients, list) 135 list_for_each_entry(me_cl, &dev->me_clients, list) {
101 if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0) 136 pn = &me_cl->props.protocol_name;
137 if (uuid_le_cmp(*uuid, *pn) == 0)
102 return mei_me_cl_get(me_cl); 138 return mei_me_cl_get(me_cl);
139 }
103 140
104 return NULL; 141 return NULL;
105} 142}
106 143
107/** 144/**
145 * mei_me_cl_by_uuid - locate me client by uuid
146 * increases ref count
147 *
148 * @dev: mei device
149 * @uuid: me client uuid
150 *
151 * Return: me client or NULL if not found
152 *
153 * Locking: dev->me_clients_rwsem
154 */
155struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
156 const uuid_le *uuid)
157{
158 struct mei_me_client *me_cl;
159
160 down_read(&dev->me_clients_rwsem);
161 me_cl = __mei_me_cl_by_uuid(dev, uuid);
162 up_read(&dev->me_clients_rwsem);
163
164 return me_cl;
165}
166
167/**
108 * mei_me_cl_by_id - locate me client by client id 168 * mei_me_cl_by_id - locate me client by client id
109 * increases ref count 169 * increases ref count
110 * 170 *
111 * @dev: the device structure 171 * @dev: the device structure
112 * @client_id: me client id 172 * @client_id: me client id
113 * 173 *
114 * Locking: called under "dev->device_lock" lock
115 *
116 * Return: me client or NULL if not found 174 * Return: me client or NULL if not found
175 *
176 * Locking: dev->me_clients_rwsem
117 */ 177 */
118struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id) 178struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
119{ 179{
120 180
181 struct mei_me_client *__me_cl, *me_cl = NULL;
182
183 down_read(&dev->me_clients_rwsem);
184 list_for_each_entry(__me_cl, &dev->me_clients, list) {
185 if (__me_cl->client_id == client_id) {
186 me_cl = mei_me_cl_get(__me_cl);
187 break;
188 }
189 }
190 up_read(&dev->me_clients_rwsem);
191
192 return me_cl;
193}
194
195/**
196 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
197 * increases ref count
198 *
199 * @dev: the device structure
200 * @uuid: me client uuid
201 * @client_id: me client id
202 *
203 * Return: me client or null if not found
204 *
205 * Locking: dev->me_clients_rwsem
206 */
207static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
208 const uuid_le *uuid, u8 client_id)
209{
121 struct mei_me_client *me_cl; 210 struct mei_me_client *me_cl;
211 const uuid_le *pn;
212
213 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
122 214
123 list_for_each_entry(me_cl, &dev->me_clients, list) 215 list_for_each_entry(me_cl, &dev->me_clients, list) {
124 if (me_cl->client_id == client_id) 216 pn = &me_cl->props.protocol_name;
217 if (uuid_le_cmp(*uuid, *pn) == 0 &&
218 me_cl->client_id == client_id)
125 return mei_me_cl_get(me_cl); 219 return mei_me_cl_get(me_cl);
220 }
126 221
127 return NULL; 222 return NULL;
128} 223}
129 224
225
130/** 226/**
131 * mei_me_cl_by_uuid_id - locate me client by client id and uuid 227 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
132 * increases ref count 228 * increases ref count
@@ -135,21 +231,18 @@ struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
135 * @uuid: me client uuid 231 * @uuid: me client uuid
136 * @client_id: me client id 232 * @client_id: me client id
137 * 233 *
138 * Locking: called under "dev->device_lock" lock 234 * Return: me client or null if not found
139 *
140 * Return: me client or NULL if not found
141 */ 235 */
142struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev, 236struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
143 const uuid_le *uuid, u8 client_id) 237 const uuid_le *uuid, u8 client_id)
144{ 238{
145 struct mei_me_client *me_cl; 239 struct mei_me_client *me_cl;
146 240
147 list_for_each_entry(me_cl, &dev->me_clients, list) 241 down_read(&dev->me_clients_rwsem);
148 if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0 && 242 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);
149 me_cl->client_id == client_id) 243 up_read(&dev->me_clients_rwsem);
150 return mei_me_cl_get(me_cl);
151 244
152 return NULL; 245 return me_cl;
153} 246}
154 247
155/** 248/**
@@ -162,12 +255,14 @@ struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
162 */ 255 */
163void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid) 256void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
164{ 257{
165 struct mei_me_client *me_cl, *next; 258 struct mei_me_client *me_cl;
166 259
167 dev_dbg(dev->dev, "remove %pUl\n", uuid); 260 dev_dbg(dev->dev, "remove %pUl\n", uuid);
168 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) 261
169 if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0) 262 down_write(&dev->me_clients_rwsem);
170 mei_me_cl_put(me_cl); 263 me_cl = __mei_me_cl_by_uuid(dev, uuid);
264 __mei_me_cl_del(dev, me_cl);
265 up_write(&dev->me_clients_rwsem);
171} 266}
172 267
173/** 268/**
@@ -181,15 +276,14 @@ void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
181 */ 276 */
182void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id) 277void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
183{ 278{
184 struct mei_me_client *me_cl, *next; 279 struct mei_me_client *me_cl;
185 const uuid_le *pn;
186 280
187 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id); 281 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);
188 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) { 282
189 pn = &me_cl->props.protocol_name; 283 down_write(&dev->me_clients_rwsem);
190 if (me_cl->client_id == id && uuid_le_cmp(*uuid, *pn) == 0) 284 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
191 mei_me_cl_put(me_cl); 285 __mei_me_cl_del(dev, me_cl);
192 } 286 up_write(&dev->me_clients_rwsem);
193} 287}
194 288
195/** 289/**
@@ -203,12 +297,12 @@ void mei_me_cl_rm_all(struct mei_device *dev)
203{ 297{
204 struct mei_me_client *me_cl, *next; 298 struct mei_me_client *me_cl, *next;
205 299
300 down_write(&dev->me_clients_rwsem);
206 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) 301 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
207 mei_me_cl_put(me_cl); 302 __mei_me_cl_del(dev, me_cl);
303 up_write(&dev->me_clients_rwsem);
208} 304}
209 305
210
211
212/** 306/**
213 * mei_cl_cmp_id - tells if the clients are the same 307 * mei_cl_cmp_id - tells if the clients are the same
214 * 308 *
@@ -535,28 +629,28 @@ int mei_cl_unlink(struct mei_cl *cl)
535 629
536void mei_host_client_init(struct work_struct *work) 630void mei_host_client_init(struct work_struct *work)
537{ 631{
538 struct mei_device *dev = container_of(work, 632 struct mei_device *dev =
539 struct mei_device, init_work); 633 container_of(work, struct mei_device, init_work);
540 struct mei_me_client *me_cl; 634 struct mei_me_client *me_cl;
541 struct mei_client_properties *props;
542 635
543 mutex_lock(&dev->device_lock); 636 mutex_lock(&dev->device_lock);
544 637
545 list_for_each_entry(me_cl, &dev->me_clients, list) {
546 props = &me_cl->props;
547 638
548 if (!uuid_le_cmp(props->protocol_name, mei_amthif_guid)) 639 me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
549 mei_amthif_host_init(dev); 640 if (me_cl)
550 else if (!uuid_le_cmp(props->protocol_name, mei_wd_guid)) 641 mei_amthif_host_init(dev);
551 mei_wd_host_init(dev); 642
552 else if (!uuid_le_cmp(props->protocol_name, mei_nfc_guid)) 643 me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
553 mei_nfc_host_init(dev); 644 if (me_cl)
645 mei_wd_host_init(dev);
646
647 me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
648 if (me_cl)
649 mei_nfc_host_init(dev);
554 650
555 }
556 651
557 dev->dev_state = MEI_DEV_ENABLED; 652 dev->dev_state = MEI_DEV_ENABLED;
558 dev->reset_count = 0; 653 dev->reset_count = 0;
559
560 mutex_unlock(&dev->device_lock); 654 mutex_unlock(&dev->device_lock);
561 655
562 pm_runtime_mark_last_busy(dev->dev); 656 pm_runtime_mark_last_busy(dev->dev);
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index cfcde8e97fc4..80386f9c27e9 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -31,7 +31,10 @@ void mei_me_cl_init(struct mei_me_client *me_cl);
31void mei_me_cl_put(struct mei_me_client *me_cl); 31void mei_me_cl_put(struct mei_me_client *me_cl);
32struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl); 32struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl);
33 33
34struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev, 34void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl);
35void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl);
36
37struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
35 const uuid_le *uuid); 38 const uuid_le *uuid);
36struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id); 39struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
37struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev, 40struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index b125380ee871..50fc6635fab1 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -28,7 +28,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
28 size_t cnt, loff_t *ppos) 28 size_t cnt, loff_t *ppos)
29{ 29{
30 struct mei_device *dev = fp->private_data; 30 struct mei_device *dev = fp->private_data;
31 struct mei_me_client *me_cl, *n; 31 struct mei_me_client *me_cl;
32 size_t bufsz = 1; 32 size_t bufsz = 1;
33 char *buf; 33 char *buf;
34 int i = 0; 34 int i = 0;
@@ -38,15 +38,14 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
38#define HDR \ 38#define HDR \
39" |id|fix| UUID |con|msg len|sb|refc|\n" 39" |id|fix| UUID |con|msg len|sb|refc|\n"
40 40
41 mutex_lock(&dev->device_lock); 41 down_read(&dev->me_clients_rwsem);
42
43 list_for_each_entry(me_cl, &dev->me_clients, list) 42 list_for_each_entry(me_cl, &dev->me_clients, list)
44 bufsz++; 43 bufsz++;
45 44
46 bufsz *= sizeof(HDR) + 1; 45 bufsz *= sizeof(HDR) + 1;
47 buf = kzalloc(bufsz, GFP_KERNEL); 46 buf = kzalloc(bufsz, GFP_KERNEL);
48 if (!buf) { 47 if (!buf) {
49 mutex_unlock(&dev->device_lock); 48 up_read(&dev->me_clients_rwsem);
50 return -ENOMEM; 49 return -ENOMEM;
51 } 50 }
52 51
@@ -56,10 +55,9 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
56 if (dev->dev_state != MEI_DEV_ENABLED) 55 if (dev->dev_state != MEI_DEV_ENABLED)
57 goto out; 56 goto out;
58 57
59 list_for_each_entry_safe(me_cl, n, &dev->me_clients, list) { 58 list_for_each_entry(me_cl, &dev->me_clients, list) {
60 59
61 me_cl = mei_me_cl_get(me_cl); 60 if (mei_me_cl_get(me_cl)) {
62 if (me_cl) {
63 pos += scnprintf(buf + pos, bufsz - pos, 61 pos += scnprintf(buf + pos, bufsz - pos,
64 "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n", 62 "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
65 i++, me_cl->client_id, 63 i++, me_cl->client_id,
@@ -69,12 +67,13 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
69 me_cl->props.max_msg_length, 67 me_cl->props.max_msg_length,
70 me_cl->props.single_recv_buf, 68 me_cl->props.single_recv_buf,
71 atomic_read(&me_cl->refcnt.refcount)); 69 atomic_read(&me_cl->refcnt.refcount));
72 }
73 70
74 mei_me_cl_put(me_cl); 71 mei_me_cl_put(me_cl);
72 }
75 } 73 }
74
76out: 75out:
77 mutex_unlock(&dev->device_lock); 76 up_read(&dev->me_clients_rwsem);
78 ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); 77 ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
79 kfree(buf); 78 kfree(buf);
80 return ret; 79 return ret;
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index c8412d41e4f1..4f83e9aaa6f9 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -338,7 +338,8 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
338 me_cl->client_id = res->me_addr; 338 me_cl->client_id = res->me_addr;
339 me_cl->mei_flow_ctrl_creds = 0; 339 me_cl->mei_flow_ctrl_creds = 0;
340 340
341 list_add(&me_cl->list, &dev->me_clients); 341 mei_me_cl_add(dev, me_cl);
342
342 return 0; 343 return 0;
343} 344}
344 345
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 9306219d5675..106c054f573f 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -387,6 +387,7 @@ void mei_device_init(struct mei_device *dev,
387 INIT_LIST_HEAD(&dev->device_list); 387 INIT_LIST_HEAD(&dev->device_list);
388 INIT_LIST_HEAD(&dev->me_clients); 388 INIT_LIST_HEAD(&dev->me_clients);
389 mutex_init(&dev->device_lock); 389 mutex_init(&dev->device_lock);
390 init_rwsem(&dev->me_clients_rwsem);
390 init_waitqueue_head(&dev->wait_hw_ready); 391 init_waitqueue_head(&dev->wait_hw_ready);
391 init_waitqueue_head(&dev->wait_pg); 392 init_waitqueue_head(&dev->wait_pg);
392 init_waitqueue_head(&dev->wait_hbm_start); 393 init_waitqueue_head(&dev->wait_hbm_start);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 6c6ce9381535..102cc6603eba 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -460,6 +460,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
460 * @version : HBM protocol version in use 460 * @version : HBM protocol version in use
461 * @hbm_f_pg_supported : hbm feature pgi protocol 461 * @hbm_f_pg_supported : hbm feature pgi protocol
462 * 462 *
463 * @me_clients_rwsem: rw lock over me_clients list
463 * @me_clients : list of FW clients 464 * @me_clients : list of FW clients
464 * @me_clients_map : FW clients bit map 465 * @me_clients_map : FW clients bit map
465 * @host_clients_map : host clients id pool 466 * @host_clients_map : host clients id pool
@@ -556,6 +557,7 @@ struct mei_device {
556 struct hbm_version version; 557 struct hbm_version version;
557 unsigned int hbm_f_pg_supported:1; 558 unsigned int hbm_f_pg_supported:1;
558 559
560 struct rw_semaphore me_clients_rwsem;
559 struct list_head me_clients; 561 struct list_head me_clients;
560 DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX); 562 DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
561 DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX); 563 DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);