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