lpfc_mem.c revision 19ca760979e4be41a3eb215fb8d0e96637161947
1dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>/*******************************************************************
2dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> * This file is part of the Emulex Linux Device Driver for         *
3c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * Fibre Channel Host Bus Adapters.                                *
4d8e93df13c8f7bde45a7756944aab528c58df4cfJames Smart * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
5c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * EMULEX and SLI are trademarks of Emulex.                        *
6dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> * www.emulex.com                                                  *
7c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
8dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> *                                                                 *
9dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> * This program is free software; you can redistribute it and/or   *
10c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * modify it under the terms of version 2 of the GNU General       *
11c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * Public License as published by the Free Software Foundation.    *
12c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * This program is distributed in the hope that it will be useful. *
13c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
14c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
15c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
16c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
18c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * more details, a copy of which can be found in the file COPYING  *
19c44ce1737438d20ac58e808897e3f8eb015c66d3James.Smart@Emulex.Com * included with this package.                                     *
20dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> *******************************************************************/
21dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
22dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include <linux/mempool.h>
235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
24dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include <linux/pci.h>
25dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include <linux/interrupt.h>
26dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
27f888ba3ce77c66bece3d804caf7d559838209a4aJames.Smart@Emulex.Com#include <scsi/scsi_device.h>
28f888ba3ce77c66bece3d804caf7d559838209a4aJames.Smart@Emulex.Com#include <scsi/scsi_transport_fc.h>
29f888ba3ce77c66bece3d804caf7d559838209a4aJames.Smart@Emulex.Com
30918865230e55b1fece2d8edec39d46c00626590bJames.Smart@Emulex.Com#include <scsi/scsi.h>
31918865230e55b1fece2d8edec39d46c00626590bJames.Smart@Emulex.Com
32da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart#include "lpfc_hw4.h"
33dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc_hw.h"
34dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc_sli.h"
35da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart#include "lpfc_sli4.h"
36ea2151b4e142fa2de0319d9dd80413a997bf435aJames Smart#include "lpfc_nl.h"
37dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc_disc.h"
38dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc_scsi.h"
39dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc.h"
40dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#include "lpfc_crtn.h"
41dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
42dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#define LPFC_MBUF_POOL_SIZE     64      /* max elements in MBUF safety pool */
43dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>#define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
44dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
452e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart
46e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
473621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * lpfc_mem_alloc - create and allocate all PCI and memory pools
48e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA to allocate pools for
49e59058c44025d71c9b7f260076a932935d3bba95James Smart *
50e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
51da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_mbuf_pool, lpfc_hrb_pool.  Creates and allocates kmalloc-backed mempools
52e59058c44025d71c9b7f260076a932935d3bba95James Smart * for LPFC_MBOXQ_t and lpfc_nodelist.  Also allocates the VPI bitmask.
53e59058c44025d71c9b7f260076a932935d3bba95James Smart *
54e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Not interrupt-safe.  Must be called with no locks held.  If any
55e59058c44025d71c9b7f260076a932935d3bba95James Smart * allocation fails, frees all successfully allocated memory before returning.
56e59058c44025d71c9b7f260076a932935d3bba95James Smart *
57e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns:
58e59058c44025d71c9b7f260076a932935d3bba95James Smart *   0 on success
59e59058c44025d71c9b7f260076a932935d3bba95James Smart *   -ENOMEM on failure (if any memory allocations fail)
60e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
61dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>int
62da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartlpfc_mem_alloc(struct lpfc_hba *phba, int align)
63dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>{
64dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
6592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	int longs;
66dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	int i;
67dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
68da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	if (phba->sli_rev == LPFC_SLI_REV4)
69da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		phba->lpfc_scsi_dma_buf_pool =
70da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart			pci_pool_create("lpfc_scsi_dma_buf_pool",
71da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				phba->pcidev,
72da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				phba->cfg_sg_dma_buf_size,
73da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				phba->cfg_sg_dma_buf_size,
74da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				0);
75da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	else
76da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		phba->lpfc_scsi_dma_buf_pool =
77da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart			pci_pool_create("lpfc_scsi_dma_buf_pool",
78da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				phba->pcidev, phba->cfg_sg_dma_buf_size,
79da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart				align, 0);
80dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (!phba->lpfc_scsi_dma_buf_pool)
81dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		goto fail;
82dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
83dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	phba->lpfc_mbuf_pool = pci_pool_create("lpfc_mbuf_pool", phba->pcidev,
84da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart							LPFC_BPL_SIZE,
85da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart							align, 0);
86dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (!phba->lpfc_mbuf_pool)
87dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		goto fail_free_dma_buf_pool;
88dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
89dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
90dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>					 LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
91a96e0c7798057dd8055d0263c076fed975c10237Mariusz Kozlowski	if (!pool->elements)
92a96e0c7798057dd8055d0263c076fed975c10237Mariusz Kozlowski		goto fail_free_lpfc_mbuf_pool;
93a96e0c7798057dd8055d0263c076fed975c10237Mariusz Kozlowski
94dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	pool->max_count = 0;
95dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	pool->current_count = 0;
96dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
97dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->elements[i].virt = pci_pool_alloc(phba->lpfc_mbuf_pool,
98dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>				       GFP_KERNEL, &pool->elements[i].phys);
99dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		if (!pool->elements[i].virt)
100dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>			goto fail_free_mbuf_pool;
101dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->max_count++;
102dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->current_count++;
103dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	}
104dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
1050eaae62abaa1ad1f231932b6cdd9fb1b91df6651Matthew Dobson	phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
1060eaae62abaa1ad1f231932b6cdd9fb1b91df6651Matthew Dobson							 sizeof(LPFC_MBOXQ_t));
107dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (!phba->mbox_mem_pool)
108dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		goto fail_free_mbuf_pool;
109dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
1100eaae62abaa1ad1f231932b6cdd9fb1b91df6651Matthew Dobson	phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
1110eaae62abaa1ad1f231932b6cdd9fb1b91df6651Matthew Dobson						sizeof(struct lpfc_nodelist));
112dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (!phba->nlp_mem_pool)
113dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		goto fail_free_mbox_pool;
1148568a4d2495ebcf5da38a2141c7633399143b1a5James Smart
1158568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	if (phba->sli_rev == LPFC_SLI_REV4) {
11619ca760979e4be41a3eb215fb8d0e96637161947James Smart		phba->rrq_pool =
11719ca760979e4be41a3eb215fb8d0e96637161947James Smart			mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
11819ca760979e4be41a3eb215fb8d0e96637161947James Smart						sizeof(struct lpfc_node_rrq));
11919ca760979e4be41a3eb215fb8d0e96637161947James Smart		if (!phba->rrq_pool)
12019ca760979e4be41a3eb215fb8d0e96637161947James Smart			goto fail_free_nlp_mem_pool;
1218568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool",
122da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					      phba->pcidev,
123da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					      LPFC_HDR_BUF_SIZE, align, 0);
1248568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		if (!phba->lpfc_hrb_pool)
12519ca760979e4be41a3eb215fb8d0e96637161947James Smart			goto fail_free_rrq_mem_pool;
1268568a4d2495ebcf5da38a2141c7633399143b1a5James Smart
1278568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool",
128da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					      phba->pcidev,
129da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					      LPFC_DATA_BUF_SIZE, align, 0);
1308568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		if (!phba->lpfc_drb_pool)
1318568a4d2495ebcf5da38a2141c7633399143b1a5James Smart			goto fail_free_hrb_pool;
1328568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_hbq_pool = NULL;
1338568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	} else {
1348568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",
1358568a4d2495ebcf5da38a2141c7633399143b1a5James Smart			phba->pcidev, LPFC_BPL_SIZE, align, 0);
1368568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		if (!phba->lpfc_hbq_pool)
1378568a4d2495ebcf5da38a2141c7633399143b1a5James Smart			goto fail_free_nlp_mem_pool;
1388568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_hrb_pool = NULL;
1398568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		phba->lpfc_drb_pool = NULL;
1408568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	}
141858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8James Smart	/* vpi zero is reserved for the physical port so add 1 to max */
142858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8James Smart	longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
14392d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
14492d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	if (!phba->vpi_bmask)
145da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		goto fail_free_dbq_pool;
14692d7f7b0cde3ad2260e7462b40867b57efd49851James Smart
147dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	return 0;
148dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
149da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart fail_free_dbq_pool:
150da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_destroy(phba->lpfc_drb_pool);
151da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_drb_pool = NULL;
1528568a4d2495ebcf5da38a2141c7633399143b1a5James Smart fail_free_hrb_pool:
153da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_destroy(phba->lpfc_hrb_pool);
154da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_hrb_pool = NULL;
15519ca760979e4be41a3eb215fb8d0e96637161947James Smart fail_free_rrq_mem_pool:
15619ca760979e4be41a3eb215fb8d0e96637161947James Smart	mempool_destroy(phba->rrq_pool);
15719ca760979e4be41a3eb215fb8d0e96637161947James Smart	phba->rrq_pool = NULL;
158ed957684294618602b48f1950b0c9bbcb036583fJames Smart fail_free_nlp_mem_pool:
159ed957684294618602b48f1950b0c9bbcb036583fJames Smart	mempool_destroy(phba->nlp_mem_pool);
160ed957684294618602b48f1950b0c9bbcb036583fJames Smart	phba->nlp_mem_pool = NULL;
161dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> fail_free_mbox_pool:
162dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	mempool_destroy(phba->mbox_mem_pool);
1632e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	phba->mbox_mem_pool = NULL;
164dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> fail_free_mbuf_pool:
165a96e0c7798057dd8055d0263c076fed975c10237Mariusz Kozlowski	while (i--)
166dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
167dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>						 pool->elements[i].phys);
168dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	kfree(pool->elements);
169a96e0c7798057dd8055d0263c076fed975c10237Mariusz Kozlowski fail_free_lpfc_mbuf_pool:
170dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	pci_pool_destroy(phba->lpfc_mbuf_pool);
1712e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	phba->lpfc_mbuf_pool = NULL;
172dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> fail_free_dma_buf_pool:
173dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
1742e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	phba->lpfc_scsi_dma_buf_pool = NULL;
175dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com> fail:
176dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	return -ENOMEM;
177dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>}
178dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
179e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
180da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc
181e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA to free memory for
182e59058c44025d71c9b7f260076a932935d3bba95James Smart *
183da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Description: Free the memory allocated by lpfc_mem_alloc routine. This
184da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * routine is a the counterpart of lpfc_mem_alloc.
185e59058c44025d71c9b7f260076a932935d3bba95James Smart *
186e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns: None
187e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
188dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>void
189da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartlpfc_mem_free(struct lpfc_hba *phba)
190dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>{
191dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	int i;
192da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
193dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
194da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free VPI bitmask memory */
19592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	kfree(phba->vpi_bmask);
196da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
197da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free HBQ pools */
198ed957684294618602b48f1950b0c9bbcb036583fJames Smart	lpfc_sli_hbqbuf_free_all(phba);
1998568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	if (phba->lpfc_drb_pool)
2008568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		pci_pool_destroy(phba->lpfc_drb_pool);
201da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_drb_pool = NULL;
2028568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	if (phba->lpfc_hrb_pool)
2038568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		pci_pool_destroy(phba->lpfc_hrb_pool);
204da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_hrb_pool = NULL;
205da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
2068568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	if (phba->lpfc_hbq_pool)
2078568a4d2495ebcf5da38a2141c7633399143b1a5James Smart		pci_pool_destroy(phba->lpfc_hbq_pool);
2088568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	phba->lpfc_hbq_pool = NULL;
2098568a4d2495ebcf5da38a2141c7633399143b1a5James Smart
210da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free NLP memory pool */
211da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	mempool_destroy(phba->nlp_mem_pool);
212da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->nlp_mem_pool = NULL;
213da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
214da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free mbox memory pool */
215da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	mempool_destroy(phba->mbox_mem_pool);
216da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->mbox_mem_pool = NULL;
217da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
218da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free MBUF memory pool */
219da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	for (i = 0; i < pool->current_count; i++)
220da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
221da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart			      pool->elements[i].phys);
222da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	kfree(pool->elements);
223da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
224da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_destroy(phba->lpfc_mbuf_pool);
225da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_mbuf_pool = NULL;
226ed957684294618602b48f1950b0c9bbcb036583fJames Smart
227da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free DMA buffer memory pool */
228da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
229da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	phba->lpfc_scsi_dma_buf_pool = NULL;
230da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
231da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	return;
232da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart}
233da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
234da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart/**
235da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_mem_free_all - Frees all PCI and driver memory
236da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * @phba: HBA to free memory for
237da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
238da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Description: Free memory from PCI and driver memory pools and also those
239da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * used : lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool, lpfc_hrb_pool. Frees
240da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * kmalloc-backed mempools for LPFC_MBOXQ_t and lpfc_nodelist. Also frees
241da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * the VPI bitmask.
242da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
243da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Returns: None
244da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart **/
245da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartvoid
246da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartlpfc_mem_free_all(struct lpfc_hba *phba)
247da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart{
248da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	struct lpfc_sli *psli = &phba->sli;
249da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	LPFC_MBOXQ_t *mbox, *next_mbox;
250da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	struct lpfc_dmabuf   *mp;
251da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
252da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free memory used in mailbox queue back to mailbox memory pool */
253dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
254dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		mp = (struct lpfc_dmabuf *) (mbox->context1);
255dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		if (mp) {
256dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>			lpfc_mbuf_free(phba, mp->virt, mp->phys);
257dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>			kfree(mp);
258dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		}
259dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		list_del(&mbox->list);
260dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		mempool_free(mbox, phba->mbox_mem_pool);
261dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	}
262da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free memory used in mailbox cmpl list back to mailbox memory pool */
26392d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
26492d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		mp = (struct lpfc_dmabuf *) (mbox->context1);
26592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		if (mp) {
26692d7f7b0cde3ad2260e7462b40867b57efd49851James Smart			lpfc_mbuf_free(phba, mp->virt, mp->phys);
26792d7f7b0cde3ad2260e7462b40867b57efd49851James Smart			kfree(mp);
26892d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		}
26992d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		list_del(&mbox->list);
27092d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		mempool_free(mbox, phba->mbox_mem_pool);
27192d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	}
272da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free the active mailbox command back to the mailbox memory pool */
273da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	spin_lock_irq(&phba->hbalock);
274dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
275da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	spin_unlock_irq(&phba->hbalock);
276dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (psli->mbox_active) {
277dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		mbox = psli->mbox_active;
278dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		mp = (struct lpfc_dmabuf *) (mbox->context1);
279dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		if (mp) {
280dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>			lpfc_mbuf_free(phba, mp->virt, mp->phys);
281dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>			kfree(mp);
282dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		}
283dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		mempool_free(mbox, phba->mbox_mem_pool);
284dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		psli->mbox_active = NULL;
285dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	}
286dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
287da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	/* Free and destroy all the allocated memory pools */
288da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	lpfc_mem_free(phba);
2892e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart
290e59058c44025d71c9b7f260076a932935d3bba95James Smart	/* Free the iocb lookup array */
2919f49d3b05f092b89e774be20c654ceb0c64a7d19James Smart	kfree(psli->iocbq_lookup);
2929f49d3b05f092b89e774be20c654ceb0c64a7d19James Smart	psli->iocbq_lookup = NULL;
293da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
294da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	return;
295dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>}
296dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
297e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
2983621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool
299e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA which owns the pool to allocate from
300e59058c44025d71c9b7f260076a932935d3bba95James Smart * @mem_flags: indicates if this is a priority (MEM_PRI) allocation
301e59058c44025d71c9b7f260076a932935d3bba95James Smart * @handle: used to return the DMA-mapped address of the mbuf
302e59058c44025d71c9b7f260076a932935d3bba95James Smart *
303e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool.
304e59058c44025d71c9b7f260076a932935d3bba95James Smart * Allocates from generic pci_pool_alloc function first and if that fails and
305e59058c44025d71c9b7f260076a932935d3bba95James Smart * mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the
306e59058c44025d71c9b7f260076a932935d3bba95James Smart * HBA's pool.
307e59058c44025d71c9b7f260076a932935d3bba95James Smart *
308e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Not interrupt-safe.  Must be called with no locks held.  Takes
309e59058c44025d71c9b7f260076a932935d3bba95James Smart * phba->hbalock.
310e59058c44025d71c9b7f260076a932935d3bba95James Smart *
311e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns:
312e59058c44025d71c9b7f260076a932935d3bba95James Smart *   pointer to the allocated mbuf on success
313e59058c44025d71c9b7f260076a932935d3bba95James Smart *   NULL on failure
314e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
315dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>void *
316dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
317dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>{
318dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
3192e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	unsigned long iflags;
320dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	void *ret;
321dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
322dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
323dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
3242e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	spin_lock_irqsave(&phba->hbalock, iflags);
32592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
326dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->current_count--;
327dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		ret = pool->elements[pool->current_count].virt;
328dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		*handle = pool->elements[pool->current_count].phys;
329dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	}
3302e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	spin_unlock_irqrestore(&phba->hbalock, iflags);
331dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	return ret;
332dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>}
333dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
334e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
3353621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
336e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA which owns the pool to return to
337e59058c44025d71c9b7f260076a932935d3bba95James Smart * @virt: mbuf to free
338e59058c44025d71c9b7f260076a932935d3bba95James Smart * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
339e59058c44025d71c9b7f260076a932935d3bba95James Smart *
340e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
341e59058c44025d71c9b7f260076a932935d3bba95James Smart * it is below its max_count, frees the mbuf otherwise.
342e59058c44025d71c9b7f260076a932935d3bba95James Smart *
343e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Must be called with phba->hbalock held to synchronize access to
344e59058c44025d71c9b7f260076a932935d3bba95James Smart * lpfc_mbuf_safety_pool.
345e59058c44025d71c9b7f260076a932935d3bba95James Smart *
346e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns: None
347e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
348dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>void
3492e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
350dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>{
351dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
352dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>
353dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	if (pool->current_count < pool->max_count) {
354dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->elements[pool->current_count].virt = virt;
355dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->elements[pool->current_count].phys = dma;
356dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pool->current_count++;
357dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	} else {
358dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>		pci_pool_free(phba->lpfc_mbuf_pool, virt, dma);
359dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	}
360dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>	return;
361dea3101e0a5c897d2c9351a7444e139db9f40247<jejb@titanic.il.steeleye.com>}
3622e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart
363e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
3643621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
365e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA which owns the pool to return to
366e59058c44025d71c9b7f260076a932935d3bba95James Smart * @virt: mbuf to free
367e59058c44025d71c9b7f260076a932935d3bba95James Smart * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
368e59058c44025d71c9b7f260076a932935d3bba95James Smart *
369e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
370e59058c44025d71c9b7f260076a932935d3bba95James Smart * it is below its max_count, frees the mbuf otherwise.
371e59058c44025d71c9b7f260076a932935d3bba95James Smart *
372e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Takes phba->hbalock.  Can be called with or without other locks held.
373e59058c44025d71c9b7f260076a932935d3bba95James Smart *
374e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns: None
375e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
3762e0fef85e098f6794956b8b80b111179fbb4cbb7James Smartvoid
3772e0fef85e098f6794956b8b80b111179fbb4cbb7James Smartlpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
3782e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart{
3792e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	unsigned long iflags;
3802e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart
3812e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	spin_lock_irqsave(&phba->hbalock, iflags);
3822e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	__lpfc_mbuf_free(phba, virt, dma);
3832e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	spin_unlock_irqrestore(&phba->hbalock, iflags);
3842e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart	return;
3852e0fef85e098f6794956b8b80b111179fbb4cbb7James Smart}
386ed957684294618602b48f1950b0c9bbcb036583fJames Smart
387e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
3883621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * lpfc_els_hbq_alloc - Allocate an HBQ buffer
389e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA to allocate HBQ buffer for
390e59058c44025d71c9b7f260076a932935d3bba95James Smart *
391da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hrb_pool PCI
392e59058c44025d71c9b7f260076a932935d3bba95James Smart * pool along a non-DMA-mapped container for it.
393e59058c44025d71c9b7f260076a932935d3bba95James Smart *
394e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Not interrupt-safe.  Must be called with no locks held.
395e59058c44025d71c9b7f260076a932935d3bba95James Smart *
396e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns:
397e59058c44025d71c9b7f260076a932935d3bba95James Smart *   pointer to HBQ on success
398e59058c44025d71c9b7f260076a932935d3bba95James Smart *   NULL on failure
399e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
40051ef4c26891a734bc8416b639ad460a8162926bcJames Smartstruct hbq_dmabuf *
40151ef4c26891a734bc8416b639ad460a8162926bcJames Smartlpfc_els_hbq_alloc(struct lpfc_hba *phba)
402ed957684294618602b48f1950b0c9bbcb036583fJames Smart{
40351ef4c26891a734bc8416b639ad460a8162926bcJames Smart	struct hbq_dmabuf *hbqbp;
40451ef4c26891a734bc8416b639ad460a8162926bcJames Smart
40551ef4c26891a734bc8416b639ad460a8162926bcJames Smart	hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
40651ef4c26891a734bc8416b639ad460a8162926bcJames Smart	if (!hbqbp)
40751ef4c26891a734bc8416b639ad460a8162926bcJames Smart		return NULL;
40851ef4c26891a734bc8416b639ad460a8162926bcJames Smart
4098568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL,
41051ef4c26891a734bc8416b639ad460a8162926bcJames Smart					  &hbqbp->dbuf.phys);
41151ef4c26891a734bc8416b639ad460a8162926bcJames Smart	if (!hbqbp->dbuf.virt) {
41251ef4c26891a734bc8416b639ad460a8162926bcJames Smart		kfree(hbqbp);
41351ef4c26891a734bc8416b639ad460a8162926bcJames Smart		return NULL;
41451ef4c26891a734bc8416b639ad460a8162926bcJames Smart	}
41551ef4c26891a734bc8416b639ad460a8162926bcJames Smart	hbqbp->size = LPFC_BPL_SIZE;
41651ef4c26891a734bc8416b639ad460a8162926bcJames Smart	return hbqbp;
417ed957684294618602b48f1950b0c9bbcb036583fJames Smart}
418ed957684294618602b48f1950b0c9bbcb036583fJames Smart
419e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
420da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_els_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
421e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA buffer was allocated for
422e59058c44025d71c9b7f260076a932935d3bba95James Smart * @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
423e59058c44025d71c9b7f260076a932935d3bba95James Smart *
424e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Frees both the container and the DMA-mapped buffer returned by
425e59058c44025d71c9b7f260076a932935d3bba95James Smart * lpfc_els_hbq_alloc.
426e59058c44025d71c9b7f260076a932935d3bba95James Smart *
427e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Can be called with or without locks held.
428e59058c44025d71c9b7f260076a932935d3bba95James Smart *
429e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns: None
430e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
431ed957684294618602b48f1950b0c9bbcb036583fJames Smartvoid
43251ef4c26891a734bc8416b639ad460a8162926bcJames Smartlpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
433ed957684294618602b48f1950b0c9bbcb036583fJames Smart{
4348568a4d2495ebcf5da38a2141c7633399143b1a5James Smart	pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys);
43551ef4c26891a734bc8416b639ad460a8162926bcJames Smart	kfree(hbqbp);
436ed957684294618602b48f1950b0c9bbcb036583fJames Smart	return;
437ed957684294618602b48f1950b0c9bbcb036583fJames Smart}
438ed957684294618602b48f1950b0c9bbcb036583fJames Smart
439e59058c44025d71c9b7f260076a932935d3bba95James Smart/**
440da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_sli4_rb_alloc - Allocate an SLI4 Receive buffer
441da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * @phba: HBA to allocate a receive buffer for
442da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
443da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI
444da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * pool along a non-DMA-mapped container for it.
445da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
446da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Notes: Not interrupt-safe.  Must be called with no locks held.
447da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
448da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Returns:
449da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *   pointer to HBQ on success
450da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *   NULL on failure
451da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart **/
452da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartstruct hbq_dmabuf *
453da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartlpfc_sli4_rb_alloc(struct lpfc_hba *phba)
454da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart{
455da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	struct hbq_dmabuf *dma_buf;
456da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
457da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	dma_buf = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
458da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	if (!dma_buf)
459da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		return NULL;
460da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
461da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	dma_buf->hbuf.virt = pci_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL,
462da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					    &dma_buf->hbuf.phys);
463da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	if (!dma_buf->hbuf.virt) {
464da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		kfree(dma_buf);
465da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		return NULL;
466da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	}
467da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
468da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart					    &dma_buf->dbuf.phys);
469da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	if (!dma_buf->dbuf.virt) {
470da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
471da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart			      dma_buf->hbuf.phys);
472da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		kfree(dma_buf);
473da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart		return NULL;
474da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	}
475da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	dma_buf->size = LPFC_BPL_SIZE;
476da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	return dma_buf;
477da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart}
478da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
479da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart/**
480da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_sli4_rb_free - Frees a receive buffer
481da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * @phba: HBA buffer was allocated for
482da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * @dmab: DMA Buffer container returned by lpfc_sli4_hbq_alloc
483da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
484da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Description: Frees both the container and the DMA-mapped buffers returned by
485da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * lpfc_sli4_rb_alloc.
486da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
487da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Notes: Can be called with or without locks held.
488da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart *
489da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart * Returns: None
490da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart **/
491da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartvoid
492da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smartlpfc_sli4_rb_free(struct lpfc_hba *phba, struct hbq_dmabuf *dmab)
493da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart{
494da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
495da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	pci_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys);
496da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	kfree(dmab);
497da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart	return;
498da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart}
499da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart
500da0436e915a5c17ee79e72c1bf978a4ebb1cbf4dJames Smart/**
5013621a710a7dbb2d22a8e95d94bcf0c2d13ef57fcJames Smart * lpfc_in_buf_free - Free a DMA buffer
502e59058c44025d71c9b7f260076a932935d3bba95James Smart * @phba: HBA buffer is associated with
503e59058c44025d71c9b7f260076a932935d3bba95James Smart * @mp: Buffer to free
504e59058c44025d71c9b7f260076a932935d3bba95James Smart *
505e59058c44025d71c9b7f260076a932935d3bba95James Smart * Description: Frees the given DMA buffer in the appropriate way given if the
506e59058c44025d71c9b7f260076a932935d3bba95James Smart * HBA is running in SLI3 mode with HBQs enabled.
507e59058c44025d71c9b7f260076a932935d3bba95James Smart *
508e59058c44025d71c9b7f260076a932935d3bba95James Smart * Notes: Takes phba->hbalock.  Can be called with or without other locks held.
509e59058c44025d71c9b7f260076a932935d3bba95James Smart *
510e59058c44025d71c9b7f260076a932935d3bba95James Smart * Returns: None
511e59058c44025d71c9b7f260076a932935d3bba95James Smart **/
51292d7f7b0cde3ad2260e7462b40867b57efd49851James Smartvoid
51392d7f7b0cde3ad2260e7462b40867b57efd49851James Smartlpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
51492d7f7b0cde3ad2260e7462b40867b57efd49851James Smart{
51592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	struct hbq_dmabuf *hbq_entry;
5163163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart	unsigned long flags;
51792d7f7b0cde3ad2260e7462b40867b57efd49851James Smart
5187f5f3d0d02aa2f124e764aee5c775589ce72fd42James Smart	if (!mp)
5197f5f3d0d02aa2f124e764aee5c775589ce72fd42James Smart		return;
5207f5f3d0d02aa2f124e764aee5c775589ce72fd42James Smart
52192d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
5223163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		/* Check whether HBQ is still in use */
5233163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		spin_lock_irqsave(&phba->hbalock, flags);
5243163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		if (!phba->hbq_in_use) {
5253163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart			spin_unlock_irqrestore(&phba->hbalock, flags);
5263163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart			return;
5273163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		}
52892d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
5293163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		list_del(&hbq_entry->dbuf.list);
53092d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		if (hbq_entry->tag == -1) {
53151ef4c26891a734bc8416b639ad460a8162926bcJames Smart			(phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
53251ef4c26891a734bc8416b639ad460a8162926bcJames Smart				(phba, hbq_entry);
53392d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		} else {
53492d7f7b0cde3ad2260e7462b40867b57efd49851James Smart			lpfc_sli_free_hbq(phba, hbq_entry);
53592d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		}
5363163f725a5d071eea1830bbbfab78cfe3fc9baafJames Smart		spin_unlock_irqrestore(&phba->hbalock, flags);
53792d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	} else {
53892d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		lpfc_mbuf_free(phba, mp->virt, mp->phys);
53992d7f7b0cde3ad2260e7462b40867b57efd49851James Smart		kfree(mp);
54092d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	}
54192d7f7b0cde3ad2260e7462b40867b57efd49851James Smart	return;
54292d7f7b0cde3ad2260e7462b40867b57efd49851James Smart}
543