18c2ecf20Sopenharmony_ci/******************************************************************* 28c2ecf20Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for * 38c2ecf20Sopenharmony_ci * Fibre Channel Host Bus Adapters. * 48c2ecf20Sopenharmony_ci * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * 58c2ecf20Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * 68c2ecf20Sopenharmony_ci * Copyright (C) 2004-2014 Emulex. All rights reserved. * 78c2ecf20Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex. * 88c2ecf20Sopenharmony_ci * www.broadcom.com * 98c2ecf20Sopenharmony_ci * Portions Copyright (C) 2004-2005 Christoph Hellwig * 108c2ecf20Sopenharmony_ci * * 118c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or * 128c2ecf20Sopenharmony_ci * modify it under the terms of version 2 of the GNU General * 138c2ecf20Sopenharmony_ci * Public License as published by the Free Software Foundation. * 148c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful. * 158c2ecf20Sopenharmony_ci * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * 168c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * 188c2ecf20Sopenharmony_ci * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * 198c2ecf20Sopenharmony_ci * TO BE LEGALLY INVALID. See the GNU General Public License for * 208c2ecf20Sopenharmony_ci * more details, a copy of which can be found in the file COPYING * 218c2ecf20Sopenharmony_ci * included with this package. * 228c2ecf20Sopenharmony_ci *******************************************************************/ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/mempool.h> 258c2ecf20Sopenharmony_ci#include <linux/slab.h> 268c2ecf20Sopenharmony_ci#include <linux/pci.h> 278c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 308c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 318c2ecf20Sopenharmony_ci#include <scsi/scsi_transport_fc.h> 328c2ecf20Sopenharmony_ci#include <scsi/fc/fc_fs.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include "lpfc_hw4.h" 358c2ecf20Sopenharmony_ci#include "lpfc_hw.h" 368c2ecf20Sopenharmony_ci#include "lpfc_sli.h" 378c2ecf20Sopenharmony_ci#include "lpfc_sli4.h" 388c2ecf20Sopenharmony_ci#include "lpfc_nl.h" 398c2ecf20Sopenharmony_ci#include "lpfc_disc.h" 408c2ecf20Sopenharmony_ci#include "lpfc.h" 418c2ecf20Sopenharmony_ci#include "lpfc_scsi.h" 428c2ecf20Sopenharmony_ci#include "lpfc_crtn.h" 438c2ecf20Sopenharmony_ci#include "lpfc_logmsg.h" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ 468c2ecf20Sopenharmony_ci#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ 478c2ecf20Sopenharmony_ci#define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */ 488c2ecf20Sopenharmony_ci#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */ 498c2ecf20Sopenharmony_ci#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */ 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ciint 528c2ecf20Sopenharmony_cilpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { 538c2ecf20Sopenharmony_ci size_t bytes; 548c2ecf20Sopenharmony_ci int max_xri = phba->sli4_hba.max_cfg_param.max_xri; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (max_xri <= 0) 578c2ecf20Sopenharmony_ci return -ENOMEM; 588c2ecf20Sopenharmony_ci bytes = ((BITS_PER_LONG - 1 + max_xri) / BITS_PER_LONG) * 598c2ecf20Sopenharmony_ci sizeof(unsigned long); 608c2ecf20Sopenharmony_ci phba->cfg_rrq_xri_bitmap_sz = bytes; 618c2ecf20Sopenharmony_ci phba->active_rrq_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, 628c2ecf20Sopenharmony_ci bytes); 638c2ecf20Sopenharmony_ci if (!phba->active_rrq_pool) 648c2ecf20Sopenharmony_ci return -ENOMEM; 658c2ecf20Sopenharmony_ci else 668c2ecf20Sopenharmony_ci return 0; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/** 708c2ecf20Sopenharmony_ci * lpfc_mem_alloc - create and allocate all PCI and memory pools 718c2ecf20Sopenharmony_ci * @phba: HBA to allocate pools for 728c2ecf20Sopenharmony_ci * @align: alignment requirement for blocks; must be a power of two 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * Description: Creates and allocates PCI pools lpfc_mbuf_pool, 758c2ecf20Sopenharmony_ci * lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools 768c2ecf20Sopenharmony_ci * for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask. 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. If any 798c2ecf20Sopenharmony_ci * allocation fails, frees all successfully allocated memory before returning. 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * Returns: 828c2ecf20Sopenharmony_ci * 0 on success 838c2ecf20Sopenharmony_ci * -ENOMEM on failure (if any memory allocations fail) 848c2ecf20Sopenharmony_ci **/ 858c2ecf20Sopenharmony_ciint 868c2ecf20Sopenharmony_cilpfc_mem_alloc(struct lpfc_hba *phba, int align) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 898c2ecf20Sopenharmony_ci int i; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci phba->lpfc_mbuf_pool = dma_pool_create("lpfc_mbuf_pool", &phba->pcidev->dev, 938c2ecf20Sopenharmony_ci LPFC_BPL_SIZE, 948c2ecf20Sopenharmony_ci align, 0); 958c2ecf20Sopenharmony_ci if (!phba->lpfc_mbuf_pool) 968c2ecf20Sopenharmony_ci goto fail; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci pool->elements = kmalloc_array(LPFC_MBUF_POOL_SIZE, 998c2ecf20Sopenharmony_ci sizeof(struct lpfc_dmabuf), 1008c2ecf20Sopenharmony_ci GFP_KERNEL); 1018c2ecf20Sopenharmony_ci if (!pool->elements) 1028c2ecf20Sopenharmony_ci goto fail_free_lpfc_mbuf_pool; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci pool->max_count = 0; 1058c2ecf20Sopenharmony_ci pool->current_count = 0; 1068c2ecf20Sopenharmony_ci for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) { 1078c2ecf20Sopenharmony_ci pool->elements[i].virt = dma_pool_alloc(phba->lpfc_mbuf_pool, 1088c2ecf20Sopenharmony_ci GFP_KERNEL, &pool->elements[i].phys); 1098c2ecf20Sopenharmony_ci if (!pool->elements[i].virt) 1108c2ecf20Sopenharmony_ci goto fail_free_mbuf_pool; 1118c2ecf20Sopenharmony_ci pool->max_count++; 1128c2ecf20Sopenharmony_ci pool->current_count++; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MBX_POOL_SIZE, 1168c2ecf20Sopenharmony_ci sizeof(LPFC_MBOXQ_t)); 1178c2ecf20Sopenharmony_ci if (!phba->mbox_mem_pool) 1188c2ecf20Sopenharmony_ci goto fail_free_mbuf_pool; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, 1218c2ecf20Sopenharmony_ci sizeof(struct lpfc_nodelist)); 1228c2ecf20Sopenharmony_ci if (!phba->nlp_mem_pool) 1238c2ecf20Sopenharmony_ci goto fail_free_mbox_pool; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 1268c2ecf20Sopenharmony_ci phba->rrq_pool = 1278c2ecf20Sopenharmony_ci mempool_create_kmalloc_pool(LPFC_RRQ_POOL_SIZE, 1288c2ecf20Sopenharmony_ci sizeof(struct lpfc_node_rrq)); 1298c2ecf20Sopenharmony_ci if (!phba->rrq_pool) 1308c2ecf20Sopenharmony_ci goto fail_free_nlp_mem_pool; 1318c2ecf20Sopenharmony_ci phba->lpfc_hrb_pool = dma_pool_create("lpfc_hrb_pool", 1328c2ecf20Sopenharmony_ci &phba->pcidev->dev, 1338c2ecf20Sopenharmony_ci LPFC_HDR_BUF_SIZE, align, 0); 1348c2ecf20Sopenharmony_ci if (!phba->lpfc_hrb_pool) 1358c2ecf20Sopenharmony_ci goto fail_free_rrq_mem_pool; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci phba->lpfc_drb_pool = dma_pool_create("lpfc_drb_pool", 1388c2ecf20Sopenharmony_ci &phba->pcidev->dev, 1398c2ecf20Sopenharmony_ci LPFC_DATA_BUF_SIZE, align, 0); 1408c2ecf20Sopenharmony_ci if (!phba->lpfc_drb_pool) 1418c2ecf20Sopenharmony_ci goto fail_free_hrb_pool; 1428c2ecf20Sopenharmony_ci phba->lpfc_hbq_pool = NULL; 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci phba->lpfc_hbq_pool = dma_pool_create("lpfc_hbq_pool", 1458c2ecf20Sopenharmony_ci &phba->pcidev->dev, LPFC_BPL_SIZE, align, 0); 1468c2ecf20Sopenharmony_ci if (!phba->lpfc_hbq_pool) 1478c2ecf20Sopenharmony_ci goto fail_free_nlp_mem_pool; 1488c2ecf20Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 1498c2ecf20Sopenharmony_ci phba->lpfc_drb_pool = NULL; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (phba->cfg_EnableXLane) { 1538c2ecf20Sopenharmony_ci phba->device_data_mem_pool = mempool_create_kmalloc_pool( 1548c2ecf20Sopenharmony_ci LPFC_DEVICE_DATA_POOL_SIZE, 1558c2ecf20Sopenharmony_ci sizeof(struct lpfc_device_data)); 1568c2ecf20Sopenharmony_ci if (!phba->device_data_mem_pool) 1578c2ecf20Sopenharmony_ci goto fail_free_drb_pool; 1588c2ecf20Sopenharmony_ci } else { 1598c2ecf20Sopenharmony_ci phba->device_data_mem_pool = NULL; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci return 0; 1638c2ecf20Sopenharmony_cifail_free_drb_pool: 1648c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_drb_pool); 1658c2ecf20Sopenharmony_ci phba->lpfc_drb_pool = NULL; 1668c2ecf20Sopenharmony_ci fail_free_hrb_pool: 1678c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_hrb_pool); 1688c2ecf20Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 1698c2ecf20Sopenharmony_ci fail_free_rrq_mem_pool: 1708c2ecf20Sopenharmony_ci mempool_destroy(phba->rrq_pool); 1718c2ecf20Sopenharmony_ci phba->rrq_pool = NULL; 1728c2ecf20Sopenharmony_ci fail_free_nlp_mem_pool: 1738c2ecf20Sopenharmony_ci mempool_destroy(phba->nlp_mem_pool); 1748c2ecf20Sopenharmony_ci phba->nlp_mem_pool = NULL; 1758c2ecf20Sopenharmony_ci fail_free_mbox_pool: 1768c2ecf20Sopenharmony_ci mempool_destroy(phba->mbox_mem_pool); 1778c2ecf20Sopenharmony_ci phba->mbox_mem_pool = NULL; 1788c2ecf20Sopenharmony_ci fail_free_mbuf_pool: 1798c2ecf20Sopenharmony_ci while (i--) 1808c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 1818c2ecf20Sopenharmony_ci pool->elements[i].phys); 1828c2ecf20Sopenharmony_ci kfree(pool->elements); 1838c2ecf20Sopenharmony_ci fail_free_lpfc_mbuf_pool: 1848c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_mbuf_pool); 1858c2ecf20Sopenharmony_ci phba->lpfc_mbuf_pool = NULL; 1868c2ecf20Sopenharmony_ci fail: 1878c2ecf20Sopenharmony_ci return -ENOMEM; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ciint 1918c2ecf20Sopenharmony_cilpfc_nvmet_mem_alloc(struct lpfc_hba *phba) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci phba->lpfc_nvmet_drb_pool = 1948c2ecf20Sopenharmony_ci dma_pool_create("lpfc_nvmet_drb_pool", 1958c2ecf20Sopenharmony_ci &phba->pcidev->dev, LPFC_NVMET_DATA_BUF_SIZE, 1968c2ecf20Sopenharmony_ci SGL_ALIGN_SZ, 0); 1978c2ecf20Sopenharmony_ci if (!phba->lpfc_nvmet_drb_pool) { 1988c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 1998c2ecf20Sopenharmony_ci "6024 Can't enable NVME Target - no memory\n"); 2008c2ecf20Sopenharmony_ci return -ENOMEM; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci/** 2068c2ecf20Sopenharmony_ci * lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc 2078c2ecf20Sopenharmony_ci * @phba: HBA to free memory for 2088c2ecf20Sopenharmony_ci * 2098c2ecf20Sopenharmony_ci * Description: Free the memory allocated by lpfc_mem_alloc routine. This 2108c2ecf20Sopenharmony_ci * routine is a the counterpart of lpfc_mem_alloc. 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * Returns: None 2138c2ecf20Sopenharmony_ci **/ 2148c2ecf20Sopenharmony_civoid 2158c2ecf20Sopenharmony_cilpfc_mem_free(struct lpfc_hba *phba) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci int i; 2188c2ecf20Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 2198c2ecf20Sopenharmony_ci struct lpfc_device_data *device_data; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* Free HBQ pools */ 2228c2ecf20Sopenharmony_ci lpfc_sli_hbqbuf_free_all(phba); 2238c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_nvmet_drb_pool); 2248c2ecf20Sopenharmony_ci phba->lpfc_nvmet_drb_pool = NULL; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_drb_pool); 2278c2ecf20Sopenharmony_ci phba->lpfc_drb_pool = NULL; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_hrb_pool); 2308c2ecf20Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_hbq_pool); 2338c2ecf20Sopenharmony_ci phba->lpfc_hbq_pool = NULL; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci mempool_destroy(phba->rrq_pool); 2368c2ecf20Sopenharmony_ci phba->rrq_pool = NULL; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* Free NLP memory pool */ 2398c2ecf20Sopenharmony_ci mempool_destroy(phba->nlp_mem_pool); 2408c2ecf20Sopenharmony_ci phba->nlp_mem_pool = NULL; 2418c2ecf20Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) { 2428c2ecf20Sopenharmony_ci mempool_destroy(phba->active_rrq_pool); 2438c2ecf20Sopenharmony_ci phba->active_rrq_pool = NULL; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* Free mbox memory pool */ 2478c2ecf20Sopenharmony_ci mempool_destroy(phba->mbox_mem_pool); 2488c2ecf20Sopenharmony_ci phba->mbox_mem_pool = NULL; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Free MBUF memory pool */ 2518c2ecf20Sopenharmony_ci for (i = 0; i < pool->current_count; i++) 2528c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 2538c2ecf20Sopenharmony_ci pool->elements[i].phys); 2548c2ecf20Sopenharmony_ci kfree(pool->elements); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_mbuf_pool); 2578c2ecf20Sopenharmony_ci phba->lpfc_mbuf_pool = NULL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* Free Device Data memory pool */ 2608c2ecf20Sopenharmony_ci if (phba->device_data_mem_pool) { 2618c2ecf20Sopenharmony_ci /* Ensure all objects have been returned to the pool */ 2628c2ecf20Sopenharmony_ci while (!list_empty(&phba->luns)) { 2638c2ecf20Sopenharmony_ci device_data = list_first_entry(&phba->luns, 2648c2ecf20Sopenharmony_ci struct lpfc_device_data, 2658c2ecf20Sopenharmony_ci listentry); 2668c2ecf20Sopenharmony_ci list_del(&device_data->listentry); 2678c2ecf20Sopenharmony_ci mempool_free(device_data, phba->device_data_mem_pool); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci mempool_destroy(phba->device_data_mem_pool); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci phba->device_data_mem_pool = NULL; 2728c2ecf20Sopenharmony_ci return; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * lpfc_mem_free_all - Frees all PCI and driver memory 2778c2ecf20Sopenharmony_ci * @phba: HBA to free memory for 2788c2ecf20Sopenharmony_ci * 2798c2ecf20Sopenharmony_ci * Description: Free memory from PCI and driver memory pools and also those 2808c2ecf20Sopenharmony_ci * used : lpfc_sg_dma_buf_pool, lpfc_mbuf_pool, lpfc_hrb_pool. Frees 2818c2ecf20Sopenharmony_ci * kmalloc-backed mempools for LPFC_MBOXQ_t and lpfc_nodelist. Also frees 2828c2ecf20Sopenharmony_ci * the VPI bitmask. 2838c2ecf20Sopenharmony_ci * 2848c2ecf20Sopenharmony_ci * Returns: None 2858c2ecf20Sopenharmony_ci **/ 2868c2ecf20Sopenharmony_civoid 2878c2ecf20Sopenharmony_cilpfc_mem_free_all(struct lpfc_hba *phba) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct lpfc_sli *psli = &phba->sli; 2908c2ecf20Sopenharmony_ci LPFC_MBOXQ_t *mbox, *next_mbox; 2918c2ecf20Sopenharmony_ci struct lpfc_dmabuf *mp; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Free memory used in mailbox queue back to mailbox memory pool */ 2948c2ecf20Sopenharmony_ci list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { 2958c2ecf20Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 2968c2ecf20Sopenharmony_ci if (mp) { 2978c2ecf20Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 2988c2ecf20Sopenharmony_ci kfree(mp); 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci list_del(&mbox->list); 3018c2ecf20Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci /* Free memory used in mailbox cmpl list back to mailbox memory pool */ 3048c2ecf20Sopenharmony_ci list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) { 3058c2ecf20Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 3068c2ecf20Sopenharmony_ci if (mp) { 3078c2ecf20Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 3088c2ecf20Sopenharmony_ci kfree(mp); 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci list_del(&mbox->list); 3118c2ecf20Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci /* Free the active mailbox command back to the mailbox memory pool */ 3148c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 3158c2ecf20Sopenharmony_ci psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 3168c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 3178c2ecf20Sopenharmony_ci if (psli->mbox_active) { 3188c2ecf20Sopenharmony_ci mbox = psli->mbox_active; 3198c2ecf20Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 3208c2ecf20Sopenharmony_ci if (mp) { 3218c2ecf20Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 3228c2ecf20Sopenharmony_ci kfree(mp); 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 3258c2ecf20Sopenharmony_ci psli->mbox_active = NULL; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Free and destroy all the allocated memory pools */ 3298c2ecf20Sopenharmony_ci lpfc_mem_free(phba); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Free DMA buffer memory pool */ 3328c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); 3338c2ecf20Sopenharmony_ci phba->lpfc_sg_dma_buf_pool = NULL; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool); 3368c2ecf20Sopenharmony_ci phba->lpfc_cmd_rsp_buf_pool = NULL; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* Free the iocb lookup array */ 3398c2ecf20Sopenharmony_ci kfree(psli->iocbq_lookup); 3408c2ecf20Sopenharmony_ci psli->iocbq_lookup = NULL; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci return; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci/** 3468c2ecf20Sopenharmony_ci * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool 3478c2ecf20Sopenharmony_ci * @phba: HBA which owns the pool to allocate from 3488c2ecf20Sopenharmony_ci * @mem_flags: indicates if this is a priority (MEM_PRI) allocation 3498c2ecf20Sopenharmony_ci * @handle: used to return the DMA-mapped address of the mbuf 3508c2ecf20Sopenharmony_ci * 3518c2ecf20Sopenharmony_ci * Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool. 3528c2ecf20Sopenharmony_ci * Allocates from generic dma_pool_alloc function first and if that fails and 3538c2ecf20Sopenharmony_ci * mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the 3548c2ecf20Sopenharmony_ci * HBA's pool. 3558c2ecf20Sopenharmony_ci * 3568c2ecf20Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. Takes 3578c2ecf20Sopenharmony_ci * phba->hbalock. 3588c2ecf20Sopenharmony_ci * 3598c2ecf20Sopenharmony_ci * Returns: 3608c2ecf20Sopenharmony_ci * pointer to the allocated mbuf on success 3618c2ecf20Sopenharmony_ci * NULL on failure 3628c2ecf20Sopenharmony_ci **/ 3638c2ecf20Sopenharmony_civoid * 3648c2ecf20Sopenharmony_cilpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 3678c2ecf20Sopenharmony_ci unsigned long iflags; 3688c2ecf20Sopenharmony_ci void *ret; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci ret = dma_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, iflags); 3738c2ecf20Sopenharmony_ci if (!ret && (mem_flags & MEM_PRI) && pool->current_count) { 3748c2ecf20Sopenharmony_ci pool->current_count--; 3758c2ecf20Sopenharmony_ci ret = pool->elements[pool->current_count].virt; 3768c2ecf20Sopenharmony_ci *handle = pool->elements[pool->current_count].phys; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, iflags); 3798c2ecf20Sopenharmony_ci return ret; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/** 3838c2ecf20Sopenharmony_ci * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked) 3848c2ecf20Sopenharmony_ci * @phba: HBA which owns the pool to return to 3858c2ecf20Sopenharmony_ci * @virt: mbuf to free 3868c2ecf20Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed 3878c2ecf20Sopenharmony_ci * 3888c2ecf20Sopenharmony_ci * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if 3898c2ecf20Sopenharmony_ci * it is below its max_count, frees the mbuf otherwise. 3908c2ecf20Sopenharmony_ci * 3918c2ecf20Sopenharmony_ci * Notes: Must be called with phba->hbalock held to synchronize access to 3928c2ecf20Sopenharmony_ci * lpfc_mbuf_safety_pool. 3938c2ecf20Sopenharmony_ci * 3948c2ecf20Sopenharmony_ci * Returns: None 3958c2ecf20Sopenharmony_ci **/ 3968c2ecf20Sopenharmony_civoid 3978c2ecf20Sopenharmony_ci__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (pool->current_count < pool->max_count) { 4028c2ecf20Sopenharmony_ci pool->elements[pool->current_count].virt = virt; 4038c2ecf20Sopenharmony_ci pool->elements[pool->current_count].phys = dma; 4048c2ecf20Sopenharmony_ci pool->current_count++; 4058c2ecf20Sopenharmony_ci } else { 4068c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, virt, dma); 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci return; 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci/** 4128c2ecf20Sopenharmony_ci * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked) 4138c2ecf20Sopenharmony_ci * @phba: HBA which owns the pool to return to 4148c2ecf20Sopenharmony_ci * @virt: mbuf to free 4158c2ecf20Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed 4168c2ecf20Sopenharmony_ci * 4178c2ecf20Sopenharmony_ci * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if 4188c2ecf20Sopenharmony_ci * it is below its max_count, frees the mbuf otherwise. 4198c2ecf20Sopenharmony_ci * 4208c2ecf20Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * Returns: None 4238c2ecf20Sopenharmony_ci **/ 4248c2ecf20Sopenharmony_civoid 4258c2ecf20Sopenharmony_cilpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci unsigned long iflags; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, iflags); 4308c2ecf20Sopenharmony_ci __lpfc_mbuf_free(phba, virt, dma); 4318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, iflags); 4328c2ecf20Sopenharmony_ci return; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/** 4368c2ecf20Sopenharmony_ci * lpfc_nvmet_buf_alloc - Allocate an nvmet_buf from the 4378c2ecf20Sopenharmony_ci * lpfc_sg_dma_buf_pool PCI pool 4388c2ecf20Sopenharmony_ci * @phba: HBA which owns the pool to allocate from 4398c2ecf20Sopenharmony_ci * @mem_flags: indicates if this is a priority (MEM_PRI) allocation 4408c2ecf20Sopenharmony_ci * @handle: used to return the DMA-mapped address of the nvmet_buf 4418c2ecf20Sopenharmony_ci * 4428c2ecf20Sopenharmony_ci * Description: Allocates a DMA-mapped buffer from the lpfc_sg_dma_buf_pool 4438c2ecf20Sopenharmony_ci * PCI pool. Allocates from generic dma_pool_alloc function. 4448c2ecf20Sopenharmony_ci * 4458c2ecf20Sopenharmony_ci * Returns: 4468c2ecf20Sopenharmony_ci * pointer to the allocated nvmet_buf on success 4478c2ecf20Sopenharmony_ci * NULL on failure 4488c2ecf20Sopenharmony_ci **/ 4498c2ecf20Sopenharmony_civoid * 4508c2ecf20Sopenharmony_cilpfc_nvmet_buf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci void *ret; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci ret = dma_pool_alloc(phba->lpfc_sg_dma_buf_pool, GFP_KERNEL, handle); 4558c2ecf20Sopenharmony_ci return ret; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci/** 4598c2ecf20Sopenharmony_ci * lpfc_nvmet_buf_free - Free an nvmet_buf from the lpfc_sg_dma_buf_pool 4608c2ecf20Sopenharmony_ci * PCI pool 4618c2ecf20Sopenharmony_ci * @phba: HBA which owns the pool to return to 4628c2ecf20Sopenharmony_ci * @virt: nvmet_buf to free 4638c2ecf20Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_sg_dma_buf_pool to be freed 4648c2ecf20Sopenharmony_ci * 4658c2ecf20Sopenharmony_ci * Returns: None 4668c2ecf20Sopenharmony_ci **/ 4678c2ecf20Sopenharmony_civoid 4688c2ecf20Sopenharmony_cilpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_sg_dma_buf_pool, virt, dma); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/** 4748c2ecf20Sopenharmony_ci * lpfc_els_hbq_alloc - Allocate an HBQ buffer 4758c2ecf20Sopenharmony_ci * @phba: HBA to allocate HBQ buffer for 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hrb_pool PCI 4788c2ecf20Sopenharmony_ci * pool along a non-DMA-mapped container for it. 4798c2ecf20Sopenharmony_ci * 4808c2ecf20Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. 4818c2ecf20Sopenharmony_ci * 4828c2ecf20Sopenharmony_ci * Returns: 4838c2ecf20Sopenharmony_ci * pointer to HBQ on success 4848c2ecf20Sopenharmony_ci * NULL on failure 4858c2ecf20Sopenharmony_ci **/ 4868c2ecf20Sopenharmony_cistruct hbq_dmabuf * 4878c2ecf20Sopenharmony_cilpfc_els_hbq_alloc(struct lpfc_hba *phba) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci struct hbq_dmabuf *hbqbp; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci hbqbp = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); 4928c2ecf20Sopenharmony_ci if (!hbqbp) 4938c2ecf20Sopenharmony_ci return NULL; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci hbqbp->dbuf.virt = dma_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL, 4968c2ecf20Sopenharmony_ci &hbqbp->dbuf.phys); 4978c2ecf20Sopenharmony_ci if (!hbqbp->dbuf.virt) { 4988c2ecf20Sopenharmony_ci kfree(hbqbp); 4998c2ecf20Sopenharmony_ci return NULL; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci hbqbp->total_size = LPFC_BPL_SIZE; 5028c2ecf20Sopenharmony_ci return hbqbp; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/** 5068c2ecf20Sopenharmony_ci * lpfc_els_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc 5078c2ecf20Sopenharmony_ci * @phba: HBA buffer was allocated for 5088c2ecf20Sopenharmony_ci * @hbqbp: HBQ container returned by lpfc_els_hbq_alloc 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffer returned by 5118c2ecf20Sopenharmony_ci * lpfc_els_hbq_alloc. 5128c2ecf20Sopenharmony_ci * 5138c2ecf20Sopenharmony_ci * Notes: Can be called with or without locks held. 5148c2ecf20Sopenharmony_ci * 5158c2ecf20Sopenharmony_ci * Returns: None 5168c2ecf20Sopenharmony_ci **/ 5178c2ecf20Sopenharmony_civoid 5188c2ecf20Sopenharmony_cilpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); 5218c2ecf20Sopenharmony_ci kfree(hbqbp); 5228c2ecf20Sopenharmony_ci return; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci/** 5268c2ecf20Sopenharmony_ci * lpfc_sli4_rb_alloc - Allocate an SLI4 Receive buffer 5278c2ecf20Sopenharmony_ci * @phba: HBA to allocate a receive buffer for 5288c2ecf20Sopenharmony_ci * 5298c2ecf20Sopenharmony_ci * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI 5308c2ecf20Sopenharmony_ci * pool along a non-DMA-mapped container for it. 5318c2ecf20Sopenharmony_ci * 5328c2ecf20Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. 5338c2ecf20Sopenharmony_ci * 5348c2ecf20Sopenharmony_ci * Returns: 5358c2ecf20Sopenharmony_ci * pointer to HBQ on success 5368c2ecf20Sopenharmony_ci * NULL on failure 5378c2ecf20Sopenharmony_ci **/ 5388c2ecf20Sopenharmony_cistruct hbq_dmabuf * 5398c2ecf20Sopenharmony_cilpfc_sli4_rb_alloc(struct lpfc_hba *phba) 5408c2ecf20Sopenharmony_ci{ 5418c2ecf20Sopenharmony_ci struct hbq_dmabuf *dma_buf; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci dma_buf = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); 5448c2ecf20Sopenharmony_ci if (!dma_buf) 5458c2ecf20Sopenharmony_ci return NULL; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci dma_buf->hbuf.virt = dma_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL, 5488c2ecf20Sopenharmony_ci &dma_buf->hbuf.phys); 5498c2ecf20Sopenharmony_ci if (!dma_buf->hbuf.virt) { 5508c2ecf20Sopenharmony_ci kfree(dma_buf); 5518c2ecf20Sopenharmony_ci return NULL; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci dma_buf->dbuf.virt = dma_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL, 5548c2ecf20Sopenharmony_ci &dma_buf->dbuf.phys); 5558c2ecf20Sopenharmony_ci if (!dma_buf->dbuf.virt) { 5568c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt, 5578c2ecf20Sopenharmony_ci dma_buf->hbuf.phys); 5588c2ecf20Sopenharmony_ci kfree(dma_buf); 5598c2ecf20Sopenharmony_ci return NULL; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci dma_buf->total_size = LPFC_DATA_BUF_SIZE; 5628c2ecf20Sopenharmony_ci return dma_buf; 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci/** 5668c2ecf20Sopenharmony_ci * lpfc_sli4_rb_free - Frees a receive buffer 5678c2ecf20Sopenharmony_ci * @phba: HBA buffer was allocated for 5688c2ecf20Sopenharmony_ci * @dmab: DMA Buffer container returned by lpfc_sli4_hbq_alloc 5698c2ecf20Sopenharmony_ci * 5708c2ecf20Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffers returned by 5718c2ecf20Sopenharmony_ci * lpfc_sli4_rb_alloc. 5728c2ecf20Sopenharmony_ci * 5738c2ecf20Sopenharmony_ci * Notes: Can be called with or without locks held. 5748c2ecf20Sopenharmony_ci * 5758c2ecf20Sopenharmony_ci * Returns: None 5768c2ecf20Sopenharmony_ci **/ 5778c2ecf20Sopenharmony_civoid 5788c2ecf20Sopenharmony_cilpfc_sli4_rb_free(struct lpfc_hba *phba, struct hbq_dmabuf *dmab) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys); 5818c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys); 5828c2ecf20Sopenharmony_ci kfree(dmab); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci/** 5868c2ecf20Sopenharmony_ci * lpfc_sli4_nvmet_alloc - Allocate an SLI4 Receive buffer 5878c2ecf20Sopenharmony_ci * @phba: HBA to allocate a receive buffer for 5888c2ecf20Sopenharmony_ci * 5898c2ecf20Sopenharmony_ci * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI 5908c2ecf20Sopenharmony_ci * pool along a non-DMA-mapped container for it. 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * Returns: 5938c2ecf20Sopenharmony_ci * pointer to HBQ on success 5948c2ecf20Sopenharmony_ci * NULL on failure 5958c2ecf20Sopenharmony_ci **/ 5968c2ecf20Sopenharmony_cistruct rqb_dmabuf * 5978c2ecf20Sopenharmony_cilpfc_sli4_nvmet_alloc(struct lpfc_hba *phba) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct rqb_dmabuf *dma_buf; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); 6028c2ecf20Sopenharmony_ci if (!dma_buf) 6038c2ecf20Sopenharmony_ci return NULL; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci dma_buf->hbuf.virt = dma_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL, 6068c2ecf20Sopenharmony_ci &dma_buf->hbuf.phys); 6078c2ecf20Sopenharmony_ci if (!dma_buf->hbuf.virt) { 6088c2ecf20Sopenharmony_ci kfree(dma_buf); 6098c2ecf20Sopenharmony_ci return NULL; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci dma_buf->dbuf.virt = dma_pool_alloc(phba->lpfc_nvmet_drb_pool, 6128c2ecf20Sopenharmony_ci GFP_KERNEL, &dma_buf->dbuf.phys); 6138c2ecf20Sopenharmony_ci if (!dma_buf->dbuf.virt) { 6148c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt, 6158c2ecf20Sopenharmony_ci dma_buf->hbuf.phys); 6168c2ecf20Sopenharmony_ci kfree(dma_buf); 6178c2ecf20Sopenharmony_ci return NULL; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci dma_buf->total_size = LPFC_NVMET_DATA_BUF_SIZE; 6208c2ecf20Sopenharmony_ci return dma_buf; 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci/** 6248c2ecf20Sopenharmony_ci * lpfc_sli4_nvmet_free - Frees a receive buffer 6258c2ecf20Sopenharmony_ci * @phba: HBA buffer was allocated for 6268c2ecf20Sopenharmony_ci * @dmab: DMA Buffer container returned by lpfc_sli4_rbq_alloc 6278c2ecf20Sopenharmony_ci * 6288c2ecf20Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffers returned by 6298c2ecf20Sopenharmony_ci * lpfc_sli4_nvmet_alloc. 6308c2ecf20Sopenharmony_ci * 6318c2ecf20Sopenharmony_ci * Notes: Can be called with or without locks held. 6328c2ecf20Sopenharmony_ci * 6338c2ecf20Sopenharmony_ci * Returns: None 6348c2ecf20Sopenharmony_ci **/ 6358c2ecf20Sopenharmony_civoid 6368c2ecf20Sopenharmony_cilpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys); 6398c2ecf20Sopenharmony_ci dma_pool_free(phba->lpfc_nvmet_drb_pool, 6408c2ecf20Sopenharmony_ci dmab->dbuf.virt, dmab->dbuf.phys); 6418c2ecf20Sopenharmony_ci kfree(dmab); 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci/** 6458c2ecf20Sopenharmony_ci * lpfc_in_buf_free - Free a DMA buffer 6468c2ecf20Sopenharmony_ci * @phba: HBA buffer is associated with 6478c2ecf20Sopenharmony_ci * @mp: Buffer to free 6488c2ecf20Sopenharmony_ci * 6498c2ecf20Sopenharmony_ci * Description: Frees the given DMA buffer in the appropriate way given if the 6508c2ecf20Sopenharmony_ci * HBA is running in SLI3 mode with HBQs enabled. 6518c2ecf20Sopenharmony_ci * 6528c2ecf20Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 6538c2ecf20Sopenharmony_ci * 6548c2ecf20Sopenharmony_ci * Returns: None 6558c2ecf20Sopenharmony_ci **/ 6568c2ecf20Sopenharmony_civoid 6578c2ecf20Sopenharmony_cilpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) 6588c2ecf20Sopenharmony_ci{ 6598c2ecf20Sopenharmony_ci struct hbq_dmabuf *hbq_entry; 6608c2ecf20Sopenharmony_ci unsigned long flags; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (!mp) 6638c2ecf20Sopenharmony_ci return; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { 6668c2ecf20Sopenharmony_ci hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); 6678c2ecf20Sopenharmony_ci /* Check whether HBQ is still in use */ 6688c2ecf20Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, flags); 6698c2ecf20Sopenharmony_ci if (!phba->hbq_in_use) { 6708c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 6718c2ecf20Sopenharmony_ci return; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci list_del(&hbq_entry->dbuf.list); 6748c2ecf20Sopenharmony_ci if (hbq_entry->tag == -1) { 6758c2ecf20Sopenharmony_ci (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) 6768c2ecf20Sopenharmony_ci (phba, hbq_entry); 6778c2ecf20Sopenharmony_ci } else { 6788c2ecf20Sopenharmony_ci lpfc_sli_free_hbq(phba, hbq_entry); 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 6818c2ecf20Sopenharmony_ci } else { 6828c2ecf20Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 6838c2ecf20Sopenharmony_ci kfree(mp); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci return; 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/** 6898c2ecf20Sopenharmony_ci * lpfc_rq_buf_free - Free a RQ DMA buffer 6908c2ecf20Sopenharmony_ci * @phba: HBA buffer is associated with 6918c2ecf20Sopenharmony_ci * @mp: Buffer to free 6928c2ecf20Sopenharmony_ci * 6938c2ecf20Sopenharmony_ci * Description: Frees the given DMA buffer in the appropriate way given by 6948c2ecf20Sopenharmony_ci * reposting it to its associated RQ so it can be reused. 6958c2ecf20Sopenharmony_ci * 6968c2ecf20Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 6978c2ecf20Sopenharmony_ci * 6988c2ecf20Sopenharmony_ci * Returns: None 6998c2ecf20Sopenharmony_ci **/ 7008c2ecf20Sopenharmony_civoid 7018c2ecf20Sopenharmony_cilpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci struct lpfc_rqb *rqbp; 7048c2ecf20Sopenharmony_ci struct lpfc_rqe hrqe; 7058c2ecf20Sopenharmony_ci struct lpfc_rqe drqe; 7068c2ecf20Sopenharmony_ci struct rqb_dmabuf *rqb_entry; 7078c2ecf20Sopenharmony_ci unsigned long flags; 7088c2ecf20Sopenharmony_ci int rc; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (!mp) 7118c2ecf20Sopenharmony_ci return; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci rqb_entry = container_of(mp, struct rqb_dmabuf, hbuf); 7148c2ecf20Sopenharmony_ci rqbp = rqb_entry->hrq->rqbp; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, flags); 7178c2ecf20Sopenharmony_ci list_del(&rqb_entry->hbuf.list); 7188c2ecf20Sopenharmony_ci hrqe.address_lo = putPaddrLow(rqb_entry->hbuf.phys); 7198c2ecf20Sopenharmony_ci hrqe.address_hi = putPaddrHigh(rqb_entry->hbuf.phys); 7208c2ecf20Sopenharmony_ci drqe.address_lo = putPaddrLow(rqb_entry->dbuf.phys); 7218c2ecf20Sopenharmony_ci drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys); 7228c2ecf20Sopenharmony_ci rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe); 7238c2ecf20Sopenharmony_ci if (rc < 0) { 7248c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 7258c2ecf20Sopenharmony_ci "6409 Cannot post to HRQ %d: %x %x %x " 7268c2ecf20Sopenharmony_ci "DRQ %x %x\n", 7278c2ecf20Sopenharmony_ci rqb_entry->hrq->queue_id, 7288c2ecf20Sopenharmony_ci rqb_entry->hrq->host_index, 7298c2ecf20Sopenharmony_ci rqb_entry->hrq->hba_index, 7308c2ecf20Sopenharmony_ci rqb_entry->hrq->entry_count, 7318c2ecf20Sopenharmony_ci rqb_entry->drq->host_index, 7328c2ecf20Sopenharmony_ci rqb_entry->drq->hba_index); 7338c2ecf20Sopenharmony_ci (rqbp->rqb_free_buffer)(phba, rqb_entry); 7348c2ecf20Sopenharmony_ci } else { 7358c2ecf20Sopenharmony_ci list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); 7368c2ecf20Sopenharmony_ci rqbp->buffer_count++; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 7408c2ecf20Sopenharmony_ci} 741