Loading drivers/net/wireless/cnss2/main.c +60 −0 Original line number Diff line number Diff line Loading @@ -2614,14 +2614,74 @@ static ssize_t fs_ready_store(struct device *dev, return count; } static ssize_t qdss_trace_start_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); wlfw_qdss_trace_send_start(plat_priv); cnss_pr_dbg("Received QDSS start command\n"); return count; } static ssize_t qdss_trace_stop_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); u32 option = 0; if (sscanf(buf, "%du", &option) != 1) return -EINVAL; wlfw_qdss_trace_send_stop(plat_priv, option); cnss_pr_dbg("Received QDSS stop command\n"); return count; } static ssize_t qdss_conf_download_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); cnss_wlfw_qdss_dnld_send_sync(plat_priv); cnss_pr_dbg("Received QDSS download config command\n"); return count; } static ssize_t hw_trace_override_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); int tmp = 0; if (sscanf(buf, "%du", &tmp) != 1) return -EINVAL; plat_priv->hw_trc_override = tmp; cnss_pr_dbg("Received QDSS hw_trc_override indication\n"); return count; } static DEVICE_ATTR_WO(fs_ready); static DEVICE_ATTR_WO(shutdown); static DEVICE_ATTR_WO(recovery); static DEVICE_ATTR_WO(qdss_trace_start); static DEVICE_ATTR_WO(qdss_trace_stop); static DEVICE_ATTR_WO(qdss_conf_download); static DEVICE_ATTR_WO(hw_trace_override); static struct attribute *cnss_attrs[] = { &dev_attr_fs_ready.attr, &dev_attr_shutdown.attr, &dev_attr_recovery.attr, &dev_attr_qdss_trace_start.attr, &dev_attr_qdss_trace_stop.attr, &dev_attr_qdss_conf_download.attr, &dev_attr_hw_trace_override.attr, NULL, }; Loading drivers/net/wireless/cnss2/main.h +3 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,8 @@ #define TIME_CLOCK_FREQ_HZ 19200000 #define CNSS_RAMDUMP_MAGIC 0x574C414E #define CNSS_RAMDUMP_VERSION 0 #define MAX_FIRMWARE_NAME_LEN 20 #define MAX_FIRMWARE_NAME_LEN 40 #define FW_V2_NUMBER 2 #define CNSS_EVENT_SYNC BIT(0) #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1) Loading Loading @@ -490,6 +491,7 @@ struct cnss_plat_data { u8 pcie_gen_speed; struct cnss_dms_data dms; int power_up_error; u32 hw_trc_override; }; #ifdef CONFIG_ARCH_QCOM Loading drivers/net/wireless/cnss2/pci.c +0 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ #define DEFAULT_M3_FILE_NAME "m3.bin" #define DEFAULT_FW_FILE_NAME "amss.bin" #define FW_V2_FILE_NAME "amss20.bin" #define FW_V2_NUMBER 2 #define WAKE_MSI_NAME "WAKE" Loading drivers/net/wireless/cnss2/qmi.c +132 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,10 @@ #define REGDB_FILE_NAME "regdb.bin" #define DUMMY_BDF_FILE_NAME "bdwlan.dmy" #define QDSS_TRACE_CONFIG_FILE "qdss_trace_config.cfg" #define QDSS_TRACE_CONFIG_FILE "qdss_trace_config" #define DEBUG_STR "debug" #define HW_V1_NUMBER "v1" #define HW_V2_NUMBER "v2" #define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout) #define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS) Loading Loading @@ -921,6 +924,38 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n return ret; } #ifdef CONFIG_CNSS2_DEBUG static void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv, char *filename, u32 filename_len) { char filename_tmp[MAX_FIRMWARE_NAME_LEN]; if (plat_priv->device_version.major_version == FW_V2_NUMBER) snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s_%s.cfg", DEBUG_STR, HW_V2_NUMBER); else snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s_%s.cfg", DEBUG_STR, HW_V1_NUMBER); cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); } #else static void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv, char *filename, u32 filename_len) { char filename_tmp[MAX_FIRMWARE_NAME_LEN]; if (plat_priv->device_version.major_version == FW_V2_NUMBER) snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s.cfg", HW_V2_NUMBER); else snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s.cfg", HW_V1_NUMBER); cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); } #endif int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) { struct wlfw_qdss_trace_config_download_req_msg_v01 *req; Loading @@ -928,6 +963,7 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) struct qmi_txn txn; const struct firmware *fw_entry = NULL; const u8 *temp; char qdss_cfg_filename[MAX_FIRMWARE_NAME_LEN]; unsigned int remaining; int ret = 0; Loading @@ -944,11 +980,12 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) return -ENOMEM; } ret = request_firmware(&fw_entry, QDSS_TRACE_CONFIG_FILE, cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename, sizeof(qdss_cfg_filename)); ret = request_firmware(&fw_entry, qdss_cfg_filename, &plat_priv->plat_dev->dev); if (ret) { cnss_pr_err("Failed to load QDSS: %s\n", QDSS_TRACE_CONFIG_FILE); qdss_cfg_filename); goto err_req_fw; } Loading @@ -956,7 +993,7 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) remaining = fw_entry->size; cnss_pr_dbg("Downloading QDSS: %s, size: %u\n", QDSS_TRACE_CONFIG_FILE, remaining); qdss_cfg_filename, remaining); while (remaining) { req->total_size_valid = 1; Loading Loading @@ -1029,6 +1066,97 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) return ret; } static int wlfw_send_qdss_trace_mode_req (struct cnss_plat_data *plat_priv, enum wlfw_qdss_trace_mode_enum_v01 mode, unsigned long long option) { int rc = 0; int tmp = 0; struct wlfw_qdss_trace_mode_req_msg_v01 *req; struct wlfw_qdss_trace_mode_resp_msg_v01 *resp; struct qmi_txn txn; if (!plat_priv) return -ENODEV; req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; resp = kzalloc(sizeof(*resp), GFP_KERNEL); if (!resp) { kfree(req); return -ENOMEM; } req->mode_valid = 1; req->mode = mode; req->option_valid = 1; req->option = option; tmp = plat_priv->hw_trc_override; req->hw_trc_disable_override_valid = 1; req->hw_trc_disable_override = (tmp > QMI_PARAM_DISABLE_V01 ? QMI_PARAM_DISABLE_V01 : (tmp < 0 ? QMI_PARAM_INVALID_V01 : tmp)); cnss_pr_dbg("%s: mode %u, option %llu, hw_trc_disable_override: %u", __func__, mode, option, req->hw_trc_disable_override); rc = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, wlfw_qdss_trace_mode_resp_msg_v01_ei, resp); if (rc < 0) { cnss_pr_err("Fail to init txn for QDSS Mode resp %d\n", rc); goto out; } rc = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, QMI_WLFW_QDSS_TRACE_MODE_REQ_V01, WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN, wlfw_qdss_trace_mode_req_msg_v01_ei, req); if (rc < 0) { qmi_txn_cancel(&txn); cnss_pr_err("Fail to send QDSS Mode req %d\n", rc); goto out; } rc = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout); if (rc < 0) { cnss_pr_err("QDSS Mode resp wait failed with rc %d\n", rc); goto out; } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("QMI QDSS Mode request rejected, result:%d error:%d\n", resp->resp.result, resp->resp.error); rc = -resp->resp.result; goto out; } kfree(resp); kfree(req); return rc; out: kfree(resp); kfree(req); CNSS_QMI_ASSERT(); return rc; } int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv) { return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_ON_V01, 0); } int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option) { return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_OFF_V01, option); } int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum cnss_driver_mode mode) { Loading drivers/net/wireless/cnss2/qmi.h +11 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ void cnss_dms_deinit(struct cnss_plat_data *plat_priv); int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv); int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name, u32 total_size); int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv); int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option); #else #define QMI_WLFW_TIMEOUT_MS 10000 Loading Loading @@ -274,6 +276,15 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n return 0; } static inline void cnss_dms_deinit(struct cnss_plat_data *plat_priv) {} int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv) { return 0; } int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option) { return 0; } #endif /* CONFIG_CNSS2_QMI */ #ifdef CONFIG_CNSS2_DEBUG Loading Loading
drivers/net/wireless/cnss2/main.c +60 −0 Original line number Diff line number Diff line Loading @@ -2614,14 +2614,74 @@ static ssize_t fs_ready_store(struct device *dev, return count; } static ssize_t qdss_trace_start_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); wlfw_qdss_trace_send_start(plat_priv); cnss_pr_dbg("Received QDSS start command\n"); return count; } static ssize_t qdss_trace_stop_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); u32 option = 0; if (sscanf(buf, "%du", &option) != 1) return -EINVAL; wlfw_qdss_trace_send_stop(plat_priv, option); cnss_pr_dbg("Received QDSS stop command\n"); return count; } static ssize_t qdss_conf_download_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); cnss_wlfw_qdss_dnld_send_sync(plat_priv); cnss_pr_dbg("Received QDSS download config command\n"); return count; } static ssize_t hw_trace_override_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); int tmp = 0; if (sscanf(buf, "%du", &tmp) != 1) return -EINVAL; plat_priv->hw_trc_override = tmp; cnss_pr_dbg("Received QDSS hw_trc_override indication\n"); return count; } static DEVICE_ATTR_WO(fs_ready); static DEVICE_ATTR_WO(shutdown); static DEVICE_ATTR_WO(recovery); static DEVICE_ATTR_WO(qdss_trace_start); static DEVICE_ATTR_WO(qdss_trace_stop); static DEVICE_ATTR_WO(qdss_conf_download); static DEVICE_ATTR_WO(hw_trace_override); static struct attribute *cnss_attrs[] = { &dev_attr_fs_ready.attr, &dev_attr_shutdown.attr, &dev_attr_recovery.attr, &dev_attr_qdss_trace_start.attr, &dev_attr_qdss_trace_stop.attr, &dev_attr_qdss_conf_download.attr, &dev_attr_hw_trace_override.attr, NULL, }; Loading
drivers/net/wireless/cnss2/main.h +3 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,8 @@ #define TIME_CLOCK_FREQ_HZ 19200000 #define CNSS_RAMDUMP_MAGIC 0x574C414E #define CNSS_RAMDUMP_VERSION 0 #define MAX_FIRMWARE_NAME_LEN 20 #define MAX_FIRMWARE_NAME_LEN 40 #define FW_V2_NUMBER 2 #define CNSS_EVENT_SYNC BIT(0) #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1) Loading Loading @@ -490,6 +491,7 @@ struct cnss_plat_data { u8 pcie_gen_speed; struct cnss_dms_data dms; int power_up_error; u32 hw_trc_override; }; #ifdef CONFIG_ARCH_QCOM Loading
drivers/net/wireless/cnss2/pci.c +0 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ #define DEFAULT_M3_FILE_NAME "m3.bin" #define DEFAULT_FW_FILE_NAME "amss.bin" #define FW_V2_FILE_NAME "amss20.bin" #define FW_V2_NUMBER 2 #define WAKE_MSI_NAME "WAKE" Loading
drivers/net/wireless/cnss2/qmi.c +132 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,10 @@ #define REGDB_FILE_NAME "regdb.bin" #define DUMMY_BDF_FILE_NAME "bdwlan.dmy" #define QDSS_TRACE_CONFIG_FILE "qdss_trace_config.cfg" #define QDSS_TRACE_CONFIG_FILE "qdss_trace_config" #define DEBUG_STR "debug" #define HW_V1_NUMBER "v1" #define HW_V2_NUMBER "v2" #define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout) #define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS) Loading Loading @@ -921,6 +924,38 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n return ret; } #ifdef CONFIG_CNSS2_DEBUG static void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv, char *filename, u32 filename_len) { char filename_tmp[MAX_FIRMWARE_NAME_LEN]; if (plat_priv->device_version.major_version == FW_V2_NUMBER) snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s_%s.cfg", DEBUG_STR, HW_V2_NUMBER); else snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s_%s.cfg", DEBUG_STR, HW_V1_NUMBER); cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); } #else static void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv, char *filename, u32 filename_len) { char filename_tmp[MAX_FIRMWARE_NAME_LEN]; if (plat_priv->device_version.major_version == FW_V2_NUMBER) snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s.cfg", HW_V2_NUMBER); else snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE "_%s.cfg", HW_V1_NUMBER); cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); } #endif int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) { struct wlfw_qdss_trace_config_download_req_msg_v01 *req; Loading @@ -928,6 +963,7 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) struct qmi_txn txn; const struct firmware *fw_entry = NULL; const u8 *temp; char qdss_cfg_filename[MAX_FIRMWARE_NAME_LEN]; unsigned int remaining; int ret = 0; Loading @@ -944,11 +980,12 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) return -ENOMEM; } ret = request_firmware(&fw_entry, QDSS_TRACE_CONFIG_FILE, cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename, sizeof(qdss_cfg_filename)); ret = request_firmware(&fw_entry, qdss_cfg_filename, &plat_priv->plat_dev->dev); if (ret) { cnss_pr_err("Failed to load QDSS: %s\n", QDSS_TRACE_CONFIG_FILE); qdss_cfg_filename); goto err_req_fw; } Loading @@ -956,7 +993,7 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) remaining = fw_entry->size; cnss_pr_dbg("Downloading QDSS: %s, size: %u\n", QDSS_TRACE_CONFIG_FILE, remaining); qdss_cfg_filename, remaining); while (remaining) { req->total_size_valid = 1; Loading Loading @@ -1029,6 +1066,97 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) return ret; } static int wlfw_send_qdss_trace_mode_req (struct cnss_plat_data *plat_priv, enum wlfw_qdss_trace_mode_enum_v01 mode, unsigned long long option) { int rc = 0; int tmp = 0; struct wlfw_qdss_trace_mode_req_msg_v01 *req; struct wlfw_qdss_trace_mode_resp_msg_v01 *resp; struct qmi_txn txn; if (!plat_priv) return -ENODEV; req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; resp = kzalloc(sizeof(*resp), GFP_KERNEL); if (!resp) { kfree(req); return -ENOMEM; } req->mode_valid = 1; req->mode = mode; req->option_valid = 1; req->option = option; tmp = plat_priv->hw_trc_override; req->hw_trc_disable_override_valid = 1; req->hw_trc_disable_override = (tmp > QMI_PARAM_DISABLE_V01 ? QMI_PARAM_DISABLE_V01 : (tmp < 0 ? QMI_PARAM_INVALID_V01 : tmp)); cnss_pr_dbg("%s: mode %u, option %llu, hw_trc_disable_override: %u", __func__, mode, option, req->hw_trc_disable_override); rc = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, wlfw_qdss_trace_mode_resp_msg_v01_ei, resp); if (rc < 0) { cnss_pr_err("Fail to init txn for QDSS Mode resp %d\n", rc); goto out; } rc = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, QMI_WLFW_QDSS_TRACE_MODE_REQ_V01, WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN, wlfw_qdss_trace_mode_req_msg_v01_ei, req); if (rc < 0) { qmi_txn_cancel(&txn); cnss_pr_err("Fail to send QDSS Mode req %d\n", rc); goto out; } rc = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout); if (rc < 0) { cnss_pr_err("QDSS Mode resp wait failed with rc %d\n", rc); goto out; } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("QMI QDSS Mode request rejected, result:%d error:%d\n", resp->resp.result, resp->resp.error); rc = -resp->resp.result; goto out; } kfree(resp); kfree(req); return rc; out: kfree(resp); kfree(req); CNSS_QMI_ASSERT(); return rc; } int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv) { return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_ON_V01, 0); } int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option) { return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_OFF_V01, option); } int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum cnss_driver_mode mode) { Loading
drivers/net/wireless/cnss2/qmi.h +11 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ void cnss_dms_deinit(struct cnss_plat_data *plat_priv); int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv); int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name, u32 total_size); int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv); int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option); #else #define QMI_WLFW_TIMEOUT_MS 10000 Loading Loading @@ -274,6 +276,15 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n return 0; } static inline void cnss_dms_deinit(struct cnss_plat_data *plat_priv) {} int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv) { return 0; } int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option) { return 0; } #endif /* CONFIG_CNSS2_QMI */ #ifdef CONFIG_CNSS2_DEBUG Loading