Loading drivers/net/wireless/cnss2/main.c +8 −0 Original line number Original line Diff line number Diff line Loading @@ -420,6 +420,14 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) if (ret) if (ret) goto out; goto out; ret = cnss_pci_load_m3(plat_priv->bus_priv); if (ret) goto out; ret = cnss_wlfw_m3_dnld_send_sync(plat_priv); if (ret) goto out; return 0; return 0; out: out: return ret; return ret; Loading drivers/net/wireless/cnss2/main.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -146,6 +146,7 @@ struct cnss_plat_data { struct wlfw_soc_info_s_v01 soc_info; struct wlfw_soc_info_s_v01 soc_info; struct wlfw_fw_version_info_s_v01 fw_version_info; struct wlfw_fw_version_info_s_v01 fw_version_info; struct cnss_fw_mem fw_mem; struct cnss_fw_mem fw_mem; struct cnss_fw_mem m3_mem; }; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); void *cnss_bus_dev_to_bus_priv(struct device *dev); Loading drivers/net/wireless/cnss2/pci.c +58 −0 Original line number Original line Diff line number Diff line Loading @@ -10,6 +10,7 @@ * GNU General Public License for more details. * GNU General Public License for more details. */ */ #include <linux/firmware.h> #include <linux/module.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> Loading Loading @@ -37,6 +38,9 @@ #define MHI_NODE_NAME "qcom,mhi" #define MHI_NODE_NAME "qcom,mhi" #define MAX_M3_FILE_NAME_LENGTH 13 #define DEFAULT_M3_FILE_NAME "m3.bin" static DEFINE_SPINLOCK(pci_link_down_lock); static DEFINE_SPINLOCK(pci_link_down_lock); static unsigned int pci_link_down_panic; static unsigned int pci_link_down_panic; Loading Loading @@ -657,6 +661,59 @@ static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv) } } } } int cnss_pci_load_m3(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; char filename[MAX_M3_FILE_NAME_LENGTH]; const struct firmware *fw_entry; int ret = 0; if (!m3_mem->va && !m3_mem->size) { snprintf(filename, sizeof(filename), DEFAULT_M3_FILE_NAME); ret = request_firmware(&fw_entry, filename, &pci_priv->pci_dev->dev); if (ret) { cnss_pr_err("Failed to load M3 image: %s\n", filename); return ret; } m3_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev, fw_entry->size, &m3_mem->pa, GFP_KERNEL); if (!m3_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(m3_mem->va, fw_entry->data, fw_entry->size); m3_mem->size = fw_entry->size; release_firmware(fw_entry); } return 0; } static void cnss_pci_free_m3_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; if (m3_mem->va && m3_mem->size) { cnss_pr_dbg("Freeing memory for M3, va: 0x%pK, pa: %pa, size: 0x%zx\n", m3_mem->va, &m3_mem->pa, m3_mem->size); dma_free_coherent(&pci_priv->pci_dev->dev, m3_mem->size, m3_mem->va, m3_mem->pa); } m3_mem->va = NULL; m3_mem->pa = 0; m3_mem->size = 0; } int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, phys_addr_t *pa) phys_addr_t *pa) { { Loading Loading @@ -1261,6 +1318,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev) struct cnss_plat_data *plat_priv = struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(&pci_dev->dev); cnss_bus_dev_to_plat_priv(&pci_dev->dev); cnss_pci_free_m3_mem(pci_priv); cnss_pci_free_fw_mem(pci_priv); cnss_pci_free_fw_mem(pci_priv); if (pci_dev->device == QCA6290_DEVICE_ID) { if (pci_dev->device == QCA6290_DEVICE_ID) { Loading drivers/net/wireless/cnss2/pci.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -123,6 +123,7 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv); int cnss_pci_init(struct cnss_plat_data *plat_priv); int cnss_pci_init(struct cnss_plat_data *plat_priv); void cnss_pci_deinit(struct cnss_plat_data *plat_priv); void cnss_pci_deinit(struct cnss_plat_data *plat_priv); int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv); int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv); int cnss_pci_load_m3(struct cnss_pci_data *pci_priv); int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, phys_addr_t *pa); phys_addr_t *pa); int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, Loading drivers/net/wireless/cnss2/qmi.c +57 −0 Original line number Original line Diff line number Diff line Loading @@ -470,6 +470,63 @@ out: return ret; return ret; } } int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv) { struct wlfw_m3_info_req_msg_v01 req; struct wlfw_m3_info_resp_msg_v01 resp; struct msg_desc req_desc, resp_desc; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; int ret = 0; cnss_pr_dbg("Sending M3 information message, state: 0x%lx\n", plat_priv->driver_state); if (!m3_mem->pa || !m3_mem->size) { cnss_pr_err("Memory for M3 is not available!\n"); ret = -ENOMEM; goto out; } cnss_pr_dbg("M3 memory, va: 0x%pK, pa: %pa, size: 0x%zx\n", m3_mem->va, &m3_mem->pa, m3_mem->size); memset(&req, 0, sizeof(req)); memset(&resp, 0, sizeof(resp)); req.addr = plat_priv->m3_mem.pa; req.size = plat_priv->m3_mem.size; req_desc.max_msg_len = WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_M3_INFO_REQ_V01; req_desc.ei_array = wlfw_m3_info_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_M3_INFO_RESP_V01; resp_desc.ei_array = wlfw_m3_info_resp_msg_v01_ei; ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, &req, sizeof(req), &resp_desc, &resp, sizeof(resp), QMI_WLFW_TIMEOUT_MS); if (ret < 0) { cnss_pr_err("Failed to send M3 information request, err = %d\n", ret); goto out; } if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("M3 information request failed, result: %d, err: %d\n", resp.resp.result, resp.resp.error); ret = resp.resp.result; goto out; } return 0; out: CNSS_ASSERT(0); return ret; } int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum wlfw_driver_mode_enum_v01 mode) enum wlfw_driver_mode_enum_v01 mode) { { Loading Loading
drivers/net/wireless/cnss2/main.c +8 −0 Original line number Original line Diff line number Diff line Loading @@ -420,6 +420,14 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) if (ret) if (ret) goto out; goto out; ret = cnss_pci_load_m3(plat_priv->bus_priv); if (ret) goto out; ret = cnss_wlfw_m3_dnld_send_sync(plat_priv); if (ret) goto out; return 0; return 0; out: out: return ret; return ret; Loading
drivers/net/wireless/cnss2/main.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -146,6 +146,7 @@ struct cnss_plat_data { struct wlfw_soc_info_s_v01 soc_info; struct wlfw_soc_info_s_v01 soc_info; struct wlfw_fw_version_info_s_v01 fw_version_info; struct wlfw_fw_version_info_s_v01 fw_version_info; struct cnss_fw_mem fw_mem; struct cnss_fw_mem fw_mem; struct cnss_fw_mem m3_mem; }; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); void *cnss_bus_dev_to_bus_priv(struct device *dev); Loading
drivers/net/wireless/cnss2/pci.c +58 −0 Original line number Original line Diff line number Diff line Loading @@ -10,6 +10,7 @@ * GNU General Public License for more details. * GNU General Public License for more details. */ */ #include <linux/firmware.h> #include <linux/module.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> Loading Loading @@ -37,6 +38,9 @@ #define MHI_NODE_NAME "qcom,mhi" #define MHI_NODE_NAME "qcom,mhi" #define MAX_M3_FILE_NAME_LENGTH 13 #define DEFAULT_M3_FILE_NAME "m3.bin" static DEFINE_SPINLOCK(pci_link_down_lock); static DEFINE_SPINLOCK(pci_link_down_lock); static unsigned int pci_link_down_panic; static unsigned int pci_link_down_panic; Loading Loading @@ -657,6 +661,59 @@ static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv) } } } } int cnss_pci_load_m3(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; char filename[MAX_M3_FILE_NAME_LENGTH]; const struct firmware *fw_entry; int ret = 0; if (!m3_mem->va && !m3_mem->size) { snprintf(filename, sizeof(filename), DEFAULT_M3_FILE_NAME); ret = request_firmware(&fw_entry, filename, &pci_priv->pci_dev->dev); if (ret) { cnss_pr_err("Failed to load M3 image: %s\n", filename); return ret; } m3_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev, fw_entry->size, &m3_mem->pa, GFP_KERNEL); if (!m3_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(m3_mem->va, fw_entry->data, fw_entry->size); m3_mem->size = fw_entry->size; release_firmware(fw_entry); } return 0; } static void cnss_pci_free_m3_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; if (m3_mem->va && m3_mem->size) { cnss_pr_dbg("Freeing memory for M3, va: 0x%pK, pa: %pa, size: 0x%zx\n", m3_mem->va, &m3_mem->pa, m3_mem->size); dma_free_coherent(&pci_priv->pci_dev->dev, m3_mem->size, m3_mem->va, m3_mem->pa); } m3_mem->va = NULL; m3_mem->pa = 0; m3_mem->size = 0; } int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, phys_addr_t *pa) phys_addr_t *pa) { { Loading Loading @@ -1261,6 +1318,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev) struct cnss_plat_data *plat_priv = struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(&pci_dev->dev); cnss_bus_dev_to_plat_priv(&pci_dev->dev); cnss_pci_free_m3_mem(pci_priv); cnss_pci_free_fw_mem(pci_priv); cnss_pci_free_fw_mem(pci_priv); if (pci_dev->device == QCA6290_DEVICE_ID) { if (pci_dev->device == QCA6290_DEVICE_ID) { Loading
drivers/net/wireless/cnss2/pci.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -123,6 +123,7 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv); int cnss_pci_init(struct cnss_plat_data *plat_priv); int cnss_pci_init(struct cnss_plat_data *plat_priv); void cnss_pci_deinit(struct cnss_plat_data *plat_priv); void cnss_pci_deinit(struct cnss_plat_data *plat_priv); int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv); int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv); int cnss_pci_load_m3(struct cnss_pci_data *pci_priv); int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, phys_addr_t *pa); phys_addr_t *pa); int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, Loading
drivers/net/wireless/cnss2/qmi.c +57 −0 Original line number Original line Diff line number Diff line Loading @@ -470,6 +470,63 @@ out: return ret; return ret; } } int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv) { struct wlfw_m3_info_req_msg_v01 req; struct wlfw_m3_info_resp_msg_v01 resp; struct msg_desc req_desc, resp_desc; struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; int ret = 0; cnss_pr_dbg("Sending M3 information message, state: 0x%lx\n", plat_priv->driver_state); if (!m3_mem->pa || !m3_mem->size) { cnss_pr_err("Memory for M3 is not available!\n"); ret = -ENOMEM; goto out; } cnss_pr_dbg("M3 memory, va: 0x%pK, pa: %pa, size: 0x%zx\n", m3_mem->va, &m3_mem->pa, m3_mem->size); memset(&req, 0, sizeof(req)); memset(&resp, 0, sizeof(resp)); req.addr = plat_priv->m3_mem.pa; req.size = plat_priv->m3_mem.size; req_desc.max_msg_len = WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_M3_INFO_REQ_V01; req_desc.ei_array = wlfw_m3_info_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_M3_INFO_RESP_V01; resp_desc.ei_array = wlfw_m3_info_resp_msg_v01_ei; ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, &req, sizeof(req), &resp_desc, &resp, sizeof(resp), QMI_WLFW_TIMEOUT_MS); if (ret < 0) { cnss_pr_err("Failed to send M3 information request, err = %d\n", ret); goto out; } if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("M3 information request failed, result: %d, err: %d\n", resp.resp.result, resp.resp.error); ret = resp.resp.result; goto out; } return 0; out: CNSS_ASSERT(0); return ret; } int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum wlfw_driver_mode_enum_v01 mode) enum wlfw_driver_mode_enum_v01 mode) { { Loading