From 5d385bce9dcd52f75a252d8026c880e9efdebb9a Mon Sep 17 00:00:00 2001 From: litong Date: Thu, 12 Nov 2020 15:24:58 +0800 Subject: [PATCH] An common module used for all of module communication. The module encapsule a group of notification, used for decoupling between modules, for example, the touchscreen driver are coupling fingerprint and display driver in the bring-up phase, the dependencies between modules need to fixed to avoid proceeding blocked, This module is middle layer, it change a direct dependece into an indirect dependence. Change-Id: I4469dd70300fce2dc5d9af48e96d65755974ef9f Reviewed-on: https://gerrit.mot.com/1802936 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Sergio Vilela Submit-Approved: Sergio Vilela Tested-by: Sergio Vilela --- drivers/mmi_relay/Android.mk | 12 ++ drivers/mmi_relay/Kbuild | 5 + drivers/mmi_relay/Makefile | 10 ++ drivers/mmi_relay/mmi_relay.c | 234 ++++++++++++++++++++++++++++++++++ include/linux/mmi_relay.h | 28 ++++ 5 files changed, 289 insertions(+) create mode 100644 drivers/mmi_relay/Android.mk create mode 100644 drivers/mmi_relay/Kbuild create mode 100644 drivers/mmi_relay/Makefile create mode 100644 drivers/mmi_relay/mmi_relay.c create mode 100644 include/linux/mmi_relay.h diff --git a/drivers/mmi_relay/Android.mk b/drivers/mmi_relay/Android.mk new file mode 100644 index 000000000000..1d574e1facb3 --- /dev/null +++ b/drivers/mmi_relay/Android.mk @@ -0,0 +1,12 @@ +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := mmi_relay.ko +LOCAL_MODULE_TAGS := optional +ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true) +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/ +else +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +endif +include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/mmi_relay/Kbuild b/drivers/mmi_relay/Kbuild new file mode 100644 index 000000000000..12e00ae16d00 --- /dev/null +++ b/drivers/mmi_relay/Kbuild @@ -0,0 +1,5 @@ +# add -Wall to try to catch everything we can. +EXTRA_CFLAGS += -Wall +EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include + +obj-m += mmi_relay.o diff --git a/drivers/mmi_relay/Makefile b/drivers/mmi_relay/Makefile new file mode 100644 index 000000000000..34b09dd815a7 --- /dev/null +++ b/drivers/mmi_relay/Makefile @@ -0,0 +1,10 @@ +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean \ No newline at end of file diff --git a/drivers/mmi_relay/mmi_relay.c b/drivers/mmi_relay/mmi_relay.c new file mode 100644 index 000000000000..14a91fe620b7 --- /dev/null +++ b/drivers/mmi_relay/mmi_relay.c @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _relay_node { + struct list_head list; + union { + struct atomic_notifier_head atomic_head; + struct blocking_notifier_head blocking_head; + }; + int id; + notifier_t type; + notifier_d dev; +}relay_node; + +struct mmi_relay_dev { + struct platform_device *pdev; + struct mutex lock; + relay_node nodes[NUM_TYPES][NUM_DEVS]; + unsigned notifier_nums; +}; +static struct mmi_relay_dev* relay_dev; + +/* + * Informs the registered notifiers about an event + * @type: notification type: atomic blocking + * @dev: notification sender + * @val: value passed to notifier function + */ + +int relay_notifier_fire(notifier_t type, notifier_d dev, unsigned long val, void *v) +{ + int ret = 0; + + if(!relay_dev) { + pr_err("Device is not initialized\n"); + return -EINVAL; + } + + if(type >= NUM_TYPES || dev >= NUM_DEVS) { + pr_err("Relay error type or dev\n"); + return -EPERM; + } + switch(type) { + case ATOMIC: + { + struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head; + ret = atomic_notifier_call_chain(h, val, v); + break; + } + case BLOCKING: + { + struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head; + ret = blocking_notifier_call_chain(h, val, v); + break; + } + default: + BUG_ON(1); + } + return ret; +} +EXPORT_SYMBOL_GPL(relay_notifier_fire); + +/** + * Register an atomic or blocking notify to receive notifications from dev. + * @dev: notification sender + */ +int relay_register_action(notifier_t type, notifier_d dev, struct notifier_block * nb) +{ + int ret = 0; + + if(!relay_dev) { + pr_err("Device is not initialized\n"); + return -EINVAL; + } + + if(type >= NUM_TYPES || dev >= NUM_DEVS) { + pr_err("Relay error type or dev\n"); + return -EPERM; + } + + mutex_lock(&relay_dev->lock); + switch(type) { + case ATOMIC: + { + struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head; + ret = atomic_notifier_chain_register(h, nb); + if (!ret) + relay_notifier_fire(ATOMIC, MMI_RELAY, RELAY_NOTIFY_REGISTER, NULL); + break; + } + case BLOCKING: + { + struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head; + ret = blocking_notifier_chain_register(h, nb); + if (!ret) + relay_notifier_fire(BLOCKING, MMI_RELAY, RELAY_NOTIFY_REGISTER, NULL); + + break; + } + default: + BUG_ON(1); + } + mutex_unlock(&relay_dev->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(relay_register_action); + +int relay_unregister_action(notifier_t type, notifier_d dev, struct notifier_block *nb) +{ + int ret = 0; + + if(!relay_dev) { + pr_err("Device is not initialized\n"); + return -EINVAL; + } + + if(type >= NUM_TYPES || dev >= NUM_DEVS) { + pr_err("Relay error type or dev\n"); + return -EPERM; + } + + mutex_lock(&relay_dev->lock); + switch(type) { + case ATOMIC: + { + struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head; + ret = atomic_notifier_chain_unregister(h, nb); + if (!ret) + relay_notifier_fire(ATOMIC, MMI_RELAY, RELAY_NOTIFY_UNREGISTER, NULL); + break; + } + case BLOCKING: + { + struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head; + ret = blocking_notifier_chain_unregister(h, nb); + if (!ret) + relay_notifier_fire(BLOCKING, MMI_RELAY, RELAY_NOTIFY_UNREGISTER, NULL); + break; + } + default: + BUG_ON(1); + } + mutex_unlock(&relay_dev->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(relay_unregister_action); + +static int mmi_relay_probe(struct platform_device *pdev) +{ + notifier_t i; + notifier_d j; + + relay_dev = kzalloc(sizeof(struct mmi_relay_dev), GFP_KERNEL); + if (!relay_dev) { + pr_err("Failed to allocate memory for relay_dev\n"); + return -ENOMEM; + } + + relay_dev->pdev = pdev; + relay_dev->notifier_nums = NUM_DEVS * NUM_TYPES; + + mutex_init(&relay_dev->lock); + + for(i = (notifier_t)0; i < NUM_TYPES; i++) { + for(j = (notifier_d)0; j < NUM_DEVS; j++) { + relay_dev->nodes[i][j].type = i; + relay_dev->nodes[i][j].dev= j; + relay_dev->nodes[i][j].id = i << 16 | j; + INIT_LIST_HEAD(&relay_dev->nodes[i][j].list); + + if(i == ATOMIC) { + ATOMIC_INIT_NOTIFIER_HEAD(&relay_dev->nodes[i][j].atomic_head); + } else { + BLOCKING_INIT_NOTIFIER_HEAD(&relay_dev->nodes[i][j].blocking_head); + } + } + } + return 0; +} + +static int mmi_relay_remove(struct platform_device *pdev) +{ + kfree(relay_dev); + return 0; +} + +static const struct of_device_id mmi_relay_mt[] = { + {.compatible = "mmi,sys-relay"}, + {}, +}; +MODULE_DEVICE_TABLE(of, mmi_relay_mt); + +static struct platform_driver mmi_relay_driver = { + .probe = mmi_relay_probe, + .remove = mmi_relay_remove, + .driver = { + .name = "mmi_relay", + .owner = THIS_MODULE, + .of_match_table = mmi_relay_mt, + }, +}; + +static int __init mmi_relay_init(void) +{ + return platform_driver_register(&mmi_relay_driver); +} + +static void __exit mmi_relay_exit(void) +{ + platform_driver_unregister(&mmi_relay_driver); +} + +module_init(mmi_relay_init); +module_exit(mmi_relay_exit); + +MODULE_ALIAS("platform:mmi_relay"); +MODULE_AUTHOR("Motorola Mobility LLC"); +MODULE_DESCRIPTION("Motorola Mobility Module Conmmunication Relay"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mmi_relay.h b/include/linux/mmi_relay.h new file mode 100644 index 000000000000..f2de826f6f0e --- /dev/null +++ b/include/linux/mmi_relay.h @@ -0,0 +1,28 @@ +#ifndef __MMI_RELAY_H__ +#define __MMI_RELAY_H__ + +#include + +typedef enum notifier_type { + ATOMIC, + BLOCKING, + NUM_TYPES, +}notifier_t; + +typedef enum notifier_dev { + LCD, + FPS, + MMI_RELAY, + NUM_DEVS, +}notifier_d; + +enum mmi_relay_event { + RELAY_NOTIFY_REGISTER, + RELAY_NOTIFY_UNREGISTER, +}; + +extern int relay_notifier_fire(notifier_t type, notifier_d dev, unsigned long val, void *v); +extern int relay_register_action(notifier_t type, notifier_d dev, struct notifier_block * nb); +extern int relay_unregister_action(notifier_t type, notifier_d dev, struct notifier_block * nb); + +#endif