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