Loading drivers/net/wireless/cnss2/debug.c +139 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -504,6 +504,142 @@ static const struct file_operations cnss_runtime_pm_debug_fops = { .llseek = seq_lseek, }; static ssize_t cnss_control_params_debug_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) { struct cnss_plat_data *plat_priv = ((struct seq_file *)fp->private_data)->private; char buf[64]; char *sptr, *token; char *cmd; u32 val; unsigned int len = 0; const char *delim = " "; if (!plat_priv) return -ENODEV; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; sptr = buf; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (!sptr) return -EINVAL; cmd = token; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (kstrtou32(token, 0, &val)) return -EINVAL; if (strcmp(cmd, "quirks") == 0) plat_priv->ctrl_params.quirks = val; else if (strcmp(cmd, "mhi_timeout") == 0) plat_priv->ctrl_params.mhi_timeout = val; else if (strcmp(cmd, "qmi_timeout") == 0) plat_priv->ctrl_params.qmi_timeout = val; else if (strcmp(cmd, "bdf_type") == 0) plat_priv->ctrl_params.bdf_type = val; else return -EINVAL; return count; } static int cnss_show_quirks_state(struct seq_file *s, struct cnss_plat_data *plat_priv) { enum cnss_debug_quirks i; int skip = 0; unsigned long state; seq_printf(s, "quirks: 0x%lx (", plat_priv->ctrl_params.quirks); for (i = 0, state = plat_priv->ctrl_params.quirks; state != 0; state >>= 1, i++) { if (!(state & 0x1)) continue; if (skip++) seq_puts(s, " | "); switch (i) { case LINK_DOWN_SELF_RECOVERY: seq_puts(s, "LINK_DOWN_SELF_RECOVERY"); continue; case SKIP_DEVICE_BOOT: seq_puts(s, "SKIP_DEVICE_BOOT"); continue; case USE_CORE_ONLY_FW: seq_puts(s, "USE_CORE_ONLY_FW"); continue; case SKIP_RECOVERY: seq_puts(s, "SKIP_RECOVERY"); continue; case QMI_BYPASS: seq_puts(s, "QMI_BYPASS"); continue; case ENABLE_WALTEST: seq_puts(s, "WALTEST"); continue; case ENABLE_PCI_LINK_DOWN_PANIC: seq_puts(s, "PCI_LINK_DOWN_PANIC"); continue; case FBC_BYPASS: seq_puts(s, "FBC_BYPASS"); continue; case ENABLE_DAEMON_SUPPORT: seq_puts(s, "DAEMON_SUPPORT"); continue; } seq_printf(s, "UNKNOWN-%d", i); } seq_puts(s, ")\n"); return 0; } static int cnss_control_params_debug_show(struct seq_file *s, void *data) { struct cnss_plat_data *cnss_priv = s->private; seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n"); seq_puts(s, "<params_name> can be one of below:\n"); seq_puts(s, "quirks: Debug quirks for driver\n"); seq_puts(s, "mhi_timeout: Timeout for MHI operation in milliseconds\n"); seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n"); seq_puts(s, "bdf_type: Type of board data file to be downloaded\n"); seq_puts(s, "\nCurrent value:\n"); cnss_show_quirks_state(s, cnss_priv); seq_printf(s, "mhi_timeout: %u\n", cnss_priv->ctrl_params.mhi_timeout); seq_printf(s, "qmi_timeout: %u\n", cnss_priv->ctrl_params.qmi_timeout); seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type); return 0; } static int cnss_control_params_debug_open(struct inode *inode, struct file *file) { return single_open(file, cnss_control_params_debug_show, inode->i_private); } static const struct file_operations cnss_control_params_debug_fops = { .read = seq_read, .write = cnss_control_params_debug_write, .open = cnss_control_params_debug_open, .owner = THIS_MODULE, .llseek = seq_lseek, }; #ifdef CONFIG_CNSS2_DEBUG static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) { Loading @@ -517,6 +653,8 @@ static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) &cnss_reg_write_debug_fops); debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv, &cnss_runtime_pm_debug_fops); debugfs_create_file("control_params", 0600, root_dentry, plat_priv, &cnss_control_params_debug_fops); return 0; } Loading drivers/net/wireless/cnss2/main.c +38 −39 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -38,27 +38,18 @@ #define FW_ASSERT_TIMEOUT 5000 #define CNSS_EVENT_PENDING 2989 static struct cnss_plat_data *plat_env; static DECLARE_RWSEM(cnss_pm_sem); static bool qmi_bypass; #ifdef CONFIG_CNSS2_DEBUG module_param(qmi_bypass, bool, 0600); MODULE_PARM_DESC(qmi_bypass, "Bypass QMI from platform driver"); #define CNSS_QUIRKS_DEFAULT BIT(ENABLE_DAEMON_SUPPORT) #ifdef CONFIG_CNSS_EMULATION #define CNSS_MHI_TIMEOUT_DEFAULT 90000 #else #define CNSS_MHI_TIMEOUT_DEFAULT 0 #endif #define CNSS_QMI_TIMEOUT_DEFAULT 10000 #define CNSS_BDF_TYPE_DEFAULT CNSS_BDF_ELF static bool enable_waltest; #ifdef CONFIG_CNSS2_DEBUG module_param(enable_waltest, bool, 0600); MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest"); #endif static struct cnss_plat_data *plat_env; unsigned long quirks; #ifdef CONFIG_CNSS2_DEBUG module_param(quirks, ulong, 0600); MODULE_PARM_DESC(quirks, "Debug quirks for the driver"); #endif static DECLARE_RWSEM(cnss_pm_sem); static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = { "qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin", Loading Loading @@ -253,7 +244,7 @@ int cnss_wlan_enable(struct device *dev, if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (qmi_bypass) if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; if (!config || !host_version) { Loading Loading @@ -285,7 +276,7 @@ int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode) if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (qmi_bypass) if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; return cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF); Loading Loading @@ -377,16 +368,6 @@ int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode) } EXPORT_SYMBOL(cnss_set_fw_log_mode); bool *cnss_get_qmi_bypass(void) { return &qmi_bypass; } unsigned long *cnss_get_debug_quirks(void) { return &quirks; } static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; Loading Loading @@ -433,7 +414,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } if (enable_waltest) { if (test_bit(ENABLE_WALTEST, &plat_priv->ctrl_params.quirks)) { ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_WALTEST); } else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) { Loading Loading @@ -571,7 +552,14 @@ int cnss_driver_event_post(struct cnss_plat_data *plat_priv, unsigned int cnss_get_boot_timeout(struct device *dev) { return cnss_get_qmi_timeout(); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); if (!plat_priv) { cnss_pr_err("plat_priv is NULL\n"); return 0; } return cnss_get_qmi_timeout(plat_priv); } EXPORT_SYMBOL(cnss_get_boot_timeout); Loading Loading @@ -890,14 +878,15 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv, if (plat_priv->device_id == QCA6174_DEVICE_ID) goto self_recovery; if (test_bit(SKIP_RECOVERY, &quirks)) { if (test_bit(SKIP_RECOVERY, &plat_priv->ctrl_params.quirks)) { cnss_pr_dbg("Skip device recovery\n"); return 0; } switch (reason) { case CNSS_REASON_LINK_DOWN: if (test_bit(LINK_DOWN_SELF_RECOVERY, &quirks)) if (test_bit(LINK_DOWN_SELF_RECOVERY, &plat_priv->ctrl_params.quirks)) goto self_recovery; break; case CNSS_REASON_RDDM: Loading Loading @@ -1513,7 +1502,7 @@ static ssize_t cnss_fs_ready_store(struct device *dev, cnss_pr_dbg("File system is ready, fs_ready is %d, count is %zu\n", fs_ready, count); if (qmi_bypass) { if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) { cnss_pr_dbg("QMI is bypassed.\n"); return count; } Loading Loading @@ -1617,6 +1606,14 @@ static void cnss_misc_deinit(struct cnss_plat_data *plat_priv) del_timer(&plat_priv->fw_boot_timer); } static void cnss_init_control_params(struct cnss_plat_data *plat_priv) { plat_priv->ctrl_params.quirks = CNSS_QUIRKS_DEFAULT; plat_priv->ctrl_params.mhi_timeout = CNSS_MHI_TIMEOUT_DEFAULT; plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT; plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT; } static const struct platform_device_id cnss_platform_id_table[] = { { .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, }, { .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, }, Loading Loading @@ -1672,11 +1669,13 @@ static int cnss_probe(struct platform_device *plat_dev) cnss_set_plat_priv(plat_dev, plat_priv); platform_set_drvdata(plat_dev, plat_priv); cnss_init_control_params(plat_priv); ret = cnss_get_resources(plat_priv); if (ret) goto reset_ctx; if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) { if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) { ret = cnss_power_on_device(plat_priv); if (ret) goto free_res; Loading Loading @@ -1731,10 +1730,10 @@ static int cnss_probe(struct platform_device *plat_dev) unreg_esoc: cnss_unregister_esoc(plat_priv); deinit_bus: if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) cnss_bus_deinit(plat_priv); power_off: if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) cnss_power_off_device(plat_priv); free_res: cnss_put_resources(plat_priv); Loading drivers/net/wireless/cnss2/main.h +20 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -205,6 +205,24 @@ enum cnss_debug_quirks { SKIP_DEVICE_BOOT, USE_CORE_ONLY_FW, SKIP_RECOVERY, QMI_BYPASS, ENABLE_WALTEST, ENABLE_PCI_LINK_DOWN_PANIC, FBC_BYPASS, ENABLE_DAEMON_SUPPORT, }; enum cnss_bdf_type { CNSS_BDF_BIN, CNSS_BDF_ELF, CNSS_BDF_DUMMY = 255, }; struct cnss_control_params { unsigned long quirks; unsigned int mhi_timeout; unsigned int qmi_timeout; unsigned int bdf_type; }; struct cnss_plat_data { Loading Loading @@ -252,11 +270,10 @@ struct cnss_plat_data { bool powered_on; char firmware_name[13]; struct completion rddm_complete; struct cnss_control_params ctrl_params; }; struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev); bool *cnss_get_qmi_bypass(void); unsigned long *cnss_get_debug_quirks(void); int cnss_driver_event_post(struct cnss_plat_data *plat_priv, enum cnss_driver_event_type type, u32 flags, void *data); Loading drivers/net/wireless/cnss2/pci.c +16 −34 Original line number Diff line number Diff line Loading @@ -59,32 +59,7 @@ static DEFINE_SPINLOCK(pci_link_down_lock); static unsigned int pci_link_down_panic; module_param(pci_link_down_panic, uint, 0600); MODULE_PARM_DESC(pci_link_down_panic, "Trigger kernel panic when PCI link down is detected"); static bool fbc_bypass; #ifdef CONFIG_CNSS2_DEBUG module_param(fbc_bypass, bool, 0600); MODULE_PARM_DESC(fbc_bypass, "Bypass firmware download when loading WLAN driver"); #endif #ifdef CONFIG_CNSS2_DEBUG #ifdef CONFIG_CNSS_EMULATION static unsigned int mhi_timeout = 90000; #else static unsigned int mhi_timeout; #endif module_param(mhi_timeout, uint, 0600); MODULE_PARM_DESC(mhi_timeout, "Timeout for MHI operation in milliseconds"); #define MHI_TIMEOUT_OVERWRITE_MS mhi_timeout #else #define MHI_TIMEOUT_OVERWRITE_MS 0 #endif #define MHI_TIMEOUT_OVERWRITE_MS (plat_priv->ctrl_params.mhi_timeout) static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save) { Loading Loading @@ -227,13 +202,16 @@ int cnss_pci_link_down(struct device *dev) unsigned long flags; struct pci_dev *pci_dev = to_pci_dev(dev); struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); struct cnss_plat_data *plat_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return -EINVAL; } if (pci_link_down_panic) plat_priv = pci_priv->plat_priv; if (test_bit(ENABLE_PCI_LINK_DOWN_PANIC, &plat_priv->ctrl_params.quirks)) panic("cnss: PCI link is down!\n"); spin_lock_irqsave(&pci_link_down_lock, flags); Loading Loading @@ -510,7 +488,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv) return 0; } if (test_bit(USE_CORE_ONLY_FW, cnss_get_debug_quirks())) { if (test_bit(USE_CORE_ONLY_FW, &plat_priv->ctrl_params.quirks)) { clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state); clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); return 0; Loading @@ -518,7 +496,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv) cnss_set_pin_connect_status(plat_priv); if (*cnss_get_qmi_bypass()) { if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) { ret = cnss_pci_call_driver_probe(pci_priv); if (ret) goto stop_mhi; Loading Loading @@ -919,6 +897,7 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) unsigned long flags; struct pci_dev *pci_dev; struct cnss_pci_data *pci_priv; struct cnss_plat_data *plat_priv; if (!notify) return; Loading @@ -931,9 +910,11 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) if (!pci_priv) return; plat_priv = pci_priv->plat_priv; switch (notify->event) { case MSM_PCIE_EVENT_LINKDOWN: if (pci_link_down_panic) if (test_bit(ENABLE_PCI_LINK_DOWN_PANIC, &plat_priv->ctrl_params.quirks)) panic("cnss: PCI link is down!\n"); spin_lock_irqsave(&pci_link_down_lock, flags); Loading Loading @@ -2346,13 +2327,15 @@ int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv) { int ret = 0; struct cnss_plat_data *plat_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return -ENODEV; } if (fbc_bypass) plat_priv = pci_priv->plat_priv; if (test_bit(FBC_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; if (MHI_TIMEOUT_OVERWRITE_MS) Loading Loading @@ -2381,10 +2364,9 @@ void cnss_pci_stop_mhi(struct cnss_pci_data *pci_priv) return; } if (fbc_bypass) return; plat_priv = pci_priv->plat_priv; if (test_bit(FBC_BYPASS, &plat_priv->ctrl_params.quirks)) return; cnss_pci_set_mhi_state_bit(pci_priv, CNSS_MHI_RESUME); if (!pci_priv->pci_link_down_ind) Loading drivers/net/wireless/cnss2/qmi.c +24 −35 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -21,42 +21,18 @@ #define WLFW_SERVICE_INS_ID_V01 1 #define WLFW_CLIENT_ID 0x4b4e454c #define MAX_BDF_FILE_NAME 11 #define MAX_BDF_FILE_NAME 13 #define ELF_BDF_FILE_NAME "bdwlan.elf" #define ELF_BDF_FILE_NAME_PREFIX "bdwlan.e" #define BIN_BDF_FILE_NAME "bdwlan.bin" #define BIN_BDF_FILE_NAME_PREFIX "bdwlan.b" #define DUMMY_BDF_FILE_NAME "bdwlan.dmy" enum cnss_bdf_type { CNSS_BDF_BIN, CNSS_BDF_ELF, CNSS_BDF_DUMMY = 255, }; #ifdef CONFIG_CNSS2_DEBUG static unsigned int qmi_timeout = 10000; module_param(qmi_timeout, uint, 0600); MODULE_PARM_DESC(qmi_timeout, "Timeout for QMI message in milliseconds"); #define QMI_WLFW_TIMEOUT_MS qmi_timeout #else #define QMI_WLFW_TIMEOUT_MS 10000 #endif #define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout) #define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS) #define QMI_WLFW_MAX_RECV_BUF_SIZE SZ_8K static bool daemon_support = true; module_param(daemon_support, bool, 0600); MODULE_PARM_DESC(daemon_support, "User space has cnss-daemon support or not"); static unsigned int bdf_type = CNSS_BDF_ELF; #ifdef CONFIG_CNSS2_DEBUG module_param(bdf_type, uint, 0600); MODULE_PARM_DESC(bdf_type, "Type of board data file to be downloaded"); #endif static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode) { switch (mode) { Loading Loading @@ -181,7 +157,11 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) } req->num_clients_valid = 1; req->num_clients = daemon_support ? 2 : 1; if (test_bit(ENABLE_DAEMON_SUPPORT, &plat_priv->ctrl_params.quirks)) req->num_clients = 2; else req->num_clients = 1; cnss_pr_dbg("Number of clients is %d\n", req->num_clients); req->wake_msi = cnss_bus_get_wake_irq(plat_priv); Loading Loading @@ -449,22 +429,30 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) return -ENOMEM; } switch (bdf_type) { switch (plat_priv->ctrl_params.bdf_type) { case CNSS_BDF_ELF: if (plat_priv->board_info.board_id == 0xFF) snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME); else else if (plat_priv->board_info.board_id < 0xFF) snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME_PREFIX "%02x", plat_priv->board_info.board_id); else snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME_PREFIX "%04x", plat_priv->board_info.board_id); break; case CNSS_BDF_BIN: if (plat_priv->board_info.board_id == 0xFF) snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME); else else if (plat_priv->board_info.board_id < 0xFF) snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME_PREFIX "%02x", plat_priv->board_info.board_id); else snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME_PREFIX "%04x", plat_priv->board_info.board_id); break; case CNSS_BDF_DUMMY: cnss_pr_dbg("CNSS_BDF_DUMMY is set, sending dummy BDF\n"); Loading @@ -473,7 +461,8 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) remaining = MAX_BDF_FILE_NAME; goto bypass_bdf; default: cnss_pr_err("Invalid BDF type: %d\n", bdf_type); cnss_pr_err("Invalid BDF type: %d\n", plat_priv->ctrl_params.bdf_type); ret = -EINVAL; goto err_req_fw; } Loading @@ -500,7 +489,7 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) req->data_valid = 1; req->end_valid = 1; req->bdf_type_valid = 1; req->bdf_type = bdf_type; req->bdf_type = plat_priv->ctrl_params.bdf_type; if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; Loading Loading @@ -555,7 +544,7 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) return 0; err_send: if (bdf_type != CNSS_BDF_DUMMY) if (plat_priv->ctrl_params.bdf_type != CNSS_BDF_DUMMY) release_firmware(fw_entry); err_req_fw: CNSS_ASSERT(0); Loading Loading @@ -1070,7 +1059,7 @@ int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv, return ret; } unsigned int cnss_get_qmi_timeout(void) unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv) { cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS); Loading Loading
drivers/net/wireless/cnss2/debug.c +139 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -504,6 +504,142 @@ static const struct file_operations cnss_runtime_pm_debug_fops = { .llseek = seq_lseek, }; static ssize_t cnss_control_params_debug_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) { struct cnss_plat_data *plat_priv = ((struct seq_file *)fp->private_data)->private; char buf[64]; char *sptr, *token; char *cmd; u32 val; unsigned int len = 0; const char *delim = " "; if (!plat_priv) return -ENODEV; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; sptr = buf; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (!sptr) return -EINVAL; cmd = token; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (kstrtou32(token, 0, &val)) return -EINVAL; if (strcmp(cmd, "quirks") == 0) plat_priv->ctrl_params.quirks = val; else if (strcmp(cmd, "mhi_timeout") == 0) plat_priv->ctrl_params.mhi_timeout = val; else if (strcmp(cmd, "qmi_timeout") == 0) plat_priv->ctrl_params.qmi_timeout = val; else if (strcmp(cmd, "bdf_type") == 0) plat_priv->ctrl_params.bdf_type = val; else return -EINVAL; return count; } static int cnss_show_quirks_state(struct seq_file *s, struct cnss_plat_data *plat_priv) { enum cnss_debug_quirks i; int skip = 0; unsigned long state; seq_printf(s, "quirks: 0x%lx (", plat_priv->ctrl_params.quirks); for (i = 0, state = plat_priv->ctrl_params.quirks; state != 0; state >>= 1, i++) { if (!(state & 0x1)) continue; if (skip++) seq_puts(s, " | "); switch (i) { case LINK_DOWN_SELF_RECOVERY: seq_puts(s, "LINK_DOWN_SELF_RECOVERY"); continue; case SKIP_DEVICE_BOOT: seq_puts(s, "SKIP_DEVICE_BOOT"); continue; case USE_CORE_ONLY_FW: seq_puts(s, "USE_CORE_ONLY_FW"); continue; case SKIP_RECOVERY: seq_puts(s, "SKIP_RECOVERY"); continue; case QMI_BYPASS: seq_puts(s, "QMI_BYPASS"); continue; case ENABLE_WALTEST: seq_puts(s, "WALTEST"); continue; case ENABLE_PCI_LINK_DOWN_PANIC: seq_puts(s, "PCI_LINK_DOWN_PANIC"); continue; case FBC_BYPASS: seq_puts(s, "FBC_BYPASS"); continue; case ENABLE_DAEMON_SUPPORT: seq_puts(s, "DAEMON_SUPPORT"); continue; } seq_printf(s, "UNKNOWN-%d", i); } seq_puts(s, ")\n"); return 0; } static int cnss_control_params_debug_show(struct seq_file *s, void *data) { struct cnss_plat_data *cnss_priv = s->private; seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n"); seq_puts(s, "<params_name> can be one of below:\n"); seq_puts(s, "quirks: Debug quirks for driver\n"); seq_puts(s, "mhi_timeout: Timeout for MHI operation in milliseconds\n"); seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n"); seq_puts(s, "bdf_type: Type of board data file to be downloaded\n"); seq_puts(s, "\nCurrent value:\n"); cnss_show_quirks_state(s, cnss_priv); seq_printf(s, "mhi_timeout: %u\n", cnss_priv->ctrl_params.mhi_timeout); seq_printf(s, "qmi_timeout: %u\n", cnss_priv->ctrl_params.qmi_timeout); seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type); return 0; } static int cnss_control_params_debug_open(struct inode *inode, struct file *file) { return single_open(file, cnss_control_params_debug_show, inode->i_private); } static const struct file_operations cnss_control_params_debug_fops = { .read = seq_read, .write = cnss_control_params_debug_write, .open = cnss_control_params_debug_open, .owner = THIS_MODULE, .llseek = seq_lseek, }; #ifdef CONFIG_CNSS2_DEBUG static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) { Loading @@ -517,6 +653,8 @@ static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) &cnss_reg_write_debug_fops); debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv, &cnss_runtime_pm_debug_fops); debugfs_create_file("control_params", 0600, root_dentry, plat_priv, &cnss_control_params_debug_fops); return 0; } Loading
drivers/net/wireless/cnss2/main.c +38 −39 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -38,27 +38,18 @@ #define FW_ASSERT_TIMEOUT 5000 #define CNSS_EVENT_PENDING 2989 static struct cnss_plat_data *plat_env; static DECLARE_RWSEM(cnss_pm_sem); static bool qmi_bypass; #ifdef CONFIG_CNSS2_DEBUG module_param(qmi_bypass, bool, 0600); MODULE_PARM_DESC(qmi_bypass, "Bypass QMI from platform driver"); #define CNSS_QUIRKS_DEFAULT BIT(ENABLE_DAEMON_SUPPORT) #ifdef CONFIG_CNSS_EMULATION #define CNSS_MHI_TIMEOUT_DEFAULT 90000 #else #define CNSS_MHI_TIMEOUT_DEFAULT 0 #endif #define CNSS_QMI_TIMEOUT_DEFAULT 10000 #define CNSS_BDF_TYPE_DEFAULT CNSS_BDF_ELF static bool enable_waltest; #ifdef CONFIG_CNSS2_DEBUG module_param(enable_waltest, bool, 0600); MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest"); #endif static struct cnss_plat_data *plat_env; unsigned long quirks; #ifdef CONFIG_CNSS2_DEBUG module_param(quirks, ulong, 0600); MODULE_PARM_DESC(quirks, "Debug quirks for the driver"); #endif static DECLARE_RWSEM(cnss_pm_sem); static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = { "qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin", Loading Loading @@ -253,7 +244,7 @@ int cnss_wlan_enable(struct device *dev, if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (qmi_bypass) if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; if (!config || !host_version) { Loading Loading @@ -285,7 +276,7 @@ int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode) if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (qmi_bypass) if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; return cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF); Loading Loading @@ -377,16 +368,6 @@ int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode) } EXPORT_SYMBOL(cnss_set_fw_log_mode); bool *cnss_get_qmi_bypass(void) { return &qmi_bypass; } unsigned long *cnss_get_debug_quirks(void) { return &quirks; } static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; Loading Loading @@ -433,7 +414,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } if (enable_waltest) { if (test_bit(ENABLE_WALTEST, &plat_priv->ctrl_params.quirks)) { ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_WALTEST); } else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) { Loading Loading @@ -571,7 +552,14 @@ int cnss_driver_event_post(struct cnss_plat_data *plat_priv, unsigned int cnss_get_boot_timeout(struct device *dev) { return cnss_get_qmi_timeout(); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); if (!plat_priv) { cnss_pr_err("plat_priv is NULL\n"); return 0; } return cnss_get_qmi_timeout(plat_priv); } EXPORT_SYMBOL(cnss_get_boot_timeout); Loading Loading @@ -890,14 +878,15 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv, if (plat_priv->device_id == QCA6174_DEVICE_ID) goto self_recovery; if (test_bit(SKIP_RECOVERY, &quirks)) { if (test_bit(SKIP_RECOVERY, &plat_priv->ctrl_params.quirks)) { cnss_pr_dbg("Skip device recovery\n"); return 0; } switch (reason) { case CNSS_REASON_LINK_DOWN: if (test_bit(LINK_DOWN_SELF_RECOVERY, &quirks)) if (test_bit(LINK_DOWN_SELF_RECOVERY, &plat_priv->ctrl_params.quirks)) goto self_recovery; break; case CNSS_REASON_RDDM: Loading Loading @@ -1513,7 +1502,7 @@ static ssize_t cnss_fs_ready_store(struct device *dev, cnss_pr_dbg("File system is ready, fs_ready is %d, count is %zu\n", fs_ready, count); if (qmi_bypass) { if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) { cnss_pr_dbg("QMI is bypassed.\n"); return count; } Loading Loading @@ -1617,6 +1606,14 @@ static void cnss_misc_deinit(struct cnss_plat_data *plat_priv) del_timer(&plat_priv->fw_boot_timer); } static void cnss_init_control_params(struct cnss_plat_data *plat_priv) { plat_priv->ctrl_params.quirks = CNSS_QUIRKS_DEFAULT; plat_priv->ctrl_params.mhi_timeout = CNSS_MHI_TIMEOUT_DEFAULT; plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT; plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT; } static const struct platform_device_id cnss_platform_id_table[] = { { .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, }, { .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, }, Loading Loading @@ -1672,11 +1669,13 @@ static int cnss_probe(struct platform_device *plat_dev) cnss_set_plat_priv(plat_dev, plat_priv); platform_set_drvdata(plat_dev, plat_priv); cnss_init_control_params(plat_priv); ret = cnss_get_resources(plat_priv); if (ret) goto reset_ctx; if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) { if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) { ret = cnss_power_on_device(plat_priv); if (ret) goto free_res; Loading Loading @@ -1731,10 +1730,10 @@ static int cnss_probe(struct platform_device *plat_dev) unreg_esoc: cnss_unregister_esoc(plat_priv); deinit_bus: if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) cnss_bus_deinit(plat_priv); power_off: if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) if (!test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks)) cnss_power_off_device(plat_priv); free_res: cnss_put_resources(plat_priv); Loading
drivers/net/wireless/cnss2/main.h +20 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -205,6 +205,24 @@ enum cnss_debug_quirks { SKIP_DEVICE_BOOT, USE_CORE_ONLY_FW, SKIP_RECOVERY, QMI_BYPASS, ENABLE_WALTEST, ENABLE_PCI_LINK_DOWN_PANIC, FBC_BYPASS, ENABLE_DAEMON_SUPPORT, }; enum cnss_bdf_type { CNSS_BDF_BIN, CNSS_BDF_ELF, CNSS_BDF_DUMMY = 255, }; struct cnss_control_params { unsigned long quirks; unsigned int mhi_timeout; unsigned int qmi_timeout; unsigned int bdf_type; }; struct cnss_plat_data { Loading Loading @@ -252,11 +270,10 @@ struct cnss_plat_data { bool powered_on; char firmware_name[13]; struct completion rddm_complete; struct cnss_control_params ctrl_params; }; struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev); bool *cnss_get_qmi_bypass(void); unsigned long *cnss_get_debug_quirks(void); int cnss_driver_event_post(struct cnss_plat_data *plat_priv, enum cnss_driver_event_type type, u32 flags, void *data); Loading
drivers/net/wireless/cnss2/pci.c +16 −34 Original line number Diff line number Diff line Loading @@ -59,32 +59,7 @@ static DEFINE_SPINLOCK(pci_link_down_lock); static unsigned int pci_link_down_panic; module_param(pci_link_down_panic, uint, 0600); MODULE_PARM_DESC(pci_link_down_panic, "Trigger kernel panic when PCI link down is detected"); static bool fbc_bypass; #ifdef CONFIG_CNSS2_DEBUG module_param(fbc_bypass, bool, 0600); MODULE_PARM_DESC(fbc_bypass, "Bypass firmware download when loading WLAN driver"); #endif #ifdef CONFIG_CNSS2_DEBUG #ifdef CONFIG_CNSS_EMULATION static unsigned int mhi_timeout = 90000; #else static unsigned int mhi_timeout; #endif module_param(mhi_timeout, uint, 0600); MODULE_PARM_DESC(mhi_timeout, "Timeout for MHI operation in milliseconds"); #define MHI_TIMEOUT_OVERWRITE_MS mhi_timeout #else #define MHI_TIMEOUT_OVERWRITE_MS 0 #endif #define MHI_TIMEOUT_OVERWRITE_MS (plat_priv->ctrl_params.mhi_timeout) static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save) { Loading Loading @@ -227,13 +202,16 @@ int cnss_pci_link_down(struct device *dev) unsigned long flags; struct pci_dev *pci_dev = to_pci_dev(dev); struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); struct cnss_plat_data *plat_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return -EINVAL; } if (pci_link_down_panic) plat_priv = pci_priv->plat_priv; if (test_bit(ENABLE_PCI_LINK_DOWN_PANIC, &plat_priv->ctrl_params.quirks)) panic("cnss: PCI link is down!\n"); spin_lock_irqsave(&pci_link_down_lock, flags); Loading Loading @@ -510,7 +488,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv) return 0; } if (test_bit(USE_CORE_ONLY_FW, cnss_get_debug_quirks())) { if (test_bit(USE_CORE_ONLY_FW, &plat_priv->ctrl_params.quirks)) { clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state); clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); return 0; Loading @@ -518,7 +496,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv) cnss_set_pin_connect_status(plat_priv); if (*cnss_get_qmi_bypass()) { if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) { ret = cnss_pci_call_driver_probe(pci_priv); if (ret) goto stop_mhi; Loading Loading @@ -919,6 +897,7 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) unsigned long flags; struct pci_dev *pci_dev; struct cnss_pci_data *pci_priv; struct cnss_plat_data *plat_priv; if (!notify) return; Loading @@ -931,9 +910,11 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) if (!pci_priv) return; plat_priv = pci_priv->plat_priv; switch (notify->event) { case MSM_PCIE_EVENT_LINKDOWN: if (pci_link_down_panic) if (test_bit(ENABLE_PCI_LINK_DOWN_PANIC, &plat_priv->ctrl_params.quirks)) panic("cnss: PCI link is down!\n"); spin_lock_irqsave(&pci_link_down_lock, flags); Loading Loading @@ -2346,13 +2327,15 @@ int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv) { int ret = 0; struct cnss_plat_data *plat_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return -ENODEV; } if (fbc_bypass) plat_priv = pci_priv->plat_priv; if (test_bit(FBC_BYPASS, &plat_priv->ctrl_params.quirks)) return 0; if (MHI_TIMEOUT_OVERWRITE_MS) Loading Loading @@ -2381,10 +2364,9 @@ void cnss_pci_stop_mhi(struct cnss_pci_data *pci_priv) return; } if (fbc_bypass) return; plat_priv = pci_priv->plat_priv; if (test_bit(FBC_BYPASS, &plat_priv->ctrl_params.quirks)) return; cnss_pci_set_mhi_state_bit(pci_priv, CNSS_MHI_RESUME); if (!pci_priv->pci_link_down_ind) Loading
drivers/net/wireless/cnss2/qmi.c +24 −35 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -21,42 +21,18 @@ #define WLFW_SERVICE_INS_ID_V01 1 #define WLFW_CLIENT_ID 0x4b4e454c #define MAX_BDF_FILE_NAME 11 #define MAX_BDF_FILE_NAME 13 #define ELF_BDF_FILE_NAME "bdwlan.elf" #define ELF_BDF_FILE_NAME_PREFIX "bdwlan.e" #define BIN_BDF_FILE_NAME "bdwlan.bin" #define BIN_BDF_FILE_NAME_PREFIX "bdwlan.b" #define DUMMY_BDF_FILE_NAME "bdwlan.dmy" enum cnss_bdf_type { CNSS_BDF_BIN, CNSS_BDF_ELF, CNSS_BDF_DUMMY = 255, }; #ifdef CONFIG_CNSS2_DEBUG static unsigned int qmi_timeout = 10000; module_param(qmi_timeout, uint, 0600); MODULE_PARM_DESC(qmi_timeout, "Timeout for QMI message in milliseconds"); #define QMI_WLFW_TIMEOUT_MS qmi_timeout #else #define QMI_WLFW_TIMEOUT_MS 10000 #endif #define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout) #define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS) #define QMI_WLFW_MAX_RECV_BUF_SIZE SZ_8K static bool daemon_support = true; module_param(daemon_support, bool, 0600); MODULE_PARM_DESC(daemon_support, "User space has cnss-daemon support or not"); static unsigned int bdf_type = CNSS_BDF_ELF; #ifdef CONFIG_CNSS2_DEBUG module_param(bdf_type, uint, 0600); MODULE_PARM_DESC(bdf_type, "Type of board data file to be downloaded"); #endif static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode) { switch (mode) { Loading Loading @@ -181,7 +157,11 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) } req->num_clients_valid = 1; req->num_clients = daemon_support ? 2 : 1; if (test_bit(ENABLE_DAEMON_SUPPORT, &plat_priv->ctrl_params.quirks)) req->num_clients = 2; else req->num_clients = 1; cnss_pr_dbg("Number of clients is %d\n", req->num_clients); req->wake_msi = cnss_bus_get_wake_irq(plat_priv); Loading Loading @@ -449,22 +429,30 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) return -ENOMEM; } switch (bdf_type) { switch (plat_priv->ctrl_params.bdf_type) { case CNSS_BDF_ELF: if (plat_priv->board_info.board_id == 0xFF) snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME); else else if (plat_priv->board_info.board_id < 0xFF) snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME_PREFIX "%02x", plat_priv->board_info.board_id); else snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME_PREFIX "%04x", plat_priv->board_info.board_id); break; case CNSS_BDF_BIN: if (plat_priv->board_info.board_id == 0xFF) snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME); else else if (plat_priv->board_info.board_id < 0xFF) snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME_PREFIX "%02x", plat_priv->board_info.board_id); else snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME_PREFIX "%04x", plat_priv->board_info.board_id); break; case CNSS_BDF_DUMMY: cnss_pr_dbg("CNSS_BDF_DUMMY is set, sending dummy BDF\n"); Loading @@ -473,7 +461,8 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) remaining = MAX_BDF_FILE_NAME; goto bypass_bdf; default: cnss_pr_err("Invalid BDF type: %d\n", bdf_type); cnss_pr_err("Invalid BDF type: %d\n", plat_priv->ctrl_params.bdf_type); ret = -EINVAL; goto err_req_fw; } Loading @@ -500,7 +489,7 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) req->data_valid = 1; req->end_valid = 1; req->bdf_type_valid = 1; req->bdf_type = bdf_type; req->bdf_type = plat_priv->ctrl_params.bdf_type; if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; Loading Loading @@ -555,7 +544,7 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) return 0; err_send: if (bdf_type != CNSS_BDF_DUMMY) if (plat_priv->ctrl_params.bdf_type != CNSS_BDF_DUMMY) release_firmware(fw_entry); err_req_fw: CNSS_ASSERT(0); Loading Loading @@ -1070,7 +1059,7 @@ int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv, return ret; } unsigned int cnss_get_qmi_timeout(void) unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv) { cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS); Loading