Explorar o código

Merge "cnss2: Add support secured wlan HW disable mode" into wlan-platform.lnx.1.0

CNSS_WLAN Service %!s(int64=2) %!d(string=hai) anos
pai
achega
fc8e91f180
Modificáronse 8 ficheiros con 180 adicións e 20 borrados
  1. 4 0
      Android.mk
  2. 4 0
      Kbuild
  3. 5 0
      cnss2/Makefile
  4. 10 0
      cnss2/debug.c
  5. 133 20
      cnss2/main.c
  6. 5 0
      cnss2/main.h
  7. 18 0
      cnss2/pci.c
  8. 1 0
      inc/cnss2.h

+ 4 - 0
Android.mk

@@ -20,6 +20,8 @@ CNSS_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/*) \
 	$(wildcard $(LOCAL_PATH)/*/*) \
 
+KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
+
 # Module.symvers needs to be generated as a intermediate module so that
 # other modules which depend on WLAN platform modules can set local
 # dependencies to it.
@@ -41,6 +43,8 @@ include $(DLKM_DIR)/Build_external_kernelmodule.mk
 
 ################################ cnss2 ################################
 include $(CLEAR_VARS)
+LOCAL_REQUIRED_MODULES := sec-module-symvers
+LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
 LOCAL_SRC_FILES           := $(CNSS_SRC_FILES)
 LOCAL_MODULE              := cnss2.ko
 LOCAL_MODULE_KBUILD_NAME  := cnss2/cnss2.ko

+ 4 - 0
Kbuild

@@ -24,6 +24,10 @@ ifeq ($(CONFIG_CNSS_PLAT_IPC_QMI_SVC),m)
 KBUILD_CPPFLAGS += -DCONFIG_CNSS_PLAT_IPC_QMI_SVC
 endif
 
+ifeq ($(CONFIG_CNSS_HW_SECURE_DISABLE), y)
+KBUILD_CPPFLAGS += -DCONFIG_CNSS_HW_SECURE_DISABLE
+endif
+
 obj-$(CONFIG_CNSS2) += cnss2/
 obj-$(CONFIG_ICNSS2) += icnss2/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/

+ 5 - 0
cnss2/Makefile

@@ -7,6 +7,11 @@ else
 ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils
 endif
 
+ifeq ($(CONFIG_CNSS_HW_SECURE_DISABLE), y)
+ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/smcinvoke/
+ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/linux/
+endif
+
 obj-$(CONFIG_CNSS2) += cnss2.o
 
 cnss2-y := main.o

+ 10 - 0
cnss2/debug.c

@@ -139,6 +139,12 @@ static int cnss_stats_show_state(struct seq_file *s,
 		case CNSS_DRIVER_REGISTER:
 			seq_puts(s, "DRIVER REGISTERED");
 			continue;
+		case CNSS_WLAN_HW_DISABLED:
+			seq_puts(s, "WLAN HW DISABLED");
+			continue;
+		case CNSS_FS_READY:
+			seq_puts(s, "FS READY");
+			continue;
 		}
 
 		seq_printf(s, "UNKNOWN-%d", i);
@@ -234,6 +240,10 @@ static ssize_t cnss_dev_boot_debug_write(struct file *fp,
 		if (!sptr)
 			return -EINVAL;
 		ret = cnss_aop_send_msg(plat_priv, sptr);
+	} else if (sysfs_streq(cmd, "dev_check")) {
+		cnss_wlan_hw_disable_check(plat_priv);
+	} else if (sysfs_streq(cmd, "dev_enable")) {
+		cnss_wlan_hw_enable();
 	} else {
 		pci_priv = plat_priv->bus_priv;
 		if (!pci_priv)

+ 133 - 20
cnss2/main.c

@@ -33,6 +33,16 @@
 #include "genl.h"
 #include "reg.h"
 
+#ifdef CONFIG_CNSS_HW_SECURE_DISABLE
+#include "smcinvoke.h"
+#include "smcinvoke_object.h"
+#include "IClientEnv.h"
+
+#define HW_STATE_UID 0x108
+#define HW_OP_GET_STATE 1
+#define HW_WIFI_UID 0x508
+#endif
+
 #define CNSS_DUMP_FORMAT_VER		0x11
 #define CNSS_DUMP_FORMAT_VER_V2		0x22
 #define CNSS_DUMP_MAGIC_VER_V2		0x42445953
@@ -1936,6 +1946,9 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
 	} else if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
 		cnss_pr_dbg("Calibration in progress. Ignore new calibration req\n");
 		goto out;
+	} else if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) {
+		cnss_pr_dbg("Calibration deferred as WLAN device disabled\n");
+		goto out;
 	}
 
 	if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
@@ -3444,6 +3457,7 @@ static ssize_t fs_ready_store(struct device *dev,
 		return count;
 	}
 
+	set_bit(CNSS_FS_READY, &plat_priv->driver_state);
 	if (fs_ready == FILE_SYSTEM_READY && plat_priv->cbc_enabled) {
 		cnss_driver_event_post(plat_priv,
 				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
@@ -3643,6 +3657,62 @@ static int cnss_reboot_notifier(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+#ifdef CONFIG_CNSS_HW_SECURE_DISABLE
+int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv)
+{
+	struct Object client_env;
+	struct Object app_object;
+	u32 wifi_uid = HW_WIFI_UID;
+	union ObjectArg obj_arg[2] = {{{0, 0}}};
+	int ret;
+	u8 state = 0;
+
+	/* get rootObj */
+	ret = get_client_env_object(&client_env);
+	if (ret) {
+		cnss_pr_dbg("Failed to get client_env_object, ret: %d\n", ret);
+		goto end;
+	}
+	ret = IClientEnv_open(client_env, HW_STATE_UID, &app_object);
+	if (ret) {
+		cnss_pr_dbg("Failed to get app_object, ret: %d\n",  ret);
+		goto exit_release_clientenv;
+	}
+
+	obj_arg[0].b = (struct ObjectBuf) {&wifi_uid, sizeof(u32)};
+	obj_arg[1].b = (struct ObjectBuf) {&state, sizeof(u8)};
+	ret = Object_invoke(app_object, HW_OP_GET_STATE, obj_arg,
+			    ObjectCounts_pack(1, 1, 0, 0));
+
+	cnss_pr_dbg("SMC invoke ret: %d state: %d\n", ret, state);
+	if (ret)
+		goto exit_release_app_obj;
+
+	if (state == 1)
+		set_bit(CNSS_WLAN_HW_DISABLED,
+			&plat_priv->driver_state);
+	else
+		clear_bit(CNSS_WLAN_HW_DISABLED,
+			  &plat_priv->driver_state);
+
+exit_release_app_obj:
+	Object_release(app_object);
+exit_release_clientenv:
+	Object_release(client_env);
+end:
+	if (ret) {
+		cnss_pr_err("Unable to get HW disable status\n");
+		CNSS_ASSERT(0);
+	}
+	return ret;
+}
+#else
+int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+#endif
+
 static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 {
 	int ret;
@@ -3874,13 +3944,67 @@ cnss_is_converged_dt(struct cnss_plat_data *plat_priv)
 				     "qcom,converged-dt");
 }
 
+static int cnss_wlan_device_init(struct cnss_plat_data *plat_priv)
+{
+	int ret = 0;
+	int retry = 0;
+
+	if (test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks))
+		return 0;
+
+retry:
+	ret = cnss_power_on_device(plat_priv);
+	if (ret)
+		goto end;
+
+	ret = cnss_bus_init(plat_priv);
+	if (ret) {
+		if ((ret != -EPROBE_DEFER) &&
+		    retry++ < POWER_ON_RETRY_MAX_TIMES) {
+			cnss_power_off_device(plat_priv);
+			cnss_pr_dbg("Retry cnss_bus_init #%d\n", retry);
+			msleep(POWER_ON_RETRY_DELAY_MS * retry);
+			goto retry;
+		}
+		goto power_off;
+	}
+power_off:
+	cnss_power_off_device(plat_priv);
+end:
+	return ret;
+}
+
+int cnss_wlan_hw_enable(void)
+{
+	struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
+	int ret = 0;
+
+	clear_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state);
+
+	ret = cnss_wlan_device_init(plat_priv);
+	if (ret) {
+		CNSS_ASSERT(0);
+		return ret;
+	}
+
+	if (test_bit(CNSS_FS_READY, &plat_priv->driver_state))
+		cnss_driver_event_post(plat_priv,
+				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
+				       0, NULL);
+
+	if (plat_priv->driver_ops)
+		ret = cnss_wlan_register_driver(plat_priv->driver_ops);
+
+	return ret;
+}
+EXPORT_SYMBOL(cnss_wlan_hw_enable);
+
 static int cnss_probe(struct platform_device *plat_dev)
 {
 	int ret = 0;
 	struct cnss_plat_data *plat_priv;
 	const struct of_device_id *of_id;
 	const struct platform_device_id *device_id;
-	int retry = 0;
 
 	if (cnss_get_plat_priv(plat_dev)) {
 		cnss_pr_err("Driver is already initialized!\n");
@@ -3968,28 +4092,20 @@ static int cnss_probe(struct platform_device *plat_dev)
 	if (ret)
 		goto destroy_debugfs;
 
+	ret = cnss_wlan_hw_disable_check(plat_priv);
+	if (ret)
+		goto deinit_misc;
+
 	/* Make sure all platform related init are done before
 	 * device power on and bus init.
 	 */
-	if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) {
-retry:
-		ret = cnss_power_on_device(plat_priv);
+	if (!test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) {
+		ret = cnss_wlan_device_init(plat_priv);
 		if (ret)
 			goto deinit_misc;
-
-		ret = cnss_bus_init(plat_priv);
-		if (ret) {
-			if ((ret != -EPROBE_DEFER) &&
-			    retry++ < POWER_ON_RETRY_MAX_TIMES) {
-				cnss_power_off_device(plat_priv);
-				cnss_pr_dbg("Retry cnss_bus_init #%d\n", retry);
-				msleep(POWER_ON_RETRY_DELAY_MS * retry);
-				goto retry;
-			}
-			goto power_off;
-		}
+	} else {
+		cnss_pr_info("WLAN HW Disabled. Defer PCI enumeration\n");
 	}
-
 	cnss_register_coex_service(plat_priv);
 	cnss_register_ims_service(plat_priv);
 
@@ -4001,9 +4117,6 @@ retry:
 
 	return 0;
 
-power_off:
-	if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks))
-		cnss_power_off_device(plat_priv);
 deinit_misc:
 	cnss_misc_deinit(plat_priv);
 destroy_debugfs:

+ 5 - 0
cnss2/main.h

@@ -318,6 +318,8 @@ enum cnss_driver_state {
 	CNSS_DAEMON_CONNECTED,
 	CNSS_PCI_PROBE_DONE,
 	CNSS_DRIVER_REGISTER,
+	CNSS_WLAN_HW_DISABLED,
+	CNSS_FS_READY = 25,
 };
 
 struct cnss_recovery_data {
@@ -502,6 +504,7 @@ struct cnss_plat_data {
 	struct completion cal_complete;
 	struct mutex dev_lock; /* mutex for register access through debugfs */
 	struct mutex driver_ops_lock; /* mutex for external driver ops */
+	struct cnss_wlan_driver *driver_ops;
 	u32 device_freq_hz;
 	u32 diag_reg_read_addr;
 	u32 diag_reg_read_mem_type;
@@ -570,6 +573,8 @@ static inline u64 cnss_get_host_timestamp(struct cnss_plat_data *plat_priv)
 }
 #endif
 
+int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv);
+int cnss_wlan_hw_enable(void);
 struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
 void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv);
 void cnss_pm_relax(struct cnss_plat_data *plat_priv);

+ 18 - 0
cnss2/pci.c

@@ -2937,6 +2937,24 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
 		return -EAGAIN;
 	}
 
+	if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) {
+		while (id_table && id_table->device) {
+			if (plat_priv->device_id == id_table->device) {
+				if (plat_priv->device_id == KIWI_DEVICE_ID &&
+				    driver_ops->chip_version != 2) {
+					cnss_pr_err("WLAN HW disabled. kiwi_v2 only supported\n");
+					return -ENODEV;
+				}
+				cnss_pr_info("WLAN register driver deferred for device ID: 0x%x due to HW disable\n",
+					     id_table->device);
+				plat_priv->driver_ops = driver_ops;
+				return 0;
+			}
+			id_table++;
+		}
+		return -ENODEV;
+	}
+
 	if (!test_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state)) {
 		cnss_pr_info("pci probe not yet done for register driver\n");
 		return -EAGAIN;

+ 1 - 0
inc/cnss2.h

@@ -270,6 +270,7 @@ extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
 extern int cnss_get_msi_irq(struct device *dev, unsigned int vector);
 extern void cnss_get_msi_address(struct device *dev, uint32_t *msi_addr_low,
 				 uint32_t *msi_addr_high);
+extern int cnss_wlan_hw_enable(void);
 extern int cnss_wlan_enable(struct device *dev,
 			    struct cnss_wlan_enable_cfg *config,
 			    enum cnss_driver_mode mode,