Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 164b0ac3 authored by Yue Ma's avatar Yue Ma
Browse files

cnss2: Use PCI dev to allocate firmware memory



Allocate firmware memory using PCI dev so that once SMMU is enabled,
firmware is still able to access the memory through PCIe bus.

Change-Id: If7eb5d9eb5ff51ad7ed791bdd0b732caadccfdfa
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent 96635a1d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -523,6 +523,9 @@ static void cnss_driver_event_work(struct work_struct *work)
			ret = cnss_wlfw_server_exit(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_REQUEST_MEM:
			ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv);
			if (ret)
				break;
			ret = cnss_wlfw_respond_mem_send_sync(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_FW_MEM_READY:
+39 −0
Original line number Diff line number Diff line
@@ -573,6 +573,43 @@ out:
}
EXPORT_SYMBOL(cnss_auto_resume);

int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;

	if (!fw_mem->va && fw_mem->size) {
		fw_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev,
						fw_mem->size, &fw_mem->pa,
						GFP_KERNEL);
		if (!fw_mem->va) {
			cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx\n",
				    fw_mem->size);
			fw_mem->size = 0;

			return -ENOMEM;
		}
	}

	return 0;
}

static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;

	if (fw_mem->va && fw_mem->size) {
		cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n",
			    fw_mem->va, &fw_mem->pa, fw_mem->size);
		dma_free_coherent(&pci_priv->pci_dev->dev, fw_mem->size,
				  fw_mem->va, fw_mem->pa);
		fw_mem->va = NULL;
		fw_mem->pa = 0;
		fw_mem->size = 0;
	}
}

int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va,
			  phys_addr_t *pa)
{
@@ -1177,6 +1214,8 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
	struct cnss_plat_data *plat_priv =
		cnss_bus_dev_to_plat_priv(&pci_dev->dev);

	cnss_pci_free_fw_mem(pci_priv);

	if (pci_dev->device == QCA6290_DEVICE_ID) {
		cnss_pci_unregister_mhi(pci_priv);
		cnss_pci_disable_msi(pci_priv);
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv);
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
int cnss_pci_init(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_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va,
			  phys_addr_t *pa);
int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
+6 −25
Original line number Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, 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
@@ -257,15 +257,9 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
	cnss_pr_dbg("Sending respond memory message, state: 0x%lx\n",
		    plat_priv->driver_state);

	if (!fw_mem->va && fw_mem->size) {
		fw_mem->va = dma_alloc_coherent(&plat_priv->plat_dev->dev,
						fw_mem->size, &fw_mem->pa,
						GFP_KERNEL);
		if (!fw_mem->va) {
			cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx\n",
				    fw_mem->size);
			fw_mem->size = 0;
		}
	if (!fw_mem->pa || !fw_mem->size) {
		cnss_pr_err("Memory for FW is not available!\n");
		goto out;
	}

	cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n",
@@ -274,8 +268,8 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	req.addr = plat_priv->fw_mem.pa;
	req.size = plat_priv->fw_mem.size;
	req.addr = fw_mem->pa;
	req.size = fw_mem->size;

	req_desc.max_msg_len = WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_RESPOND_MEM_REQ_V01;
@@ -676,8 +670,6 @@ err_create_handle:

int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
{
	struct cnss_fw_mem *fw_mem;

	if (!plat_priv)
		return -ENODEV;

@@ -685,17 +677,6 @@ int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
	clear_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state);

	fw_mem = &plat_priv->fw_mem;
	if (fw_mem->va && fw_mem->size) {
		cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n",
			    fw_mem->va, &fw_mem->pa, fw_mem->size);
		dma_free_coherent(&plat_priv->plat_dev->dev, fw_mem->size,
				  fw_mem->va, fw_mem->pa);
		fw_mem->va = NULL;
		fw_mem->pa = 0;
		fw_mem->size = 0;
	}

	cnss_pr_info("QMI WLFW service disconnected, state: 0x%lx\n",
		     plat_priv->driver_state);