cnss2: Add support secured wlan HW disable mode
WLAN HW can be securely disabled. Add support in platform driver to handle WLAN cold boot initialization sequence changes if HW is disabled at boot and WLAN resume sequence after WLAN HW is enabled. Change-Id: If5036560820c54653801298ceebe4f50b7532f3f CRs-fixed: 3211229
This commit is contained in:
@@ -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
Kbuild
4
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/
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
153
cnss2/main.c
153
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:
|
||||
|
@@ -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
cnss2/pci.c
18
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;
|
||||
|
@@ -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,
|
||||
|
Fai riferimento in un nuovo problema
Block a user