162306a36Sopenharmony_ci/******************************************************************* 262306a36Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for * 362306a36Sopenharmony_ci * Fibre Channel Host Bus Adapters. * 462306a36Sopenharmony_ci * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * 562306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * 662306a36Sopenharmony_ci * Copyright (C) 2004-2014 Emulex. All rights reserved. * 762306a36Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex. * 862306a36Sopenharmony_ci * www.broadcom.com * 962306a36Sopenharmony_ci * Portions Copyright (C) 2004-2005 Christoph Hellwig * 1062306a36Sopenharmony_ci * * 1162306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or * 1262306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General * 1362306a36Sopenharmony_ci * Public License as published by the Free Software Foundation. * 1462306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful. * 1562306a36Sopenharmony_ci * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * 1662306a36Sopenharmony_ci * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * 1862306a36Sopenharmony_ci * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * 1962306a36Sopenharmony_ci * TO BE LEGALLY INVALID. See the GNU General Public License for * 2062306a36Sopenharmony_ci * more details, a copy of which can be found in the file COPYING * 2162306a36Sopenharmony_ci * included with this package. * 2262306a36Sopenharmony_ci *******************************************************************/ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/mempool.h> 2562306a36Sopenharmony_ci#include <linux/slab.h> 2662306a36Sopenharmony_ci#include <linux/pci.h> 2762306a36Sopenharmony_ci#include <linux/interrupt.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <scsi/scsi.h> 3062306a36Sopenharmony_ci#include <scsi/scsi_device.h> 3162306a36Sopenharmony_ci#include <scsi/scsi_transport_fc.h> 3262306a36Sopenharmony_ci#include <scsi/fc/fc_fs.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include "lpfc_hw4.h" 3562306a36Sopenharmony_ci#include "lpfc_hw.h" 3662306a36Sopenharmony_ci#include "lpfc_sli.h" 3762306a36Sopenharmony_ci#include "lpfc_sli4.h" 3862306a36Sopenharmony_ci#include "lpfc_nl.h" 3962306a36Sopenharmony_ci#include "lpfc_disc.h" 4062306a36Sopenharmony_ci#include "lpfc.h" 4162306a36Sopenharmony_ci#include "lpfc_scsi.h" 4262306a36Sopenharmony_ci#include "lpfc_crtn.h" 4362306a36Sopenharmony_ci#include "lpfc_logmsg.h" 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ 4662306a36Sopenharmony_ci#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ 4762306a36Sopenharmony_ci#define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */ 4862306a36Sopenharmony_ci#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */ 4962306a36Sopenharmony_ci#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */ 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciint 5262306a36Sopenharmony_cilpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { 5362306a36Sopenharmony_ci size_t bytes; 5462306a36Sopenharmony_ci int max_xri = phba->sli4_hba.max_cfg_param.max_xri; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (max_xri <= 0) 5762306a36Sopenharmony_ci return -ENOMEM; 5862306a36Sopenharmony_ci bytes = ((BITS_PER_LONG - 1 + max_xri) / BITS_PER_LONG) * 5962306a36Sopenharmony_ci sizeof(unsigned long); 6062306a36Sopenharmony_ci phba->cfg_rrq_xri_bitmap_sz = bytes; 6162306a36Sopenharmony_ci phba->active_rrq_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, 6262306a36Sopenharmony_ci bytes); 6362306a36Sopenharmony_ci if (!phba->active_rrq_pool) 6462306a36Sopenharmony_ci return -ENOMEM; 6562306a36Sopenharmony_ci else 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/** 7062306a36Sopenharmony_ci * lpfc_mem_alloc - create and allocate all PCI and memory pools 7162306a36Sopenharmony_ci * @phba: HBA to allocate pools for 7262306a36Sopenharmony_ci * @align: alignment requirement for blocks; must be a power of two 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * Description: Creates and allocates PCI pools lpfc_mbuf_pool, 7562306a36Sopenharmony_ci * lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools 7662306a36Sopenharmony_ci * for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. If any 7962306a36Sopenharmony_ci * allocation fails, frees all successfully allocated memory before returning. 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * Returns: 8262306a36Sopenharmony_ci * 0 on success 8362306a36Sopenharmony_ci * -ENOMEM on failure (if any memory allocations fail) 8462306a36Sopenharmony_ci **/ 8562306a36Sopenharmony_ciint 8662306a36Sopenharmony_cilpfc_mem_alloc(struct lpfc_hba *phba, int align) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 8962306a36Sopenharmony_ci int i; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci phba->lpfc_mbuf_pool = dma_pool_create("lpfc_mbuf_pool", &phba->pcidev->dev, 9362306a36Sopenharmony_ci LPFC_BPL_SIZE, 9462306a36Sopenharmony_ci align, 0); 9562306a36Sopenharmony_ci if (!phba->lpfc_mbuf_pool) 9662306a36Sopenharmony_ci goto fail; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci pool->elements = kmalloc_array(LPFC_MBUF_POOL_SIZE, 9962306a36Sopenharmony_ci sizeof(struct lpfc_dmabuf), 10062306a36Sopenharmony_ci GFP_KERNEL); 10162306a36Sopenharmony_ci if (!pool->elements) 10262306a36Sopenharmony_ci goto fail_free_lpfc_mbuf_pool; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci pool->max_count = 0; 10562306a36Sopenharmony_ci pool->current_count = 0; 10662306a36Sopenharmony_ci for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) { 10762306a36Sopenharmony_ci pool->elements[i].virt = dma_pool_alloc(phba->lpfc_mbuf_pool, 10862306a36Sopenharmony_ci GFP_KERNEL, &pool->elements[i].phys); 10962306a36Sopenharmony_ci if (!pool->elements[i].virt) 11062306a36Sopenharmony_ci goto fail_free_mbuf_pool; 11162306a36Sopenharmony_ci pool->max_count++; 11262306a36Sopenharmony_ci pool->current_count++; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MBX_POOL_SIZE, 11662306a36Sopenharmony_ci sizeof(LPFC_MBOXQ_t)); 11762306a36Sopenharmony_ci if (!phba->mbox_mem_pool) 11862306a36Sopenharmony_ci goto fail_free_mbuf_pool; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, 12162306a36Sopenharmony_ci sizeof(struct lpfc_nodelist)); 12262306a36Sopenharmony_ci if (!phba->nlp_mem_pool) 12362306a36Sopenharmony_ci goto fail_free_mbox_pool; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 12662306a36Sopenharmony_ci phba->rrq_pool = 12762306a36Sopenharmony_ci mempool_create_kmalloc_pool(LPFC_RRQ_POOL_SIZE, 12862306a36Sopenharmony_ci sizeof(struct lpfc_node_rrq)); 12962306a36Sopenharmony_ci if (!phba->rrq_pool) 13062306a36Sopenharmony_ci goto fail_free_nlp_mem_pool; 13162306a36Sopenharmony_ci phba->lpfc_hrb_pool = dma_pool_create("lpfc_hrb_pool", 13262306a36Sopenharmony_ci &phba->pcidev->dev, 13362306a36Sopenharmony_ci LPFC_HDR_BUF_SIZE, align, 0); 13462306a36Sopenharmony_ci if (!phba->lpfc_hrb_pool) 13562306a36Sopenharmony_ci goto fail_free_rrq_mem_pool; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci phba->lpfc_drb_pool = dma_pool_create("lpfc_drb_pool", 13862306a36Sopenharmony_ci &phba->pcidev->dev, 13962306a36Sopenharmony_ci LPFC_DATA_BUF_SIZE, align, 0); 14062306a36Sopenharmony_ci if (!phba->lpfc_drb_pool) 14162306a36Sopenharmony_ci goto fail_free_hrb_pool; 14262306a36Sopenharmony_ci phba->lpfc_hbq_pool = NULL; 14362306a36Sopenharmony_ci } else { 14462306a36Sopenharmony_ci phba->lpfc_hbq_pool = dma_pool_create("lpfc_hbq_pool", 14562306a36Sopenharmony_ci &phba->pcidev->dev, LPFC_BPL_SIZE, align, 0); 14662306a36Sopenharmony_ci if (!phba->lpfc_hbq_pool) 14762306a36Sopenharmony_ci goto fail_free_nlp_mem_pool; 14862306a36Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 14962306a36Sopenharmony_ci phba->lpfc_drb_pool = NULL; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (phba->cfg_EnableXLane) { 15362306a36Sopenharmony_ci phba->device_data_mem_pool = mempool_create_kmalloc_pool( 15462306a36Sopenharmony_ci LPFC_DEVICE_DATA_POOL_SIZE, 15562306a36Sopenharmony_ci sizeof(struct lpfc_device_data)); 15662306a36Sopenharmony_ci if (!phba->device_data_mem_pool) 15762306a36Sopenharmony_ci goto fail_free_drb_pool; 15862306a36Sopenharmony_ci } else { 15962306a36Sopenharmony_ci phba->device_data_mem_pool = NULL; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return 0; 16362306a36Sopenharmony_cifail_free_drb_pool: 16462306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_drb_pool); 16562306a36Sopenharmony_ci phba->lpfc_drb_pool = NULL; 16662306a36Sopenharmony_ci fail_free_hrb_pool: 16762306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_hrb_pool); 16862306a36Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 16962306a36Sopenharmony_ci fail_free_rrq_mem_pool: 17062306a36Sopenharmony_ci mempool_destroy(phba->rrq_pool); 17162306a36Sopenharmony_ci phba->rrq_pool = NULL; 17262306a36Sopenharmony_ci fail_free_nlp_mem_pool: 17362306a36Sopenharmony_ci mempool_destroy(phba->nlp_mem_pool); 17462306a36Sopenharmony_ci phba->nlp_mem_pool = NULL; 17562306a36Sopenharmony_ci fail_free_mbox_pool: 17662306a36Sopenharmony_ci mempool_destroy(phba->mbox_mem_pool); 17762306a36Sopenharmony_ci phba->mbox_mem_pool = NULL; 17862306a36Sopenharmony_ci fail_free_mbuf_pool: 17962306a36Sopenharmony_ci while (i--) 18062306a36Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 18162306a36Sopenharmony_ci pool->elements[i].phys); 18262306a36Sopenharmony_ci kfree(pool->elements); 18362306a36Sopenharmony_ci fail_free_lpfc_mbuf_pool: 18462306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_mbuf_pool); 18562306a36Sopenharmony_ci phba->lpfc_mbuf_pool = NULL; 18662306a36Sopenharmony_ci fail: 18762306a36Sopenharmony_ci return -ENOMEM; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciint 19162306a36Sopenharmony_cilpfc_nvmet_mem_alloc(struct lpfc_hba *phba) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci phba->lpfc_nvmet_drb_pool = 19462306a36Sopenharmony_ci dma_pool_create("lpfc_nvmet_drb_pool", 19562306a36Sopenharmony_ci &phba->pcidev->dev, LPFC_NVMET_DATA_BUF_SIZE, 19662306a36Sopenharmony_ci SGL_ALIGN_SZ, 0); 19762306a36Sopenharmony_ci if (!phba->lpfc_nvmet_drb_pool) { 19862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 19962306a36Sopenharmony_ci "6024 Can't enable NVME Target - no memory\n"); 20062306a36Sopenharmony_ci return -ENOMEM; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/** 20662306a36Sopenharmony_ci * lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc 20762306a36Sopenharmony_ci * @phba: HBA to free memory for 20862306a36Sopenharmony_ci * 20962306a36Sopenharmony_ci * Description: Free the memory allocated by lpfc_mem_alloc routine. This 21062306a36Sopenharmony_ci * routine is a the counterpart of lpfc_mem_alloc. 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * Returns: None 21362306a36Sopenharmony_ci **/ 21462306a36Sopenharmony_civoid 21562306a36Sopenharmony_cilpfc_mem_free(struct lpfc_hba *phba) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci int i; 21862306a36Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 21962306a36Sopenharmony_ci struct lpfc_device_data *device_data; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Free HBQ pools */ 22262306a36Sopenharmony_ci lpfc_sli_hbqbuf_free_all(phba); 22362306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_nvmet_drb_pool); 22462306a36Sopenharmony_ci phba->lpfc_nvmet_drb_pool = NULL; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_drb_pool); 22762306a36Sopenharmony_ci phba->lpfc_drb_pool = NULL; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_hrb_pool); 23062306a36Sopenharmony_ci phba->lpfc_hrb_pool = NULL; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_hbq_pool); 23362306a36Sopenharmony_ci phba->lpfc_hbq_pool = NULL; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci mempool_destroy(phba->rrq_pool); 23662306a36Sopenharmony_ci phba->rrq_pool = NULL; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* Free NLP memory pool */ 23962306a36Sopenharmony_ci mempool_destroy(phba->nlp_mem_pool); 24062306a36Sopenharmony_ci phba->nlp_mem_pool = NULL; 24162306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) { 24262306a36Sopenharmony_ci mempool_destroy(phba->active_rrq_pool); 24362306a36Sopenharmony_ci phba->active_rrq_pool = NULL; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Free mbox memory pool */ 24762306a36Sopenharmony_ci mempool_destroy(phba->mbox_mem_pool); 24862306a36Sopenharmony_ci phba->mbox_mem_pool = NULL; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Free MBUF memory pool */ 25162306a36Sopenharmony_ci for (i = 0; i < pool->current_count; i++) 25262306a36Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 25362306a36Sopenharmony_ci pool->elements[i].phys); 25462306a36Sopenharmony_ci kfree(pool->elements); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_mbuf_pool); 25762306a36Sopenharmony_ci phba->lpfc_mbuf_pool = NULL; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* Free Device Data memory pool */ 26062306a36Sopenharmony_ci if (phba->device_data_mem_pool) { 26162306a36Sopenharmony_ci /* Ensure all objects have been returned to the pool */ 26262306a36Sopenharmony_ci while (!list_empty(&phba->luns)) { 26362306a36Sopenharmony_ci device_data = list_first_entry(&phba->luns, 26462306a36Sopenharmony_ci struct lpfc_device_data, 26562306a36Sopenharmony_ci listentry); 26662306a36Sopenharmony_ci list_del(&device_data->listentry); 26762306a36Sopenharmony_ci mempool_free(device_data, phba->device_data_mem_pool); 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci mempool_destroy(phba->device_data_mem_pool); 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci phba->device_data_mem_pool = NULL; 27262306a36Sopenharmony_ci return; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/** 27662306a36Sopenharmony_ci * lpfc_mem_free_all - Frees all PCI and driver memory 27762306a36Sopenharmony_ci * @phba: HBA to free memory for 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * Description: Free memory from PCI and driver memory pools and also those 28062306a36Sopenharmony_ci * used : lpfc_sg_dma_buf_pool, lpfc_mbuf_pool, lpfc_hrb_pool. Frees 28162306a36Sopenharmony_ci * kmalloc-backed mempools for LPFC_MBOXQ_t and lpfc_nodelist. Also frees 28262306a36Sopenharmony_ci * the VPI bitmask. 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * Returns: None 28562306a36Sopenharmony_ci **/ 28662306a36Sopenharmony_civoid 28762306a36Sopenharmony_cilpfc_mem_free_all(struct lpfc_hba *phba) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct lpfc_sli *psli = &phba->sli; 29062306a36Sopenharmony_ci LPFC_MBOXQ_t *mbox, *next_mbox; 29162306a36Sopenharmony_ci struct lpfc_dmabuf *mp; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Free memory used in mailbox queue back to mailbox memory pool */ 29462306a36Sopenharmony_ci list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { 29562306a36Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 29662306a36Sopenharmony_ci if (mp) { 29762306a36Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 29862306a36Sopenharmony_ci kfree(mp); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci list_del(&mbox->list); 30162306a36Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci /* Free memory used in mailbox cmpl list back to mailbox memory pool */ 30462306a36Sopenharmony_ci list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) { 30562306a36Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 30662306a36Sopenharmony_ci if (mp) { 30762306a36Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 30862306a36Sopenharmony_ci kfree(mp); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci list_del(&mbox->list); 31162306a36Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci /* Free the active mailbox command back to the mailbox memory pool */ 31462306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 31562306a36Sopenharmony_ci psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 31662306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 31762306a36Sopenharmony_ci if (psli->mbox_active) { 31862306a36Sopenharmony_ci mbox = psli->mbox_active; 31962306a36Sopenharmony_ci mp = (struct lpfc_dmabuf *)(mbox->ctx_buf); 32062306a36Sopenharmony_ci if (mp) { 32162306a36Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 32262306a36Sopenharmony_ci kfree(mp); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 32562306a36Sopenharmony_ci psli->mbox_active = NULL; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Free and destroy all the allocated memory pools */ 32962306a36Sopenharmony_ci lpfc_mem_free(phba); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* Free DMA buffer memory pool */ 33262306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); 33362306a36Sopenharmony_ci phba->lpfc_sg_dma_buf_pool = NULL; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool); 33662306a36Sopenharmony_ci phba->lpfc_cmd_rsp_buf_pool = NULL; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* Free Congestion Data buffer */ 33962306a36Sopenharmony_ci if (phba->cgn_i) { 34062306a36Sopenharmony_ci dma_free_coherent(&phba->pcidev->dev, 34162306a36Sopenharmony_ci sizeof(struct lpfc_cgn_info), 34262306a36Sopenharmony_ci phba->cgn_i->virt, phba->cgn_i->phys); 34362306a36Sopenharmony_ci kfree(phba->cgn_i); 34462306a36Sopenharmony_ci phba->cgn_i = NULL; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* Free RX Monitor */ 34862306a36Sopenharmony_ci if (phba->rx_monitor) { 34962306a36Sopenharmony_ci lpfc_rx_monitor_destroy_ring(phba->rx_monitor); 35062306a36Sopenharmony_ci kfree(phba->rx_monitor); 35162306a36Sopenharmony_ci phba->rx_monitor = NULL; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Free the iocb lookup array */ 35562306a36Sopenharmony_ci kfree(psli->iocbq_lookup); 35662306a36Sopenharmony_ci psli->iocbq_lookup = NULL; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci return; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/** 36262306a36Sopenharmony_ci * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool 36362306a36Sopenharmony_ci * @phba: HBA which owns the pool to allocate from 36462306a36Sopenharmony_ci * @mem_flags: indicates if this is a priority (MEM_PRI) allocation 36562306a36Sopenharmony_ci * @handle: used to return the DMA-mapped address of the mbuf 36662306a36Sopenharmony_ci * 36762306a36Sopenharmony_ci * Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool. 36862306a36Sopenharmony_ci * Allocates from generic dma_pool_alloc function first and if that fails and 36962306a36Sopenharmony_ci * mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the 37062306a36Sopenharmony_ci * HBA's pool. 37162306a36Sopenharmony_ci * 37262306a36Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. Takes 37362306a36Sopenharmony_ci * phba->hbalock. 37462306a36Sopenharmony_ci * 37562306a36Sopenharmony_ci * Returns: 37662306a36Sopenharmony_ci * pointer to the allocated mbuf on success 37762306a36Sopenharmony_ci * NULL on failure 37862306a36Sopenharmony_ci **/ 37962306a36Sopenharmony_civoid * 38062306a36Sopenharmony_cilpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 38362306a36Sopenharmony_ci unsigned long iflags; 38462306a36Sopenharmony_ci void *ret; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci ret = dma_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, iflags); 38962306a36Sopenharmony_ci if (!ret && (mem_flags & MEM_PRI) && pool->current_count) { 39062306a36Sopenharmony_ci pool->current_count--; 39162306a36Sopenharmony_ci ret = pool->elements[pool->current_count].virt; 39262306a36Sopenharmony_ci *handle = pool->elements[pool->current_count].phys; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, iflags); 39562306a36Sopenharmony_ci return ret; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci/** 39962306a36Sopenharmony_ci * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked) 40062306a36Sopenharmony_ci * @phba: HBA which owns the pool to return to 40162306a36Sopenharmony_ci * @virt: mbuf to free 40262306a36Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed 40362306a36Sopenharmony_ci * 40462306a36Sopenharmony_ci * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if 40562306a36Sopenharmony_ci * it is below its max_count, frees the mbuf otherwise. 40662306a36Sopenharmony_ci * 40762306a36Sopenharmony_ci * Notes: Must be called with phba->hbalock held to synchronize access to 40862306a36Sopenharmony_ci * lpfc_mbuf_safety_pool. 40962306a36Sopenharmony_ci * 41062306a36Sopenharmony_ci * Returns: None 41162306a36Sopenharmony_ci **/ 41262306a36Sopenharmony_civoid 41362306a36Sopenharmony_ci__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci if (pool->current_count < pool->max_count) { 41862306a36Sopenharmony_ci pool->elements[pool->current_count].virt = virt; 41962306a36Sopenharmony_ci pool->elements[pool->current_count].phys = dma; 42062306a36Sopenharmony_ci pool->current_count++; 42162306a36Sopenharmony_ci } else { 42262306a36Sopenharmony_ci dma_pool_free(phba->lpfc_mbuf_pool, virt, dma); 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci return; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/** 42862306a36Sopenharmony_ci * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked) 42962306a36Sopenharmony_ci * @phba: HBA which owns the pool to return to 43062306a36Sopenharmony_ci * @virt: mbuf to free 43162306a36Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed 43262306a36Sopenharmony_ci * 43362306a36Sopenharmony_ci * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if 43462306a36Sopenharmony_ci * it is below its max_count, frees the mbuf otherwise. 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 43762306a36Sopenharmony_ci * 43862306a36Sopenharmony_ci * Returns: None 43962306a36Sopenharmony_ci **/ 44062306a36Sopenharmony_civoid 44162306a36Sopenharmony_cilpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci unsigned long iflags; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, iflags); 44662306a36Sopenharmony_ci __lpfc_mbuf_free(phba, virt, dma); 44762306a36Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, iflags); 44862306a36Sopenharmony_ci return; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci/** 45262306a36Sopenharmony_ci * lpfc_nvmet_buf_alloc - Allocate an nvmet_buf from the 45362306a36Sopenharmony_ci * lpfc_sg_dma_buf_pool PCI pool 45462306a36Sopenharmony_ci * @phba: HBA which owns the pool to allocate from 45562306a36Sopenharmony_ci * @mem_flags: indicates if this is a priority (MEM_PRI) allocation 45662306a36Sopenharmony_ci * @handle: used to return the DMA-mapped address of the nvmet_buf 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * Description: Allocates a DMA-mapped buffer from the lpfc_sg_dma_buf_pool 45962306a36Sopenharmony_ci * PCI pool. Allocates from generic dma_pool_alloc function. 46062306a36Sopenharmony_ci * 46162306a36Sopenharmony_ci * Returns: 46262306a36Sopenharmony_ci * pointer to the allocated nvmet_buf on success 46362306a36Sopenharmony_ci * NULL on failure 46462306a36Sopenharmony_ci **/ 46562306a36Sopenharmony_civoid * 46662306a36Sopenharmony_cilpfc_nvmet_buf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) 46762306a36Sopenharmony_ci{ 46862306a36Sopenharmony_ci void *ret; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ret = dma_pool_alloc(phba->lpfc_sg_dma_buf_pool, GFP_KERNEL, handle); 47162306a36Sopenharmony_ci return ret; 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/** 47562306a36Sopenharmony_ci * lpfc_nvmet_buf_free - Free an nvmet_buf from the lpfc_sg_dma_buf_pool 47662306a36Sopenharmony_ci * PCI pool 47762306a36Sopenharmony_ci * @phba: HBA which owns the pool to return to 47862306a36Sopenharmony_ci * @virt: nvmet_buf to free 47962306a36Sopenharmony_ci * @dma: the DMA-mapped address of the lpfc_sg_dma_buf_pool to be freed 48062306a36Sopenharmony_ci * 48162306a36Sopenharmony_ci * Returns: None 48262306a36Sopenharmony_ci **/ 48362306a36Sopenharmony_civoid 48462306a36Sopenharmony_cilpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci dma_pool_free(phba->lpfc_sg_dma_buf_pool, virt, dma); 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci/** 49062306a36Sopenharmony_ci * lpfc_els_hbq_alloc - Allocate an HBQ buffer 49162306a36Sopenharmony_ci * @phba: HBA to allocate HBQ buffer for 49262306a36Sopenharmony_ci * 49362306a36Sopenharmony_ci * Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hrb_pool PCI 49462306a36Sopenharmony_ci * pool along a non-DMA-mapped container for it. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. 49762306a36Sopenharmony_ci * 49862306a36Sopenharmony_ci * Returns: 49962306a36Sopenharmony_ci * pointer to HBQ on success 50062306a36Sopenharmony_ci * NULL on failure 50162306a36Sopenharmony_ci **/ 50262306a36Sopenharmony_cistruct hbq_dmabuf * 50362306a36Sopenharmony_cilpfc_els_hbq_alloc(struct lpfc_hba *phba) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci struct hbq_dmabuf *hbqbp; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci hbqbp = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); 50862306a36Sopenharmony_ci if (!hbqbp) 50962306a36Sopenharmony_ci return NULL; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci hbqbp->dbuf.virt = dma_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL, 51262306a36Sopenharmony_ci &hbqbp->dbuf.phys); 51362306a36Sopenharmony_ci if (!hbqbp->dbuf.virt) { 51462306a36Sopenharmony_ci kfree(hbqbp); 51562306a36Sopenharmony_ci return NULL; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci hbqbp->total_size = LPFC_BPL_SIZE; 51862306a36Sopenharmony_ci return hbqbp; 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci/** 52262306a36Sopenharmony_ci * lpfc_els_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc 52362306a36Sopenharmony_ci * @phba: HBA buffer was allocated for 52462306a36Sopenharmony_ci * @hbqbp: HBQ container returned by lpfc_els_hbq_alloc 52562306a36Sopenharmony_ci * 52662306a36Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffer returned by 52762306a36Sopenharmony_ci * lpfc_els_hbq_alloc. 52862306a36Sopenharmony_ci * 52962306a36Sopenharmony_ci * Notes: Can be called with or without locks held. 53062306a36Sopenharmony_ci * 53162306a36Sopenharmony_ci * Returns: None 53262306a36Sopenharmony_ci **/ 53362306a36Sopenharmony_civoid 53462306a36Sopenharmony_cilpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci dma_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); 53762306a36Sopenharmony_ci kfree(hbqbp); 53862306a36Sopenharmony_ci return; 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci/** 54262306a36Sopenharmony_ci * lpfc_sli4_rb_alloc - Allocate an SLI4 Receive buffer 54362306a36Sopenharmony_ci * @phba: HBA to allocate a receive buffer for 54462306a36Sopenharmony_ci * 54562306a36Sopenharmony_ci * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI 54662306a36Sopenharmony_ci * pool along a non-DMA-mapped container for it. 54762306a36Sopenharmony_ci * 54862306a36Sopenharmony_ci * Notes: Not interrupt-safe. Must be called with no locks held. 54962306a36Sopenharmony_ci * 55062306a36Sopenharmony_ci * Returns: 55162306a36Sopenharmony_ci * pointer to HBQ on success 55262306a36Sopenharmony_ci * NULL on failure 55362306a36Sopenharmony_ci **/ 55462306a36Sopenharmony_cistruct hbq_dmabuf * 55562306a36Sopenharmony_cilpfc_sli4_rb_alloc(struct lpfc_hba *phba) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci struct hbq_dmabuf *dma_buf; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci dma_buf = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); 56062306a36Sopenharmony_ci if (!dma_buf) 56162306a36Sopenharmony_ci return NULL; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci dma_buf->hbuf.virt = dma_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL, 56462306a36Sopenharmony_ci &dma_buf->hbuf.phys); 56562306a36Sopenharmony_ci if (!dma_buf->hbuf.virt) { 56662306a36Sopenharmony_ci kfree(dma_buf); 56762306a36Sopenharmony_ci return NULL; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci dma_buf->dbuf.virt = dma_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL, 57062306a36Sopenharmony_ci &dma_buf->dbuf.phys); 57162306a36Sopenharmony_ci if (!dma_buf->dbuf.virt) { 57262306a36Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt, 57362306a36Sopenharmony_ci dma_buf->hbuf.phys); 57462306a36Sopenharmony_ci kfree(dma_buf); 57562306a36Sopenharmony_ci return NULL; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci dma_buf->total_size = LPFC_DATA_BUF_SIZE; 57862306a36Sopenharmony_ci return dma_buf; 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci/** 58262306a36Sopenharmony_ci * lpfc_sli4_rb_free - Frees a receive buffer 58362306a36Sopenharmony_ci * @phba: HBA buffer was allocated for 58462306a36Sopenharmony_ci * @dmab: DMA Buffer container returned by lpfc_sli4_hbq_alloc 58562306a36Sopenharmony_ci * 58662306a36Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffers returned by 58762306a36Sopenharmony_ci * lpfc_sli4_rb_alloc. 58862306a36Sopenharmony_ci * 58962306a36Sopenharmony_ci * Notes: Can be called with or without locks held. 59062306a36Sopenharmony_ci * 59162306a36Sopenharmony_ci * Returns: None 59262306a36Sopenharmony_ci **/ 59362306a36Sopenharmony_civoid 59462306a36Sopenharmony_cilpfc_sli4_rb_free(struct lpfc_hba *phba, struct hbq_dmabuf *dmab) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys); 59762306a36Sopenharmony_ci dma_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys); 59862306a36Sopenharmony_ci kfree(dmab); 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci/** 60262306a36Sopenharmony_ci * lpfc_sli4_nvmet_alloc - Allocate an SLI4 Receive buffer 60362306a36Sopenharmony_ci * @phba: HBA to allocate a receive buffer for 60462306a36Sopenharmony_ci * 60562306a36Sopenharmony_ci * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI 60662306a36Sopenharmony_ci * pool along a non-DMA-mapped container for it. 60762306a36Sopenharmony_ci * 60862306a36Sopenharmony_ci * Returns: 60962306a36Sopenharmony_ci * pointer to HBQ on success 61062306a36Sopenharmony_ci * NULL on failure 61162306a36Sopenharmony_ci **/ 61262306a36Sopenharmony_cistruct rqb_dmabuf * 61362306a36Sopenharmony_cilpfc_sli4_nvmet_alloc(struct lpfc_hba *phba) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci struct rqb_dmabuf *dma_buf; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); 61862306a36Sopenharmony_ci if (!dma_buf) 61962306a36Sopenharmony_ci return NULL; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci dma_buf->hbuf.virt = dma_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL, 62262306a36Sopenharmony_ci &dma_buf->hbuf.phys); 62362306a36Sopenharmony_ci if (!dma_buf->hbuf.virt) { 62462306a36Sopenharmony_ci kfree(dma_buf); 62562306a36Sopenharmony_ci return NULL; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci dma_buf->dbuf.virt = dma_pool_alloc(phba->lpfc_nvmet_drb_pool, 62862306a36Sopenharmony_ci GFP_KERNEL, &dma_buf->dbuf.phys); 62962306a36Sopenharmony_ci if (!dma_buf->dbuf.virt) { 63062306a36Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt, 63162306a36Sopenharmony_ci dma_buf->hbuf.phys); 63262306a36Sopenharmony_ci kfree(dma_buf); 63362306a36Sopenharmony_ci return NULL; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci dma_buf->total_size = LPFC_NVMET_DATA_BUF_SIZE; 63662306a36Sopenharmony_ci return dma_buf; 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci/** 64062306a36Sopenharmony_ci * lpfc_sli4_nvmet_free - Frees a receive buffer 64162306a36Sopenharmony_ci * @phba: HBA buffer was allocated for 64262306a36Sopenharmony_ci * @dmab: DMA Buffer container returned by lpfc_sli4_rbq_alloc 64362306a36Sopenharmony_ci * 64462306a36Sopenharmony_ci * Description: Frees both the container and the DMA-mapped buffers returned by 64562306a36Sopenharmony_ci * lpfc_sli4_nvmet_alloc. 64662306a36Sopenharmony_ci * 64762306a36Sopenharmony_ci * Notes: Can be called with or without locks held. 64862306a36Sopenharmony_ci * 64962306a36Sopenharmony_ci * Returns: None 65062306a36Sopenharmony_ci **/ 65162306a36Sopenharmony_civoid 65262306a36Sopenharmony_cilpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys); 65562306a36Sopenharmony_ci dma_pool_free(phba->lpfc_nvmet_drb_pool, 65662306a36Sopenharmony_ci dmab->dbuf.virt, dmab->dbuf.phys); 65762306a36Sopenharmony_ci kfree(dmab); 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci/** 66162306a36Sopenharmony_ci * lpfc_in_buf_free - Free a DMA buffer 66262306a36Sopenharmony_ci * @phba: HBA buffer is associated with 66362306a36Sopenharmony_ci * @mp: Buffer to free 66462306a36Sopenharmony_ci * 66562306a36Sopenharmony_ci * Description: Frees the given DMA buffer in the appropriate way given if the 66662306a36Sopenharmony_ci * HBA is running in SLI3 mode with HBQs enabled. 66762306a36Sopenharmony_ci * 66862306a36Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 66962306a36Sopenharmony_ci * 67062306a36Sopenharmony_ci * Returns: None 67162306a36Sopenharmony_ci **/ 67262306a36Sopenharmony_civoid 67362306a36Sopenharmony_cilpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci struct hbq_dmabuf *hbq_entry; 67662306a36Sopenharmony_ci unsigned long flags; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci if (!mp) 67962306a36Sopenharmony_ci return; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { 68262306a36Sopenharmony_ci hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); 68362306a36Sopenharmony_ci /* Check whether HBQ is still in use */ 68462306a36Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, flags); 68562306a36Sopenharmony_ci if (!phba->hbq_in_use) { 68662306a36Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 68762306a36Sopenharmony_ci return; 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci list_del(&hbq_entry->dbuf.list); 69062306a36Sopenharmony_ci if (hbq_entry->tag == -1) { 69162306a36Sopenharmony_ci (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) 69262306a36Sopenharmony_ci (phba, hbq_entry); 69362306a36Sopenharmony_ci } else { 69462306a36Sopenharmony_ci lpfc_sli_free_hbq(phba, hbq_entry); 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 69762306a36Sopenharmony_ci } else { 69862306a36Sopenharmony_ci lpfc_mbuf_free(phba, mp->virt, mp->phys); 69962306a36Sopenharmony_ci kfree(mp); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci return; 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci/** 70562306a36Sopenharmony_ci * lpfc_rq_buf_free - Free a RQ DMA buffer 70662306a36Sopenharmony_ci * @phba: HBA buffer is associated with 70762306a36Sopenharmony_ci * @mp: Buffer to free 70862306a36Sopenharmony_ci * 70962306a36Sopenharmony_ci * Description: Frees the given DMA buffer in the appropriate way given by 71062306a36Sopenharmony_ci * reposting it to its associated RQ so it can be reused. 71162306a36Sopenharmony_ci * 71262306a36Sopenharmony_ci * Notes: Takes phba->hbalock. Can be called with or without other locks held. 71362306a36Sopenharmony_ci * 71462306a36Sopenharmony_ci * Returns: None 71562306a36Sopenharmony_ci **/ 71662306a36Sopenharmony_civoid 71762306a36Sopenharmony_cilpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci struct lpfc_rqb *rqbp; 72062306a36Sopenharmony_ci struct lpfc_rqe hrqe; 72162306a36Sopenharmony_ci struct lpfc_rqe drqe; 72262306a36Sopenharmony_ci struct rqb_dmabuf *rqb_entry; 72362306a36Sopenharmony_ci unsigned long flags; 72462306a36Sopenharmony_ci int rc; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (!mp) 72762306a36Sopenharmony_ci return; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci rqb_entry = container_of(mp, struct rqb_dmabuf, hbuf); 73062306a36Sopenharmony_ci rqbp = rqb_entry->hrq->rqbp; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci spin_lock_irqsave(&phba->hbalock, flags); 73362306a36Sopenharmony_ci list_del(&rqb_entry->hbuf.list); 73462306a36Sopenharmony_ci hrqe.address_lo = putPaddrLow(rqb_entry->hbuf.phys); 73562306a36Sopenharmony_ci hrqe.address_hi = putPaddrHigh(rqb_entry->hbuf.phys); 73662306a36Sopenharmony_ci drqe.address_lo = putPaddrLow(rqb_entry->dbuf.phys); 73762306a36Sopenharmony_ci drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys); 73862306a36Sopenharmony_ci rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe); 73962306a36Sopenharmony_ci if (rc < 0) { 74062306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 74162306a36Sopenharmony_ci "6409 Cannot post to HRQ %d: %x %x %x " 74262306a36Sopenharmony_ci "DRQ %x %x\n", 74362306a36Sopenharmony_ci rqb_entry->hrq->queue_id, 74462306a36Sopenharmony_ci rqb_entry->hrq->host_index, 74562306a36Sopenharmony_ci rqb_entry->hrq->hba_index, 74662306a36Sopenharmony_ci rqb_entry->hrq->entry_count, 74762306a36Sopenharmony_ci rqb_entry->drq->host_index, 74862306a36Sopenharmony_ci rqb_entry->drq->hba_index); 74962306a36Sopenharmony_ci (rqbp->rqb_free_buffer)(phba, rqb_entry); 75062306a36Sopenharmony_ci } else { 75162306a36Sopenharmony_ci list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); 75262306a36Sopenharmony_ci rqbp->buffer_count++; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci spin_unlock_irqrestore(&phba->hbalock, flags); 75662306a36Sopenharmony_ci} 757