aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-11-16 15:51:29 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-17 10:37:49 -0500
commit7c7a6077f5c7a35fc03a7f452875d8440dd1bc8d (patch)
treee495b143494b3a7b98ce1841d8cc3c2a5f97c2cf
parentc110cdb171488c60295d49fda16634cfec58ae28 (diff)
mei: bus: split RX and async notification callbacks
Split callbacks for RX and async notification events on mei bus to eliminate synchronization problems and to open way for RX optimizations. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mei/bus.c141
-rw-r--r--drivers/misc/mei/client.c5
-rw-r--r--drivers/nfc/mei_phy.c36
-rw-r--r--drivers/watchdog/mei_wdt.c36
-rw-r--r--include/linux/mei_cl_bus.h32
5 files changed, 128 insertions, 122 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 483587f60249..2fd254ecde2f 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -209,31 +209,40 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
209EXPORT_SYMBOL_GPL(mei_cldev_recv); 209EXPORT_SYMBOL_GPL(mei_cldev_recv);
210 210
211/** 211/**
212 * mei_cl_bus_event_work - dispatch rx event for a bus device 212 * mei_cl_bus_rx_work - dispatch rx event for a bus device
213 * and schedule new work
214 * 213 *
215 * @work: work 214 * @work: work
216 */ 215 */
217static void mei_cl_bus_event_work(struct work_struct *work) 216static void mei_cl_bus_rx_work(struct work_struct *work)
218{ 217{
219 struct mei_cl_device *cldev; 218 struct mei_cl_device *cldev;
220 struct mei_device *bus; 219 struct mei_device *bus;
221 220
222 cldev = container_of(work, struct mei_cl_device, event_work); 221 cldev = container_of(work, struct mei_cl_device, rx_work);
223 222
224 bus = cldev->bus; 223 bus = cldev->bus;
225 224
226 if (cldev->event_cb) 225 if (cldev->rx_cb)
227 cldev->event_cb(cldev, cldev->events); 226 cldev->rx_cb(cldev);
228 227
229 cldev->events = 0; 228 mutex_lock(&bus->device_lock);
229 mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
230 mutex_unlock(&bus->device_lock);
231}
230 232
231 /* Prepare for the next read */ 233/**
232 if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { 234 * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
233 mutex_lock(&bus->device_lock); 235 *
234 mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL); 236 * @work: work
235 mutex_unlock(&bus->device_lock); 237 */
236 } 238static void mei_cl_bus_notif_work(struct work_struct *work)
239{
240 struct mei_cl_device *cldev;
241
242 cldev = container_of(work, struct mei_cl_device, notif_work);
243
244 if (cldev->notif_cb)
245 cldev->notif_cb(cldev);
237} 246}
238 247
239/** 248/**
@@ -248,18 +257,13 @@ bool mei_cl_bus_notify_event(struct mei_cl *cl)
248{ 257{
249 struct mei_cl_device *cldev = cl->cldev; 258 struct mei_cl_device *cldev = cl->cldev;
250 259
251 if (!cldev || !cldev->event_cb) 260 if (!cldev || !cldev->notif_cb)
252 return false;
253
254 if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
255 return false; 261 return false;
256 262
257 if (!cl->notify_ev) 263 if (!cl->notify_ev)
258 return false; 264 return false;
259 265
260 set_bit(MEI_CL_EVENT_NOTIF, &cldev->events); 266 schedule_work(&cldev->notif_work);
261
262 schedule_work(&cldev->event_work);
263 267
264 cl->notify_ev = false; 268 cl->notify_ev = false;
265 269
@@ -267,7 +271,7 @@ bool mei_cl_bus_notify_event(struct mei_cl *cl)
267} 271}
268 272
269/** 273/**
270 * mei_cl_bus_rx_event - schedule rx event 274 * mei_cl_bus_rx_event - schedule rx event
271 * 275 *
272 * @cl: host client 276 * @cl: host client
273 * 277 *
@@ -278,64 +282,81 @@ bool mei_cl_bus_rx_event(struct mei_cl *cl)
278{ 282{
279 struct mei_cl_device *cldev = cl->cldev; 283 struct mei_cl_device *cldev = cl->cldev;
280 284
281 if (!cldev || !cldev->event_cb) 285 if (!cldev || !cldev->rx_cb)
282 return false;
283
284 if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
285 return false; 286 return false;
286 287
287 set_bit(MEI_CL_EVENT_RX, &cldev->events); 288 schedule_work(&cldev->rx_work);
288
289 schedule_work(&cldev->event_work);
290 289
291 return true; 290 return true;
292} 291}
293 292
294/** 293/**
295 * mei_cldev_register_event_cb - register event callback 294 * mei_cldev_register_rx_cb - register Rx event callback
296 * 295 *
297 * @cldev: me client devices 296 * @cldev: me client devices
298 * @event_cb: callback function 297 * @rx_cb: callback function
299 * @events_mask: requested events bitmask
300 * 298 *
301 * Return: 0 on success 299 * Return: 0 on success
302 * -EALREADY if an callback is already registered 300 * -EALREADY if an callback is already registered
303 * <0 on other errors 301 * <0 on other errors
304 */ 302 */
305int mei_cldev_register_event_cb(struct mei_cl_device *cldev, 303int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
306 unsigned long events_mask,
307 mei_cldev_event_cb_t event_cb)
308{ 304{
309 struct mei_device *bus = cldev->bus; 305 struct mei_device *bus = cldev->bus;
310 int ret; 306 int ret;
311 307
312 if (cldev->event_cb) 308 if (!rx_cb)
309 return -EINVAL;
310 if (cldev->rx_cb)
313 return -EALREADY; 311 return -EALREADY;
314 312
315 cldev->events = 0; 313 cldev->rx_cb = rx_cb;
316 cldev->events_mask = events_mask; 314 INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
317 cldev->event_cb = event_cb;
318 INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
319 315
320 if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { 316 mutex_lock(&bus->device_lock);
321 mutex_lock(&bus->device_lock); 317 ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
322 ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL); 318 mutex_unlock(&bus->device_lock);
323 mutex_unlock(&bus->device_lock); 319 if (ret && ret != -EBUSY)
324 if (ret && ret != -EBUSY) 320 return ret;
325 return ret;
326 }
327 321
328 if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) { 322 return 0;
329 mutex_lock(&bus->device_lock); 323}
330 ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0); 324EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);
331 mutex_unlock(&bus->device_lock); 325
332 if (ret) 326/**
333 return ret; 327 * mei_cldev_register_notif_cb - register FW notification event callback
334 } 328 *
329 * @cldev: me client devices
330 * @notif_cb: callback function
331 *
332 * Return: 0 on success
333 * -EALREADY if an callback is already registered
334 * <0 on other errors
335 */
336int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
337 mei_cldev_cb_t notif_cb)
338{
339 struct mei_device *bus = cldev->bus;
340 int ret;
341
342 if (!notif_cb)
343 return -EINVAL;
344
345 if (cldev->notif_cb)
346 return -EALREADY;
347
348 cldev->notif_cb = notif_cb;
349 INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);
350
351 mutex_lock(&bus->device_lock);
352 ret = mei_cl_notify_request(cldev->cl, NULL, 1);
353 mutex_unlock(&bus->device_lock);
354 if (ret)
355 return ret;
335 356
336 return 0; 357 return 0;
337} 358}
338EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb); 359EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
339 360
340/** 361/**
341 * mei_cldev_get_drvdata - driver data getter 362 * mei_cldev_get_drvdata - driver data getter
@@ -471,8 +492,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
471 492
472 bus = cldev->bus; 493 bus = cldev->bus;
473 494
474 cldev->event_cb = NULL;
475
476 mutex_lock(&bus->device_lock); 495 mutex_lock(&bus->device_lock);
477 496
478 if (!mei_cl_is_connected(cl)) { 497 if (!mei_cl_is_connected(cl)) {
@@ -619,9 +638,13 @@ static int mei_cl_device_remove(struct device *dev)
619 if (!cldev || !dev->driver) 638 if (!cldev || !dev->driver)
620 return 0; 639 return 0;
621 640
622 if (cldev->event_cb) { 641 if (cldev->rx_cb) {
623 cldev->event_cb = NULL; 642 cancel_work_sync(&cldev->rx_work);
624 cancel_work_sync(&cldev->event_work); 643 cldev->rx_cb = NULL;
644 }
645 if (cldev->notif_cb) {
646 cancel_work_sync(&cldev->notif_work);
647 cldev->notif_cb = NULL;
625 } 648 }
626 649
627 cldrv = to_mei_cl_driver(dev->driver); 650 cldrv = to_mei_cl_driver(dev->driver);
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 46ee9155ada6..9635b14b6011 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -673,6 +673,11 @@ int mei_cl_unlink(struct mei_cl *cl)
673 list_del_init(&cl->link); 673 list_del_init(&cl->link);
674 674
675 cl->state = MEI_FILE_UNINITIALIZED; 675 cl->state = MEI_FILE_UNINITIALIZED;
676 cl->writing_state = MEI_IDLE;
677
678 WARN_ON(!list_empty(&cl->rd_completed) ||
679 !list_empty(&cl->rd_pending) ||
680 !list_empty(&cl->link));
676 681
677 return 0; 682 return 0;
678} 683}
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
index 03139c5a05e4..8a04c5e02999 100644
--- a/drivers/nfc/mei_phy.c
+++ b/drivers/nfc/mei_phy.c
@@ -297,9 +297,11 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
297} 297}
298 298
299 299
300static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events) 300static void nfc_mei_rx_cb(struct mei_cl_device *cldev)
301{ 301{
302 struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev); 302 struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
303 struct sk_buff *skb;
304 int reply_size;
303 305
304 if (!phy) 306 if (!phy)
305 return; 307 return;
@@ -307,27 +309,22 @@ static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events)
307 if (phy->hard_fault != 0) 309 if (phy->hard_fault != 0)
308 return; 310 return;
309 311
310 if (events & BIT(MEI_CL_EVENT_RX)) { 312 skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
311 struct sk_buff *skb; 313 if (!skb)
312 int reply_size; 314 return;
313
314 skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
315 if (!skb)
316 return;
317 315
318 reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ); 316 reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
319 if (reply_size < MEI_NFC_HEADER_SIZE) { 317 if (reply_size < MEI_NFC_HEADER_SIZE) {
320 kfree_skb(skb); 318 kfree_skb(skb);
321 return; 319 return;
322 } 320 }
323 321
324 skb_put(skb, reply_size); 322 skb_put(skb, reply_size);
325 skb_pull(skb, MEI_NFC_HEADER_SIZE); 323 skb_pull(skb, MEI_NFC_HEADER_SIZE);
326 324
327 MEI_DUMP_SKB_IN("mei frame read", skb); 325 MEI_DUMP_SKB_IN("mei frame read", skb);
328 326
329 nfc_hci_recv_frame(phy->hdev, skb); 327 nfc_hci_recv_frame(phy->hdev, skb);
330 }
331} 328}
332 329
333static int nfc_mei_phy_enable(void *phy_id) 330static int nfc_mei_phy_enable(void *phy_id)
@@ -358,8 +355,7 @@ static int nfc_mei_phy_enable(void *phy_id)
358 goto err; 355 goto err;
359 } 356 }
360 357
361 r = mei_cldev_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX), 358 r = mei_cldev_register_rx_cb(phy->cldev, nfc_mei_rx_cb);
362 nfc_mei_event_cb);
363 if (r) { 359 if (r) {
364 pr_err("Event cb registration failed %d\n", r); 360 pr_err("Event cb registration failed %d\n", r);
365 goto err; 361 goto err;
diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
index e0af52265511..79b35515904e 100644
--- a/drivers/watchdog/mei_wdt.c
+++ b/drivers/watchdog/mei_wdt.c
@@ -410,11 +410,11 @@ static void mei_wdt_unregister_work(struct work_struct *work)
410} 410}
411 411
412/** 412/**
413 * mei_wdt_event_rx - callback for data receive 413 * mei_wdt_rx - callback for data receive
414 * 414 *
415 * @cldev: bus device 415 * @cldev: bus device
416 */ 416 */
417static void mei_wdt_event_rx(struct mei_cl_device *cldev) 417static void mei_wdt_rx(struct mei_cl_device *cldev)
418{ 418{
419 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); 419 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
420 struct mei_wdt_start_response res; 420 struct mei_wdt_start_response res;
@@ -482,11 +482,11 @@ out:
482} 482}
483 483
484/* 484/*
485 * mei_wdt_notify_event - callback for event notification 485 * mei_wdt_notif - callback for event notification
486 * 486 *
487 * @cldev: bus device 487 * @cldev: bus device
488 */ 488 */
489static void mei_wdt_notify_event(struct mei_cl_device *cldev) 489static void mei_wdt_notif(struct mei_cl_device *cldev)
490{ 490{
491 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); 491 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
492 492
@@ -496,21 +496,6 @@ static void mei_wdt_notify_event(struct mei_cl_device *cldev)
496 mei_wdt_register(wdt); 496 mei_wdt_register(wdt);
497} 497}
498 498
499/**
500 * mei_wdt_event - callback for event receive
501 *
502 * @cldev: bus device
503 * @events: event mask
504 */
505static void mei_wdt_event(struct mei_cl_device *cldev, u32 events)
506{
507 if (events & BIT(MEI_CL_EVENT_RX))
508 mei_wdt_event_rx(cldev);
509
510 if (events & BIT(MEI_CL_EVENT_NOTIF))
511 mei_wdt_notify_event(cldev);
512}
513
514#if IS_ENABLED(CONFIG_DEBUG_FS) 499#if IS_ENABLED(CONFIG_DEBUG_FS)
515 500
516static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf, 501static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf,
@@ -621,16 +606,17 @@ static int mei_wdt_probe(struct mei_cl_device *cldev,
621 goto err_out; 606 goto err_out;
622 } 607 }
623 608
624 ret = mei_cldev_register_event_cb(wdt->cldev, 609 ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx);
625 BIT(MEI_CL_EVENT_RX) | 610 if (ret) {
626 BIT(MEI_CL_EVENT_NOTIF), 611 dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret);
627 mei_wdt_event); 612 goto err_disable;
613 }
628 614
615 ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif);
629 /* on legacy devices notification is not supported 616 /* on legacy devices notification is not supported
630 * this doesn't fail the registration for RX event
631 */ 617 */
632 if (ret && ret != -EOPNOTSUPP) { 618 if (ret && ret != -EOPNOTSUPP) {
633 dev_err(&cldev->dev, "Could not register event ret=%d\n", ret); 619 dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret);
634 goto err_disable; 620 goto err_disable;
635 } 621 }
636 622
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 4adb2e7c9f84..017f5232b3de 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -8,8 +8,7 @@
8struct mei_cl_device; 8struct mei_cl_device;
9struct mei_device; 9struct mei_device;
10 10
11typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev, 11typedef void (*mei_cldev_cb_t)(struct mei_cl_device *cldev);
12 u32 events);
13 12
14/** 13/**
15 * struct mei_cl_device - MEI device handle 14 * struct mei_cl_device - MEI device handle
@@ -24,11 +23,12 @@ typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev,
24 * @me_cl: me client 23 * @me_cl: me client
25 * @cl: mei client 24 * @cl: mei client
26 * @name: device name 25 * @name: device name
27 * @event_work: async work to execute event callback 26 * @rx_work: async work to execute Rx event callback
28 * @event_cb: Drivers register this callback to get asynchronous ME 27 * @rx_cb: Drivers register this callback to get asynchronous ME
29 * events (e.g. Rx buffer pending) notifications. 28 * Rx buffer pending notifications.
30 * @events_mask: Events bit mask requested by driver. 29 * @notif_work: async work to execute FW notif event callback
31 * @events: Events bitmask sent to the driver. 30 * @notif_cb: Drivers register this callback to get asynchronous ME
31 * FW notification pending notifications.
32 * 32 *
33 * @do_match: wheather device can be matched with a driver 33 * @do_match: wheather device can be matched with a driver
34 * @is_added: device is already scanned 34 * @is_added: device is already scanned
@@ -43,10 +43,10 @@ struct mei_cl_device {
43 struct mei_cl *cl; 43 struct mei_cl *cl;
44 char name[MEI_CL_NAME_SIZE]; 44 char name[MEI_CL_NAME_SIZE];
45 45
46 struct work_struct event_work; 46 struct work_struct rx_work;
47 mei_cldev_event_cb_t event_cb; 47 mei_cldev_cb_t rx_cb;
48 unsigned long events_mask; 48 struct work_struct notif_work;
49 unsigned long events; 49 mei_cldev_cb_t notif_cb;
50 50
51 unsigned int do_match:1; 51 unsigned int do_match:1;
52 unsigned int is_added:1; 52 unsigned int is_added:1;
@@ -88,13 +88,9 @@ void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv);
88ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length); 88ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
89ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); 89ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
90 90
91int mei_cldev_register_event_cb(struct mei_cl_device *cldev, 91int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
92 unsigned long event_mask, 92int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
93 mei_cldev_event_cb_t read_cb); 93 mei_cldev_cb_t notif_cb);
94
95#define MEI_CL_EVENT_RX 0
96#define MEI_CL_EVENT_TX 1
97#define MEI_CL_EVENT_NOTIF 2
98 94
99const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev); 95const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev);
100u8 mei_cldev_ver(const struct mei_cl_device *cldev); 96u8 mei_cldev_ver(const struct mei_cl_device *cldev);