diff --git a/core/Android.mk b/core/Android.mk index b1211d666d64..d9e1d9714afd 100644 --- a/core/Android.mk +++ b/core/Android.mk @@ -33,5 +33,26 @@ KBUILD_OPTIONS := $(RMNET_BLD_DIR) $(warning $(DLKM_DIR)) include $(DLKM_DIR)/AndroidKernelModule.mk +######## Create RMNET_CTL DLKM ######## +include $(CLEAR_VARS) + +LOCAL_CFLAGS := -Wno-macro-redefined -Wno-unused-function -Wall -Werror +LOCAL_CLANG :=true + +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +LOCAL_MODULE := rmnet_ctl.ko + +LOCAL_SRC_FILES := \ + rmnet_ctl_client.c \ + rmnet_ctl_ipa.c + +RMNET_BLD_DIR := ../../vendor/qcom/opensource/datarmnet/core +DLKM_DIR := $(TOP)/device/qcom/common/dlkm + +KBUILD_OPTIONS := $(RMNET_BLD_DIR) + +$(warning $(DLKM_DIR)) +include $(DLKM_DIR)/AndroidKernelModule.mk + endif #End of Check for target endif #End of Check for qssi target diff --git a/core/Kbuild b/core/Kbuild index e9d19b16dc90..51ac345578dc 100644 --- a/core/Kbuild +++ b/core/Kbuild @@ -1,6 +1,8 @@ obj-m += rmnet_core.o +obj-m += rmnet_ctl.o rmnet_core-y := rmnet_config.o rmnet_handlers.o rmnet_descriptor.o \ rmnet_genl.o rmnet_map_command.o rmnet_map_data.o rmnet_vnd.o\ qmi_rmnet.o wda_qmi.o dfc_qmi.o dfc_qmap.o +rmnet_ctl-y := rmnet_ctl_client.o rmnet_ctl_ipa.o diff --git a/core/Kconfig b/core/Kconfig index b6356c1ee2a4..0fe2530349a4 100644 --- a/core/Kconfig +++ b/core/Kconfig @@ -10,3 +10,9 @@ menuconfig RMNET_CORE for handling data in the multiplexing and aggregation protocol (MAP) format in the embedded data path. RMNET devices can be attached to any IP mode physical device. + +menuconfig RMNET_CTL + default m + ---help--- + Enable the RMNET CTL module which is used for handling QMAP commands + for flow control purposes. diff --git a/core/rmnet_ctl.h b/core/rmnet_ctl.h index 0c7061837c12..54d2385c4eb9 100644 --- a/core/rmnet_ctl.h +++ b/core/rmnet_ctl.h @@ -10,6 +10,8 @@ #include +#define CONFIG_RMNET_CTL 1 + enum rmnet_ctl_log_lvl { RMNET_CTL_LOG_CRIT, RMNET_CTL_LOG_ERR, diff --git a/core/rmnet_ctl_client.c b/core/rmnet_ctl_client.c index f082101972ed..1fe348b1387d 100644 --- a/core/rmnet_ctl_client.c +++ b/core/rmnet_ctl_client.c @@ -26,6 +26,10 @@ struct rmnet_ctl_endpoint { void *ipc_log; }; +#if defined(CONFIG_IPA_DEBUG) || defined(CONFIG_MHI_DEBUG) +#define CONFIG_RMNET_CTL_DEBUG 1 +#endif + #ifdef CONFIG_RMNET_CTL_DEBUG static u8 ipc_log_lvl = RMNET_CTL_LOG_DEBUG; #else @@ -35,13 +39,13 @@ static u8 ipc_log_lvl = RMNET_CTL_LOG_ERR; static DEFINE_SPINLOCK(client_lock); static struct rmnet_ctl_endpoint ctl_ep; -void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev) +void rmnet_ctl_set_dbgfs(bool enable) { - rcu_assign_pointer(ctl_ep.dev, dev); + if (enable) { + if (IS_ERR_OR_NULL(ctl_ep.dbgfs_dir)) + ctl_ep.dbgfs_dir = debugfs_create_dir( + RMNET_CTL_LOG_NAME, NULL); - if (dev) { - ctl_ep.dbgfs_dir = debugfs_create_dir( - RMNET_CTL_LOG_NAME, NULL); if (!IS_ERR_OR_NULL(ctl_ep.dbgfs_dir)) ctl_ep.dbgfs_loglvl = debugfs_create_u8( RMNET_CTL_LOG_LVL, 0644, ctl_ep.dbgfs_dir, @@ -52,9 +56,18 @@ void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev) RMNET_CTL_LOG_PAGE, RMNET_CTL_LOG_NAME, 0); } else { debugfs_remove_recursive(ctl_ep.dbgfs_dir); + ipc_log_context_destroy(ctl_ep.ipc_log); + ctl_ep.dbgfs_dir = NULL; + ctl_ep.dbgfs_loglvl = NULL; + ctl_ep.ipc_log = NULL; } } +void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev) +{ + rcu_assign_pointer(ctl_ep.dev, dev); +} + void rmnet_ctl_endpoint_post(const void *data, size_t len) { struct rmnet_ctl_client *client; @@ -63,22 +76,38 @@ void rmnet_ctl_endpoint_post(const void *data, size_t len) if (unlikely(!data || !len)) return; - rmnet_ctl_log_info("RX", data, len); + if (len == 0xFFFFFFFF) { + skb = (struct sk_buff *)data; + rmnet_ctl_log_info("RX", skb->data, skb->len); - rcu_read_lock(); + rcu_read_lock(); - client = rcu_dereference(ctl_ep.client); - - if (client && client->hooks.ctl_dl_client_hook) { - skb = alloc_skb(len, GFP_ATOMIC); - if (skb) { - skb_put_data(skb, data, len); + client = rcu_dereference(ctl_ep.client); + if (client && client->hooks.ctl_dl_client_hook) { skb->protocol = htons(ETH_P_MAP); client->hooks.ctl_dl_client_hook(skb); + } else { + kfree(skb); } - } - rcu_read_unlock(); + rcu_read_unlock(); + } else { + rmnet_ctl_log_info("RX", data, len); + + rcu_read_lock(); + + client = rcu_dereference(ctl_ep.client); + if (client && client->hooks.ctl_dl_client_hook) { + skb = alloc_skb(len, GFP_ATOMIC); + if (skb) { + skb_put_data(skb, data, len); + skb->protocol = htons(ETH_P_MAP); + client->hooks.ctl_dl_client_hook(skb); + } + } + + rcu_read_unlock(); + } } void *rmnet_ctl_register_client(struct rmnet_ctl_client_hooks *hook) diff --git a/core/rmnet_ctl_client.h b/core/rmnet_ctl_client.h index 384064d134df..f7b1b6a69e61 100644 --- a/core/rmnet_ctl_client.h +++ b/core/rmnet_ctl_client.h @@ -25,5 +25,6 @@ struct rmnet_ctl_dev { void rmnet_ctl_endpoint_post(const void *data, size_t len); void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev); +void rmnet_ctl_set_dbgfs(bool enable); #endif /* _RMNET_CTL_CLIENT_H_ */ diff --git a/core/rmnet_ctl_ipa.c b/core/rmnet_ctl_ipa.c new file mode 100644 index 000000000000..fc4864cc12df --- /dev/null +++ b/core/rmnet_ctl_ipa.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * RMNET_CTL mhi handler + * + */ + +#include +#include +#include +#include "rmnet_ctl.h" +#include "rmnet_ctl_client.h" + +struct rmnet_ctl_ipa_dev { + struct rmnet_ctl_dev dev; + spinlock_t rx_lock; /* rx lock */ + spinlock_t tx_lock; /* tx lock */ +}; + +static struct rmnet_ctl_ipa_dev ctl_ipa_dev; + +static int rmnet_ctl_send_ipa(struct rmnet_ctl_dev *dev, struct sk_buff *skb) +{ + struct rmnet_ctl_ipa_dev *ctl_dev = container_of( + dev, struct rmnet_ctl_ipa_dev, dev); + int rc; + + spin_lock_bh(&ctl_dev->tx_lock); + + rc = ipa_rmnet_ctl_xmit(skb); + if (rc) + dev->stats.tx_err++; + else + dev->stats.tx_pkts++; + + spin_unlock_bh(&ctl_dev->tx_lock); + + return rc; +} + +static void rmnet_ctl_dl_callback(void *user_data, void *rx_data) +{ + struct rmnet_ctl_ipa_dev *ctl_dev = user_data; + + ctl_dev->dev.stats.rx_pkts++; + rmnet_ctl_endpoint_post(rx_data, 0xFFFFFFFF); +} + +static void rmnet_ctl_probe(void *user_data) +{ + memset(&ctl_ipa_dev, 0, sizeof(ctl_ipa_dev)); + + spin_lock_init(&ctl_ipa_dev.rx_lock); + spin_lock_init(&ctl_ipa_dev.tx_lock); + + ctl_ipa_dev.dev.xmit = rmnet_ctl_send_ipa; + rmnet_ctl_endpoint_setdev(&ctl_ipa_dev.dev); + + pr_info("rmnet_ctl driver probed\n"); +} + +static void rmnet_ctl_remove(void *user_data) +{ + rmnet_ctl_endpoint_setdev(NULL); + + pr_info("rmnet_ctl driver removed\n"); +} + +static void rmnet_ctl_ipa_ready(void *user_data) +{ + int rc; + + rc = ipa_register_rmnet_ctl_cb( + rmnet_ctl_probe, + &ctl_ipa_dev, + rmnet_ctl_remove, + &ctl_ipa_dev, + rmnet_ctl_dl_callback, + &ctl_ipa_dev); + + pr_info("%s: %d\n", __func__, rc); +} + +static int __init rmnet_ctl_init(void) +{ + int rc; + + rc = ipa_register_rmnet_ctl_cb( + rmnet_ctl_probe, + &ctl_ipa_dev, + rmnet_ctl_remove, + &ctl_ipa_dev, + rmnet_ctl_dl_callback, + &ctl_ipa_dev); + + if (rc == -EAGAIN) + rc = ipa_register_ipa_ready_cb( + rmnet_ctl_ipa_ready, NULL); + + pr_info("%s: %d\n", __func__, rc); + + return 0; +} + +static void __exit rmnet_ctl_exit(void) +{ + ipa_unregister_rmnet_ctl_cb(); +} + +module_init(rmnet_ctl_init) +module_exit(rmnet_ctl_exit) + +MODULE_DESCRIPTION("RmNet control IPA Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/core/rmnet_ctl_mhi.c b/core/rmnet_ctl_mhi.c index e22c137df01e..f9cc2ba2943c 100644 --- a/core/rmnet_ctl_mhi.c +++ b/core/rmnet_ctl_mhi.c @@ -199,8 +199,24 @@ static struct mhi_driver rmnet_ctl_driver = { }, }; -module_driver(rmnet_ctl_driver, - mhi_driver_register, mhi_driver_unregister); +static int __init rmnet_ctl_init(void) +{ + int rc; -MODULE_DESCRIPTION("RmNet Control Driver"); + rc = mhi_driver_register(&rmnet_ctl_driver); + rmnet_ctl_set_dbgfs(true); + + return rc; +} + +static void __exit rmnet_ctl_exit(void) +{ + mhi_driver_unregister(&rmnet_ctl_driver); + rmnet_ctl_set_dbgfs(false); +} + +module_init(rmnet_ctl_init) +module_exit(rmnet_ctl_exit) + +MODULE_DESCRIPTION("RmNet Control MHI Driver"); MODULE_LICENSE("GPL v2"); diff --git a/datarmnet_dlkm_vendor_board.mk b/datarmnet_dlkm_vendor_board.mk index 303c6b81865b..aa855f23db04 100644 --- a/datarmnet_dlkm_vendor_board.mk +++ b/datarmnet_dlkm_vendor_board.mk @@ -3,6 +3,7 @@ DATA_DLKM_BOARD_PLATFORMS_LIST := lahaina ifneq ($(TARGET_BOARD_AUTO),true) ifeq ($(call is-board-platform-in-list,$(DATA_DLKM_BOARD_PLATFORMS_LIST)),true) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/rmnet_core.ko +BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/rmnet_ctl.ko endif endif diff --git a/datarmnet_dlkm_vendor_product.mk b/datarmnet_dlkm_vendor_product.mk index fe147f060629..33343754c1e6 100644 --- a/datarmnet_dlkm_vendor_product.mk +++ b/datarmnet_dlkm_vendor_product.mk @@ -1 +1,2 @@ PRODUCT_PACKAGES += rmnet_core.ko +PRODUCT_PACKAGES += rmnet_ctl.ko