diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 6e4530cdd0db..4b8f78da518d 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ #include #include @@ -3984,15 +3986,27 @@ int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { if (!fw_mem[i].va && fw_mem[i].size) { +retry: fw_mem[i].va = dma_alloc_attrs(dev, fw_mem[i].size, &fw_mem[i].pa, GFP_KERNEL, fw_mem[i].attrs); if (!fw_mem[i].va) { + if ((fw_mem[i].attrs & + DMA_ATTR_FORCE_CONTIGUOUS)) { + fw_mem[i].attrs &= + ~DMA_ATTR_FORCE_CONTIGUOUS; + + cnss_pr_dbg("Fallback to non-contiguous memory for FW, Mem type: %u\n", + fw_mem[i].type); + goto retry; + } + cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx, type: %u\n", fw_mem[i].size, fw_mem[i].type); - BUG(); + CNSS_ASSERT(0); + return -ENOMEM; } } } @@ -5083,17 +5097,21 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic) mhi_dump_sfr(pci_priv->mhi_ctrl); - cnss_pr_dbg("Collect remote heap dump segment\n"); - for (i = 0, j = 0; i < plat_priv->fw_mem_seg_len; i++) { if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) { - cnss_pci_add_dump_seg(pci_priv, dump_seg, - CNSS_FW_REMOTE_HEAP, j, - fw_mem[i].va, fw_mem[i].pa, - fw_mem[i].size); - dump_seg++; - dump_data->nentries++; - j++; + if (fw_mem[i].attrs & DMA_ATTR_FORCE_CONTIGUOUS) { + cnss_pr_dbg("Collect remote heap dump segment\n"); + cnss_pci_add_dump_seg(pci_priv, dump_seg, + CNSS_FW_REMOTE_HEAP, j, + fw_mem[i].va, + fw_mem[i].pa, + fw_mem[i].size); + dump_seg++; + dump_data->nentries++; + j++; + } else { + cnss_pr_dbg("Skip remote heap dumps as it is non-contiguous\n"); + } } } @@ -5138,7 +5156,8 @@ void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv) } for (i = 0, j = 0; i < plat_priv->fw_mem_seg_len; i++) { - if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) { + if (fw_mem[i].type == CNSS_MEM_TYPE_DDR && + (fw_mem[i].attrs & DMA_ATTR_FORCE_CONTIGUOUS)) { cnss_pci_remove_dump_seg(pci_priv, dump_seg, CNSS_FW_REMOTE_HEAP, j, fw_mem[i].va, fw_mem[i].pa, diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index d0f85455de8e..157c90506d30 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ #include #include @@ -2206,7 +2208,8 @@ static void cnss_wlfw_request_mem_ind_cb(struct qmi_handle *qmi_wlfw, ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type); plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type; plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size; - if (plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR) + if (!plat_priv->fw_mem[i].va && + plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR) plat_priv->fw_mem[i].attrs |= DMA_ATTR_FORCE_CONTIGUOUS; }