aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-07-23 08:08:43 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-03 20:24:16 -0400
commit71ce789115f878a07e4a6c43d6006cea6aee1078 (patch)
treeaef1e29741969c8b7b3d0501e4c451fba1fe456a
parent0ff0a8d853039aa60bba3ca3e04e4fb74584a736 (diff)
mei: bus: enable running fixup routines before device registration
Split the device registration into allocation and device struct initialization, device setup, and the final device registration. This why it is possible to run fixups and quirks during the setup stage on an initialized device. Each fixup routine effects do_match flag. If the flag is set to false at the end the device won't be registered on the bus. 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-fixup.c30
-rw-r--r--drivers/misc/mei/bus.c91
-rw-r--r--drivers/misc/mei/mei_dev.h2
-rw-r--r--include/linux/mei_cl_bus.h4
4 files changed, 111 insertions, 16 deletions
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 47aa1523d9e1..865e33bcd226 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -20,12 +20,15 @@
20#include <linux/moduleparam.h> 20#include <linux/moduleparam.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/uuid.h>
23 24
24#include <linux/mei_cl_bus.h> 25#include <linux/mei_cl_bus.h>
25 26
26#include "mei_dev.h" 27#include "mei_dev.h"
27#include "client.h" 28#include "client.h"
28 29
30#define MEI_UUID_ANY NULL_UUID_LE
31
29struct mei_nfc_cmd { 32struct mei_nfc_cmd {
30 u8 command; 33 u8 command;
31 u8 status; 34 u8 status;
@@ -412,4 +415,31 @@ void mei_nfc_host_exit(struct mei_device *bus)
412 mutex_unlock(&bus->device_lock); 415 mutex_unlock(&bus->device_lock);
413} 416}
414 417
418#define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }
419
420static struct mei_fixup {
421
422 const uuid_le uuid;
423 void (*hook)(struct mei_cl_device *cldev);
424} mei_fixups[] = {};
425
426/**
427 * mei_cl_dev_fixup - run fixup handlers
428 *
429 * @cldev: me client device
430 */
431void mei_cl_dev_fixup(struct mei_cl_device *cldev)
432{
433 struct mei_fixup *f;
434 const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
435 int i;
436
437 for (i = 0; i < ARRAY_SIZE(mei_fixups); i++) {
438
439 f = &mei_fixups[i];
440 if (uuid_le_cmp(f->uuid, MEI_UUID_ANY) == 0 ||
441 uuid_le_cmp(f->uuid, *uuid) == 0)
442 f->hook(cldev);
443 }
444}
415 445
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 34b14dda050c..68b7756bf384 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -436,6 +436,9 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
436 if (!cldev) 436 if (!cldev)
437 return 0; 437 return 0;
438 438
439 if (!cldev->do_match)
440 return 0;
441
439 if (!cldrv || !cldrv->id_table) 442 if (!cldrv || !cldrv->id_table)
440 return 0; 443 return 0;
441 444
@@ -634,6 +637,76 @@ struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *bus,
634 return NULL; 637 return NULL;
635} 638}
636 639
640/**
641 * mei_cl_dev_alloc - initialize and allocate mei client device
642 *
643 * @bus: mei device
644 * @me_cl: me client
645 *
646 * Return: allocated device structur or NULL on allocation failure
647 */
648static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
649 struct mei_me_client *me_cl)
650{
651 struct mei_cl_device *cldev;
652
653 cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
654 if (!cldev)
655 return NULL;
656
657 device_initialize(&cldev->dev);
658 cldev->dev.parent = bus->dev;
659 cldev->dev.bus = &mei_cl_bus_type;
660 cldev->dev.type = &mei_cl_device_type;
661 cldev->bus = mei_dev_bus_get(bus);
662 cldev->me_cl = mei_me_cl_get(me_cl);
663 cldev->is_added = 0;
664 INIT_LIST_HEAD(&cldev->bus_list);
665
666 return cldev;
667}
668
669/**
670 * mei_cl_dev_setup - setup me client device
671 * run fix up routines and set the device name
672 *
673 * @bus: mei device
674 * @cldev: me client device
675 *
676 * Return: true if the device is eligible for enumeration
677 */
678static bool mei_cl_dev_setup(struct mei_device *bus,
679 struct mei_cl_device *cldev)
680{
681 cldev->do_match = 1;
682 mei_cl_dev_fixup(cldev);
683
684 if (cldev->do_match)
685 dev_set_name(&cldev->dev, "mei:%s:%pUl",
686 cldev->name, mei_me_cl_uuid(cldev->me_cl));
687
688 return cldev->do_match == 1;
689}
690
691/**
692 * mei_cl_bus_dev_add - add me client devices
693 *
694 * @cldev: me client device
695 *
696 * Return: 0 on success; < 0 on failre
697 */
698static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
699{
700 int ret;
701
702 dev_dbg(cldev->bus->dev, "adding %pUL\n", mei_me_cl_uuid(cldev->me_cl));
703 ret = device_add(&cldev->dev);
704 if (!ret)
705 cldev->is_added = 1;
706
707 return ret;
708}
709
637struct mei_cl_device *mei_cl_add_device(struct mei_device *bus, 710struct mei_cl_device *mei_cl_add_device(struct mei_device *bus,
638 struct mei_me_client *me_cl, 711 struct mei_me_client *me_cl,
639 struct mei_cl *cl, 712 struct mei_cl *cl,
@@ -642,28 +715,16 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *bus,
642 struct mei_cl_device *cldev; 715 struct mei_cl_device *cldev;
643 int status; 716 int status;
644 717
645 cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL); 718 cldev = mei_cl_dev_alloc(bus, me_cl);
646 if (!cldev) 719 if (!cldev)
647 return NULL; 720 return NULL;
648 721
649 cldev->me_cl = mei_me_cl_get(me_cl);
650 if (!cldev->me_cl) {
651 kfree(cldev);
652 return NULL;
653 }
654
655 cldev->cl = cl; 722 cldev->cl = cl;
656 cldev->dev.parent = bus->dev;
657 cldev->dev.bus = &mei_cl_bus_type;
658 cldev->dev.type = &mei_cl_device_type;
659 cldev->bus = mei_dev_bus_get(bus);
660 INIT_LIST_HEAD(&cldev->bus_list);
661
662 strlcpy(cldev->name, name, sizeof(cldev->name)); 723 strlcpy(cldev->name, name, sizeof(cldev->name));
663 724
664 dev_set_name(&cldev->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl)); 725 mei_cl_dev_setup(bus, cldev);
665 726
666 status = device_register(&cldev->dev); 727 status = mei_cl_bus_dev_add(cldev);
667 if (status) { 728 if (status) {
668 dev_err(bus->dev, "Failed to register MEI device\n"); 729 dev_err(bus->dev, "Failed to register MEI device\n");
669 mei_me_cl_put(cldev->me_cl); 730 mei_me_cl_put(cldev->me_cl);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 882e6f77084a..ad59ab776f2d 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -335,7 +335,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *bus,
335 struct mei_cl *cl, 335 struct mei_cl *cl,
336 char *name); 336 char *name);
337void mei_cl_remove_device(struct mei_cl_device *cldev); 337void mei_cl_remove_device(struct mei_cl_device *cldev);
338 338void mei_cl_dev_fixup(struct mei_cl_device *dev);
339ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, 339ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
340 bool blocking); 340 bool blocking);
341ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); 341ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 85239138251c..81ab56dd0ae0 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -29,6 +29,8 @@ typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
29 * events (e.g. Rx buffer pending) notifications. 29 * events (e.g. Rx buffer pending) notifications.
30 * @event_context: event callback run context 30 * @event_context: event callback run context
31 * @events: Events bitmask sent to the driver. 31 * @events: Events bitmask sent to the driver.
32 *
33 * @do_match: wheather device can be matched with a driver
32 * @is_added: device is already scanned 34 * @is_added: device is already scanned
33 * @priv_data: client private data 35 * @priv_data: client private data
34 */ 36 */
@@ -45,6 +47,8 @@ struct mei_cl_device {
45 mei_cl_event_cb_t event_cb; 47 mei_cl_event_cb_t event_cb;
46 void *event_context; 48 void *event_context;
47 unsigned long events; 49 unsigned long events;
50
51 unsigned int do_match:1;
48 unsigned int is_added:1; 52 unsigned int is_added:1;
49 53
50 void *priv_data; 54 void *priv_data;