소스 검색

rmnet_ctl: Support IPA EP

Support QMAP commands from dedicated IPA EP.

Change-Id: Ic5e489d2b33223b2af2fb471d20611bc5a0d7d58
Acked-by: Weiyi Chen <[email protected]>
Signed-off-by: Subash Abhinov Kasiviswanathan <[email protected]>
Subash Abhinov Kasiviswanathan 5 년 전
부모
커밋
5a88e58652
10개의 변경된 파일211개의 추가작업 그리고 18개의 파일을 삭제
  1. 21 0
      core/Android.mk
  2. 2 0
      core/Kbuild
  3. 6 0
      core/Kconfig
  4. 2 0
      core/rmnet_ctl.h
  5. 44 15
      core/rmnet_ctl_client.c
  6. 1 0
      core/rmnet_ctl_client.h
  7. 114 0
      core/rmnet_ctl_ipa.c
  8. 19 3
      core/rmnet_ctl_mhi.c
  9. 1 0
      datarmnet_dlkm_vendor_board.mk
  10. 1 0
      datarmnet_dlkm_vendor_product.mk

+ 21 - 0
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

+ 2 - 0
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
 
 

+ 6 - 0
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.

+ 2 - 0
core/rmnet_ctl.h

@@ -10,6 +10,8 @@
 
 #include <linux/skbuff.h>
 
+#define CONFIG_RMNET_CTL 1
+
 enum rmnet_ctl_log_lvl {
 	RMNET_CTL_LOG_CRIT,
 	RMNET_CTL_LOG_ERR,

+ 44 - 15
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();
-
-	client = rcu_dereference(ctl_ep.client);
+		rcu_read_lock();
 
-	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)

+ 1 - 0
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_ */

+ 114 - 0
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 <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipa.h>
+#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");

+ 19 - 3
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;
+
+	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 Driver");
+MODULE_DESCRIPTION("RmNet Control MHI Driver");
 MODULE_LICENSE("GPL v2");

+ 1 - 0
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
 

+ 1 - 0
datarmnet_dlkm_vendor_product.mk

@@ -1 +1,2 @@
 PRODUCT_PACKAGES += rmnet_core.ko
+PRODUCT_PACKAGES += rmnet_ctl.ko