فهرست منبع

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))
 $(warning $(DLKM_DIR))
 include $(DLKM_DIR)/AndroidKernelModule.mk
 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 target
 endif #End of Check for qssi target
 endif #End of Check for qssi target

+ 2 - 0
core/Kbuild

@@ -1,6 +1,8 @@
 obj-m += rmnet_core.o
 obj-m += rmnet_core.o
+obj-m += rmnet_ctl.o
 rmnet_core-y := rmnet_config.o rmnet_handlers.o rmnet_descriptor.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\
 	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
 	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)
 	  for handling data in the multiplexing and aggregation protocol (MAP)
 	  format in the embedded data path. RMNET devices can be attached to
 	  format in the embedded data path. RMNET devices can be attached to
 	  any IP mode physical device.
 	  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>
 #include <linux/skbuff.h>
 
 
+#define CONFIG_RMNET_CTL 1
+
 enum rmnet_ctl_log_lvl {
 enum rmnet_ctl_log_lvl {
 	RMNET_CTL_LOG_CRIT,
 	RMNET_CTL_LOG_CRIT,
 	RMNET_CTL_LOG_ERR,
 	RMNET_CTL_LOG_ERR,

+ 44 - 15
core/rmnet_ctl_client.c

@@ -26,6 +26,10 @@ struct rmnet_ctl_endpoint {
 	void *ipc_log;
 	void *ipc_log;
 };
 };
 
 
+#if defined(CONFIG_IPA_DEBUG) || defined(CONFIG_MHI_DEBUG)
+#define CONFIG_RMNET_CTL_DEBUG 1
+#endif
+
 #ifdef CONFIG_RMNET_CTL_DEBUG
 #ifdef CONFIG_RMNET_CTL_DEBUG
 static u8 ipc_log_lvl = RMNET_CTL_LOG_DEBUG;
 static u8 ipc_log_lvl = RMNET_CTL_LOG_DEBUG;
 #else
 #else
@@ -35,13 +39,13 @@ static u8 ipc_log_lvl = RMNET_CTL_LOG_ERR;
 static DEFINE_SPINLOCK(client_lock);
 static DEFINE_SPINLOCK(client_lock);
 static struct rmnet_ctl_endpoint ctl_ep;
 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))
 		if (!IS_ERR_OR_NULL(ctl_ep.dbgfs_dir))
 			ctl_ep.dbgfs_loglvl = debugfs_create_u8(
 			ctl_ep.dbgfs_loglvl = debugfs_create_u8(
 				RMNET_CTL_LOG_LVL, 0644, ctl_ep.dbgfs_dir,
 				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);
 				RMNET_CTL_LOG_PAGE, RMNET_CTL_LOG_NAME, 0);
 	} else {
 	} else {
 		debugfs_remove_recursive(ctl_ep.dbgfs_dir);
 		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)
 void rmnet_ctl_endpoint_post(const void *data, size_t len)
 {
 {
 	struct rmnet_ctl_client *client;
 	struct rmnet_ctl_client *client;
@@ -63,22 +76,38 @@ void rmnet_ctl_endpoint_post(const void *data, size_t len)
 	if (unlikely(!data || !len))
 	if (unlikely(!data || !len))
 		return;
 		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);
 			skb->protocol = htons(ETH_P_MAP);
 			client->hooks.ctl_dl_client_hook(skb);
 			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)
 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_post(const void *data, size_t len);
 void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev);
 void rmnet_ctl_endpoint_setdev(const struct rmnet_ctl_dev *dev);
+void rmnet_ctl_set_dbgfs(bool enable);
 
 
 #endif /* _RMNET_CTL_CLIENT_H_ */
 #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");
 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)
 ifneq ($(TARGET_BOARD_AUTO),true)
 ifeq ($(call is-board-platform-in-list,$(DATA_DLKM_BOARD_PLATFORMS_LIST)),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_core.ko
+BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/rmnet_ctl.ko
 endif
 endif
 endif
 endif
 
 

+ 1 - 0
datarmnet_dlkm_vendor_product.mk

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