瀏覽代碼

Merge c4bc8cea33596751a56d3ab1e80f8466e51be2a3 on remote branch

Change-Id: I2dd89ba303468c24ac926af4850cf6062bceac62
Linux Build Service Account 1 年之前
父節點
當前提交
85bf216799
共有 11 個文件被更改,包括 493 次插入22 次删除
  1. 15 0
      cnss2/bus.c
  2. 1 0
      cnss2/bus.h
  3. 35 1
      cnss2/main.c
  4. 4 0
      cnss2/main.h
  5. 153 0
      cnss2/pci.c
  6. 1 0
      cnss2/pci.h
  7. 122 14
      cnss2/qmi.c
  8. 2 0
      cnss2/qmi.h
  9. 117 0
      cnss_utils/wlan_firmware_service_v01.c
  10. 39 2
      cnss_utils/wlan_firmware_service_v01.h
  11. 4 5
      icnss2/main.c

+ 15 - 0
cnss2/bus.c

@@ -139,6 +139,21 @@ void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
 	}
 }
 
+int cnss_bus_load_tme_patch(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return -ENODEV;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		return cnss_pci_load_tme_patch(plat_priv->bus_priv);
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return -EINVAL;
+	}
+}
+
 int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
 {
 	if (!plat_priv)

+ 1 - 0
cnss2/bus.h

@@ -21,6 +21,7 @@ int cnss_bus_init(struct cnss_plat_data *plat_priv);
 void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
 void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
 				 char *prefix_name, char *name);
+int cnss_bus_load_tme_patch(struct cnss_plat_data *plat_priv);
 int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
 int cnss_bus_load_aux(struct cnss_plat_data *plat_priv);
 int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv);

+ 35 - 1
cnss2/main.c

@@ -467,6 +467,35 @@ int cnss_get_feature_list(struct cnss_plat_data *plat_priv,
 	return 0;
 }
 
+size_t cnss_get_platform_name(struct cnss_plat_data *plat_priv,
+			      char *buf, const size_t buf_len)
+{
+	if (unlikely(!plat_priv || !buf || !buf_len))
+		return 0;
+
+	if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
+				  "platform-name-required")) {
+		struct device_node *root;
+
+		root = of_find_node_by_path("/");
+		if (root) {
+			const char *model;
+			size_t model_len;
+
+			model = of_get_property(root, "model", NULL);
+			if (model) {
+				model_len = strlcpy(buf, model, buf_len);
+				cnss_pr_dbg("Platform name: %s (%zu)\n",
+					    buf, model_len);
+
+				return model_len;
+			}
+		}
+	}
+
+	return 0;
+}
+
 void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv)
 {
 	if (atomic_inc_return(&plat_priv->pm_count) != 1)
@@ -842,6 +871,11 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 	if (ret)
 		goto out;
 
+	cnss_bus_load_tme_patch(plat_priv);
+
+	cnss_wlfw_tme_patch_dnld_send_sync(plat_priv,
+					   WLFW_TME_LITE_PATCH_FILE_V01);
+
 	if (plat_priv->hds_enabled)
 		cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_HDS);
 
@@ -4440,7 +4474,7 @@ static void cnss_sram_dump_init(struct cnss_plat_data *plat_priv)
 }
 #endif
 
-#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
+#if IS_ENABLED(CONFIG_WCNSS_MEM_PRE_ALLOC)
 static void cnss_initialize_mem_pool(unsigned long device_id)
 {
 	cnss_initialize_prealloc_pool(device_id);

+ 4 - 0
cnss2/main.h

@@ -548,6 +548,7 @@ struct cnss_plat_data {
 	u32 fw_mem_seg_len;
 	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
 	struct cnss_fw_mem m3_mem;
+	struct cnss_fw_mem tme_lite_mem;
 	struct cnss_fw_mem *cal_mem;
 	struct cnss_fw_mem aux_mem;
 	u64 cal_time;
@@ -566,6 +567,7 @@ struct cnss_plat_data {
 	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 supported_link_speed;
 	u32 device_freq_hz;
 	u32 diag_reg_read_addr;
 	u32 diag_reg_read_mem_type;
@@ -743,4 +745,6 @@ int cnss_get_input_gpio_value(struct cnss_plat_data *plat_priv, int gpio_num);
 bool cnss_check_driver_loading_allowed(void);
 int cnss_dev_specific_power_on(struct cnss_plat_data *plat_priv);
 void cnss_recovery_handler(struct cnss_plat_data *plat_priv);
+size_t cnss_get_platform_name(struct cnss_plat_data *plat_priv,
+			      char *buf, const size_t buf_len);
 #endif /* _CNSS_MAIN_H */

+ 153 - 0
cnss2/pci.c

@@ -49,6 +49,7 @@
 #define DEFAULT_PHY_M3_FILE_NAME	"m3.bin"
 #define DEFAULT_AUX_FILE_NAME		"aux_ucode.elf"
 #define DEFAULT_PHY_UCODE_FILE_NAME	"phy_ucode.elf"
+#define TME_PATCH_FILE_NAME		"tmel_patch.elf"
 #define PHY_UCODE_V2_FILE_NAME		"phy_ucode20.elf"
 #define DEFAULT_FW_FILE_NAME		"amss.bin"
 #define FW_V2_FILE_NAME			"amss20.bin"
@@ -1310,6 +1311,42 @@ static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save)
 	return 0;
 }
 
+static int cnss_update_supported_link_info(struct cnss_pci_data *pci_priv)
+{
+	int ret = 0;
+	struct pci_dev *root_port;
+	struct device_node *root_of_node;
+	struct cnss_plat_data *plat_priv;
+
+	if (!pci_priv)
+		return -EINVAL;
+
+	if (pci_priv->device_id != KIWI_DEVICE_ID)
+		return ret;
+
+	plat_priv = pci_priv->plat_priv;
+	root_port = pcie_find_root_port(pci_priv->pci_dev);
+
+	if (!root_port) {
+		cnss_pr_err("PCIe root port is null\n");
+		return -EINVAL;
+	}
+
+	root_of_node = root_port->dev.of_node;
+	if (root_of_node && root_of_node->parent) {
+		ret = of_property_read_u32(root_of_node->parent,
+					   "qcom,target-link-speed",
+					   &plat_priv->supported_link_speed);
+		if (!ret)
+			cnss_pr_dbg("Supported PCIe Link Speed: %d\n",
+				    plat_priv->supported_link_speed);
+		else
+			plat_priv->supported_link_speed = 0;
+	}
+
+	return ret;
+}
+
 static int cnss_pci_get_link_status(struct cnss_pci_data *pci_priv)
 {
 	u16 link_status;
@@ -4762,6 +4799,78 @@ void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv)
 	plat_priv->qdss_mem_seg_len = 0;
 }
 
+int cnss_pci_load_tme_patch(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *tme_lite_mem = &plat_priv->tme_lite_mem;
+	char filename[MAX_FIRMWARE_NAME_LEN];
+	char *tme_patch_filename = NULL;
+	const struct firmware *fw_entry;
+	int ret = 0;
+
+	switch (pci_priv->device_id) {
+	case PEACH_DEVICE_ID:
+		tme_patch_filename = TME_PATCH_FILE_NAME;
+		break;
+	case QCA6174_DEVICE_ID:
+	case QCA6290_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
+	case QCA6490_DEVICE_ID:
+	case KIWI_DEVICE_ID:
+	case MANGO_DEVICE_ID:
+	default:
+		cnss_pr_dbg("TME-L not supported for device ID: (0x%x)\n",
+			    pci_priv->device_id);
+		return 0;
+	}
+
+	if (!tme_lite_mem->va && !tme_lite_mem->size) {
+		cnss_pci_add_fw_prefix_name(pci_priv, filename,
+					    tme_patch_filename);
+
+		ret = firmware_request_nowarn(&fw_entry, filename,
+					      &pci_priv->pci_dev->dev);
+		if (ret) {
+			cnss_pr_err("Failed to load TME-L patch: %s, ret: %d\n",
+				    filename, ret);
+			return ret;
+		}
+
+		tme_lite_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev,
+						fw_entry->size, &tme_lite_mem->pa,
+						GFP_KERNEL);
+		if (!tme_lite_mem->va) {
+			cnss_pr_err("Failed to allocate memory for M3, size: 0x%zx\n",
+				    fw_entry->size);
+			release_firmware(fw_entry);
+			return -ENOMEM;
+		}
+
+		memcpy(tme_lite_mem->va, fw_entry->data, fw_entry->size);
+		tme_lite_mem->size = fw_entry->size;
+		release_firmware(fw_entry);
+	}
+
+	return 0;
+}
+
+static void cnss_pci_free_tme_lite_mem(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *tme_lite_mem = &plat_priv->tme_lite_mem;
+
+	if (tme_lite_mem->va && tme_lite_mem->size) {
+		cnss_pr_dbg("Freeing memory for TME patch, va: 0x%pK, pa: %pa, size: 0x%zx\n",
+			    tme_lite_mem->va, &tme_lite_mem->pa, tme_lite_mem->size);
+		dma_free_coherent(&pci_priv->pci_dev->dev, tme_lite_mem->size,
+				  tme_lite_mem->va, tme_lite_mem->pa);
+	}
+
+	tme_lite_mem->va = NULL;
+	tme_lite_mem->pa = 0;
+	tme_lite_mem->size = 0;
+}
+
 int cnss_pci_load_m3(struct cnss_pci_data *pci_priv)
 {
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -5139,6 +5248,19 @@ int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
 					    base_vector);
 }
 
+static int cnss_pci_irq_set_affinity_hint(struct cnss_pci_data *pci_priv,
+					  unsigned int vec,
+					  const struct cpumask *cpumask)
+{
+	int ret;
+	struct pci_dev *pci_dev = pci_priv->pci_dev;
+
+	ret = irq_set_affinity_hint(pci_irq_vector(pci_dev, vec),
+				    cpumask);
+
+	return ret;
+}
+
 static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv)
 {
 	int ret = 0;
@@ -5180,6 +5302,24 @@ static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv)
 		goto reset_msi_config;
 	}
 
+	/* With VT-d disabled on x86 platform, only one pci irq vector is
+	 * allocated. Once suspend the irq may be migrated to CPU0 if it was
+	 * affine to other CPU with one new msi vector re-allocated.
+	 * The observation cause the issue about no irq handler for vector
+	 * once resume.
+	 * The fix is to set irq vector affinity to CPU0 before calling
+	 * request_irq to avoid the irq migration.
+	 */
+	if (cnss_pci_is_one_msi(pci_priv)) {
+		ret = cnss_pci_irq_set_affinity_hint(pci_priv,
+						     0,
+						     cpumask_of(0));
+		if (ret) {
+			cnss_pr_err("Failed to affinize irq vector to CPU0\n");
+			goto free_msi_vector;
+		}
+	}
+
 	if (cnss_pci_config_msi_addr(pci_priv)) {
 		ret = -EINVAL;
 		goto free_msi_vector;
@@ -5193,6 +5333,8 @@ static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv)
 	return 0;
 
 free_msi_vector:
+	if (cnss_pci_is_one_msi(pci_priv))
+		cnss_pci_irq_set_affinity_hint(pci_priv, 0, NULL);
 	pci_free_irq_vectors(pci_priv->pci_dev);
 reset_msi_config:
 	pci_priv->msi_config = NULL;
@@ -5205,6 +5347,9 @@ static void cnss_pci_disable_msi(struct cnss_pci_data *pci_priv)
 	if (pci_priv->device_id == QCA6174_DEVICE_ID)
 		return;
 
+	if (cnss_pci_is_one_msi(pci_priv))
+		cnss_pci_irq_set_affinity_hint(pci_priv, 0, NULL);
+
 	pci_free_irq_vectors(pci_priv->pci_dev);
 }
 
@@ -5603,6 +5748,11 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 	ret = cnss_pci_pm_runtime_get_sync(pci_priv, RTPM_ID_CNSS);
 	if (ret < 0)
 		goto runtime_pm_put;
+	/*
+	 * In some scenarios, cnss_pci_pm_runtime_get_sync
+	 * might not resume PCI bus. For those cases do auto resume.
+	 */
+	cnss_auto_resume(&pci_priv->pci_dev->dev);
 
 	if (!pci_priv->is_smmu_fault)
 		cnss_pci_mhi_reg_dump(pci_priv);
@@ -7030,6 +7180,8 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
 	/* update drv support flag */
 	cnss_pci_update_drv_supported(pci_priv);
 
+	cnss_update_supported_link_info(pci_priv);
+
 	ret = cnss_reg_pci_event(pci_priv);
 	if (ret) {
 		cnss_pr_err("Failed to register PCI event, err = %d\n", ret);
@@ -7123,6 +7275,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
 	clear_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state);
 	cnss_pci_unregister_driver_hdlr(pci_priv);
 	cnss_pci_free_aux_mem(pci_priv);
+	cnss_pci_free_tme_lite_mem(pci_priv);
 	cnss_pci_free_m3_mem(pci_priv);
 	cnss_pci_free_fw_mem(pci_priv);
 	cnss_pci_free_qdss_mem(pci_priv);

+ 1 - 0
cnss2/pci.h

@@ -253,6 +253,7 @@ void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
 int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
 void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
+int cnss_pci_load_tme_patch(struct cnss_pci_data *pci_priv);
 int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
 void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_load_aux(struct cnss_pci_data *pci_priv);

+ 122 - 14
cnss2/qmi.c

@@ -33,10 +33,15 @@
 #define INI_FILE_NAME_LEN		100
 
 #define QDSS_TRACE_CONFIG_FILE		"qdss_trace_config"
+/*
+ * Download QDSS config file based on build type. Add build type string to
+ * file name. Download "qdss_trace_config_debug_v<n>.cfg" for debug build
+ * and "qdss_trace_config_perf_v<n>.cfg" for perf build.
+ */
 #ifdef CONFIG_CNSS2_DEBUG
-#define QDSS_DEBUG_FILE_STR		"debug_"
+#define QDSS_FILE_BUILD_STR		"debug_"
 #else
-#define QDSS_DEBUG_FILE_STR		""
+#define QDSS_FILE_BUILD_STR		"perf_"
 #endif
 #define HW_V1_NUMBER			"v1"
 #define HW_V2_NUMBER			"v2"
@@ -322,6 +327,14 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
 		req->nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT;
 	}
 
+	if (plat_priv->supported_link_speed) {
+		req->pcie_link_info_valid = 1;
+		req->pcie_link_info.pci_link_speed =
+					plat_priv->supported_link_speed;
+		cnss_pr_dbg("Supported link speed in Host Cap %d\n",
+			    plat_priv->supported_link_speed);
+	}
+
 	if (cnss_bus_is_smmu_s1_enabled(plat_priv) &&
 	    !cnss_bus_get_iova(plat_priv, &iova_start, &iova_size) &&
 	    !cnss_bus_get_iova_ipa(plat_priv, &iova_ipa_start,
@@ -345,6 +358,11 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
 		cnss_pr_dbg("Sending feature list 0x%llx\n",
 			    req->feature_list);
 	}
+
+	if (cnss_get_platform_name(plat_priv, req->platform_name,
+				   QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01))
+		req->platform_name_valid = 1;
+
 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
 			   wlfw_host_cap_resp_msg_v01_ei, resp);
 	if (ret < 0) {
@@ -1017,6 +1035,87 @@ err_req_fw:
 	return ret;
 }
 
+int cnss_wlfw_tme_patch_dnld_send_sync(struct cnss_plat_data *plat_priv,
+				       enum wlfw_tme_lite_file_type_v01 file)
+{
+	struct wlfw_tme_lite_info_req_msg_v01 *req;
+	struct wlfw_tme_lite_info_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	struct cnss_fw_mem *tme_lite_mem = &plat_priv->tme_lite_mem;
+	int ret = 0;
+
+	cnss_pr_dbg("Sending TME patch information message, state: 0x%lx\n",
+		    plat_priv->driver_state);
+
+	if (plat_priv->device_id != PEACH_DEVICE_ID)
+		return 0;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	if (!tme_lite_mem->pa || !tme_lite_mem->size) {
+		cnss_pr_err("Memory for TME patch is not available\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cnss_pr_dbg("TME-L patch memory, va: 0x%pK, pa: %pa, size: 0x%zx\n",
+		    tme_lite_mem->va, &tme_lite_mem->pa, tme_lite_mem->size);
+
+	req->tme_file = file;
+	req->addr = plat_priv->tme_lite_mem.pa;
+	req->size = plat_priv->tme_lite_mem.size;
+
+	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
+			   wlfw_tme_lite_info_resp_msg_v01_ei, resp);
+	if (ret < 0) {
+		cnss_pr_err("Failed to initialize txn for TME patch information request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
+			       QMI_WLFW_TME_LITE_INFO_REQ_V01,
+			       WLFW_TME_LITE_INFO_REQ_MSG_V01_MAX_MSG_LEN,
+			       wlfw_tme_lite_info_req_msg_v01_ei, req);
+	if (ret < 0) {
+		qmi_txn_cancel(&txn);
+		cnss_pr_err("Failed to send TME patch information request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
+	if (ret < 0) {
+		cnss_pr_err("Failed to wait for response of TME patch information request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+		cnss_pr_err("TME patch information request failed, result: %d, err: %d\n",
+			    resp->resp.result, resp->resp.error);
+		ret = -resp->resp.result;
+		goto out;
+	}
+
+	kfree(req);
+	kfree(resp);
+	return 0;
+
+out:
+	kfree(req);
+	kfree(resp);
+	return ret;
+}
+
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
 {
 	struct wlfw_m3_info_req_msg_v01 *req;
@@ -1350,22 +1449,21 @@ end:
 }
 
 void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv,
-				char *filename, u32 filename_len)
+				char *filename, u32 filename_len,
+				bool fallback_file)
 {
 	char filename_tmp[MAX_FIRMWARE_NAME_LEN];
-	char *debug_str = QDSS_DEBUG_FILE_STR;
+	char *build_str = QDSS_FILE_BUILD_STR;
 
-	if (plat_priv->device_id == KIWI_DEVICE_ID ||
-	    plat_priv->device_id == MANGO_DEVICE_ID ||
-	    plat_priv->device_id == PEACH_DEVICE_ID)
-		debug_str = "";
+	if (fallback_file)
+		build_str = "";
 
 	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);
+			 "_%s%s.cfg", build_str, HW_V2_NUMBER);
 	else
 		snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE
-			 "_%s%s.cfg", debug_str, HW_V1_NUMBER);
+			 "_%s%s.cfg", build_str, HW_V1_NUMBER);
 
 	cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp);
 }
@@ -1394,13 +1492,23 @@ int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv)
 		return -ENOMEM;
 	}
 
-	cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename, sizeof(qdss_cfg_filename));
+	cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename,
+				   sizeof(qdss_cfg_filename), false);
 	ret = cnss_request_firmware_direct(plat_priv, &fw_entry,
 					   qdss_cfg_filename);
 	if (ret) {
-		cnss_pr_dbg("Unable to load %s\n",
-			    qdss_cfg_filename);
-		goto err_req_fw;
+		cnss_pr_dbg("Unable to load %s ret %d, try default file\n",
+			    qdss_cfg_filename, ret);
+		cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename,
+					   sizeof(qdss_cfg_filename),
+					   true);
+		ret = cnss_request_firmware_direct(plat_priv, &fw_entry,
+						   qdss_cfg_filename);
+		if (ret) {
+			cnss_pr_err("Unable to load %s ret %d\n",
+				    qdss_cfg_filename, ret);
+			goto err_req_fw;
+		}
 	}
 
 	temp = fw_entry->data;

+ 2 - 0
cnss2/qmi.h

@@ -44,6 +44,8 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
 				 u32 bdf_type);
+int cnss_wlfw_tme_patch_dnld_send_sync(struct cnss_plat_data *plat_priv,
+				       enum wlfw_tme_lite_file_type_v01 file);
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,

+ 117 - 0
cnss_utils/wlan_firmware_service_v01.c

@@ -804,6 +804,34 @@ static struct qmi_elem_info wlfw_share_mem_info_s_v01_ei[] = {
 	},
 };
 
+static struct qmi_elem_info wlfw_host_pcie_link_info_s_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct
+					   wlfw_host_pcie_link_info_s_v01,
+					   pci_link_speed),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct
+					   wlfw_host_pcie_link_info_s_v01,
+					   pci_link_width),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
 struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
 	{
 		.data_type      = QMI_OPT_FLAG,
@@ -1205,6 +1233,26 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
 					   wlfw_ind_register_req_msg_v01,
 					   m3_dump_upload_segments_req_enable),
 	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x24,
+		.offset         = offsetof(struct
+					   wlfw_ind_register_req_msg_v01,
+					   fw_ssr_enable_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x24,
+		.offset         = offsetof(struct
+					   wlfw_ind_register_req_msg_v01,
+					   fw_ssr_enable),
+	},
 	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
@@ -4062,6 +4110,27 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
 					   mlo_chip_v2_info),
 		.ei_array      = wlfw_host_mlo_chip_v2_info_s_v01_ei,
 	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x30,
+		.offset         = offsetof(struct
+					   wlfw_host_cap_req_msg_v01,
+					   pcie_link_info_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct wlfw_host_pcie_link_info_s_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x30,
+		.offset         = offsetof(struct
+					   wlfw_host_cap_req_msg_v01,
+					   pcie_link_info),
+		.ei_array      = wlfw_host_pcie_link_info_s_v01_ei,
+	},
 	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
@@ -6569,6 +6638,54 @@ struct qmi_elem_info wlfw_tme_lite_info_resp_msg_v01_ei[] = {
 };
 EXPORT_SYMBOL(wlfw_tme_lite_info_resp_msg_v01_ei);
 
+struct qmi_elem_info wlfw_fw_ssr_ind_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_fw_ssr_ind_msg_v01_ei);
+
+struct qmi_elem_info wlfw_bmps_ctrl_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wlfw_bmps_state_enum_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_bmps_ctrl_req_msg_v01,
+					   bmps_state),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_bmps_ctrl_req_msg_v01_ei);
+
+struct qmi_elem_info wlfw_bmps_ctrl_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_bmps_ctrl_resp_msg_v01,
+					   resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_bmps_ctrl_resp_msg_v01_ei);
+
 /**
  * wlfw_is_valid_dt_node_found - Check if valid device tree node present
  *

+ 39 - 2
cnss_utils/wlan_firmware_service_v01.h

@@ -37,6 +37,7 @@
 #define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
 #define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
 #define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
+#define QMI_WLFW_BMPS_CTRL_RESP_V01 0x005D
 #define QMI_WLFW_AUX_UC_INFO_RESP_V01 0x005A
 #define QMI_WLFW_M3_INFO_REQ_V01 0x003C
 #define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053
@@ -75,10 +76,12 @@
 #define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F
 #define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
 #define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031
+#define QMI_WLFW_FW_SSR_IND_V01 0x005C
 #define QMI_WLFW_PHY_CAP_RESP_V01 0x0057
 #define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044
 #define QMI_WLFW_SOC_WAKE_RESP_V01 0x004F
 #define QMI_WLFW_GET_INFO_RESP_V01 0x004A
+#define QMI_WLFW_BMPS_CTRL_REQ_V01 0x005D
 #define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053
 #define QMI_WLFW_INI_REQ_V01 0x002F
 #define QMI_WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_V01 0x0054
@@ -354,6 +357,13 @@ enum wlfw_tme_lite_file_type_v01 {
 	WLFW_TME_LITE_FILE_TYPE_MAX_VAL_V01 = INT_MAX,
 };
 
+enum wlfw_bmps_state_enum_v01 {
+	WLFW_BMPS_STATE_ENUM_MIN_VAL_V01 = INT_MIN,
+	QMI_WLFW_BMPS_ENABLE_V01 = 0,
+	QMI_WLFW_BMPS_DISABLE_V01 = 1,
+	WLFW_BMPS_STATE_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
 #define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
 #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
 #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
@@ -506,6 +516,11 @@ struct wlfw_share_mem_info_s_v01 {
 	u64 size;
 };
 
+struct wlfw_host_pcie_link_info_s_v01 {
+	u32 pci_link_speed;
+	u32 pci_link_width;
+};
+
 struct wlfw_ind_register_req_msg_v01 {
 	u8 fw_ready_enable_valid;
 	u8 fw_ready_enable;
@@ -547,8 +562,10 @@ struct wlfw_ind_register_req_msg_v01 {
 	u8 qdss_mem_ready_enable;
 	u8 m3_dump_upload_segments_req_enable_valid;
 	u8 m3_dump_upload_segments_req_enable;
+	u8 fw_ssr_enable_valid;
+	u8 fw_ssr_enable;
 };
-#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 86
+#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 90
 extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
 
 struct wlfw_ind_register_resp_msg_v01 {
@@ -976,8 +993,10 @@ struct wlfw_host_cap_req_msg_v01 {
 	u8 fw_ini_cfg_support;
 	u8 mlo_chip_v2_info_valid;
 	struct wlfw_host_mlo_chip_v2_info_s_v01 mlo_chip_v2_info[QMI_WLFW_MAX_NUM_MLO_V2_CHIPS_V01];
+	u8 pcie_link_info_valid;
+	struct wlfw_host_pcie_link_info_s_v01 pcie_link_info;
 };
-#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 570
+#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 581
 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
 
 struct wlfw_host_cap_resp_msg_v01 {
@@ -1499,4 +1518,22 @@ struct wlfw_tme_lite_info_resp_msg_v01 {
 #define WLFW_TME_LITE_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
 extern struct qmi_elem_info wlfw_tme_lite_info_resp_msg_v01_ei[];
 
+struct wlfw_fw_ssr_ind_msg_v01 {
+	char placeholder;
+};
+#define WLFW_FW_SSR_IND_MSG_V01_MAX_MSG_LEN 0
+extern struct qmi_elem_info wlfw_fw_ssr_ind_msg_v01_ei[];
+
+struct wlfw_bmps_ctrl_req_msg_v01 {
+	enum wlfw_bmps_state_enum_v01 bmps_state;
+};
+#define WLFW_BMPS_CTRL_REQ_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_bmps_ctrl_req_msg_v01_ei[];
+
+struct wlfw_bmps_ctrl_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+#define WLFW_BMPS_CTRL_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_bmps_ctrl_resp_msg_v01_ei[];
+
 #endif

+ 4 - 5
icnss2/main.c

@@ -4299,14 +4299,13 @@ static int icnss_resource_parse(struct icnss_priv *priv)
 
 		icnss_get_msi_assignment(priv);
 		for (i = 0; i < priv->msi_config->total_vectors; i++) {
-			res = platform_get_resource(priv->pdev,
-						    IORESOURCE_IRQ, i);
-			if (!res) {
+			irq = platform_get_irq(priv->pdev, i);
+			if (irq < 0) {
 				icnss_pr_err("Fail to get IRQ-%d\n", i);
 				ret = -ENODEV;
 				goto put_clk;
 			} else {
-				priv->srng_irqs[i] = res->start;
+				priv->srng_irqs[i] = irq;
 			}
 		}
 	}
@@ -4621,7 +4620,7 @@ static void rproc_restart_level_notifier(void *data, struct rproc *rproc)
 	}
 }
 
-#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
+#if IS_ENABLED(CONFIG_WCNSS_MEM_PRE_ALLOC)
 static void icnss_initialize_mem_pool(unsigned long device_id)
 {
 	cnss_initialize_prealloc_pool(device_id);