1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
88f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
238f23e9faSHans Rosenfeld  * Copyright (c) 2004-2011 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25*a3170057SPaul Winder  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26*a3170057SPaul Winder  * Copyright 2020 RackTop Systems, Inc.
27fcf3ce44SJohn Forte  */
28fcf3ce44SJohn Forte 
29291a2b48SSukumar Swaminathan #include <emlxs.h>
30fcf3ce44SJohn Forte 
318f23e9faSHans Rosenfeld /* #define EMLXS_POOL_DEBUG */
328f23e9faSHans Rosenfeld 
33fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_MEM_C);
34fcf3ce44SJohn Forte 
35fcf3ce44SJohn Forte 
368f23e9faSHans Rosenfeld static uint32_t emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg,
378f23e9faSHans Rosenfeld 			uint32_t count);
388f23e9faSHans Rosenfeld static void emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count);
398f23e9faSHans Rosenfeld 
408f23e9faSHans Rosenfeld 
41fcf3ce44SJohn Forte extern int32_t
emlxs_mem_alloc_buffer(emlxs_hba_t * hba)42fcf3ce44SJohn Forte emlxs_mem_alloc_buffer(emlxs_hba_t *hba)
43fcf3ce44SJohn Forte {
44fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
45fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
46fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
4782527734SSukumar Swaminathan 	MEMSEG *seg;
48fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
49fcf3ce44SJohn Forte 	int32_t i;
5082527734SSukumar Swaminathan 	MATCHMAP *mp;
518f23e9faSHans Rosenfeld 	MATCHMAP **bpl_table;
52fcf3ce44SJohn Forte 
53fcf3ce44SJohn Forte 	buf_info = &bufinfo;
54fcf3ce44SJohn Forte 	cfg = &CFG;
55fcf3ce44SJohn Forte 
5682527734SSukumar Swaminathan 	bzero(hba->memseg, sizeof (hba->memseg));
57fcf3ce44SJohn Forte 
58fcf3ce44SJohn Forte 	/* Allocate the fc_table */
59fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
6082527734SSukumar Swaminathan 	buf_info->size = (hba->max_iotag * sizeof (emlxs_buf_t *));
61fcf3ce44SJohn Forte 
62fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
63fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
64fcf3ce44SJohn Forte 
65fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
66fcf3ce44SJohn Forte 		    "fc_table buffer.");
67fcf3ce44SJohn Forte 
6882527734SSukumar Swaminathan 		goto failed;
69fcf3ce44SJohn Forte 	}
7082527734SSukumar Swaminathan 	hba->fc_table = buf_info->virt;
7182527734SSukumar Swaminathan 	bzero(hba->fc_table, buf_info->size);
72fcf3ce44SJohn Forte 
7382527734SSukumar Swaminathan 	/* Prepare the memory pools */
7482527734SSukumar Swaminathan 	for (i = 0; i < FC_MAX_SEG; i++) {
7582527734SSukumar Swaminathan 		seg = &hba->memseg[i];
76fcf3ce44SJohn Forte 
7782527734SSukumar Swaminathan 		switch (i) {
7882527734SSukumar Swaminathan 		case MEM_NLP:
798f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "Node Pool",
808f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
8182527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_NLP;
8282527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (NODELIST);
838f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_nodes + 2;
848f23e9faSHans Rosenfeld 			seg->fc_lo_water = 2;
858f23e9faSHans Rosenfeld 			seg->fc_step = 1;
8682527734SSukumar Swaminathan 			break;
87fcf3ce44SJohn Forte 
8882527734SSukumar Swaminathan 		case MEM_IOCB:
898f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "IOCB Pool",
908f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
9182527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IOCB;
9282527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (IOCBQ);
938f23e9faSHans Rosenfeld 			seg->fc_hi_water = cfg[CFG_NUM_IOCBS].current;
948f23e9faSHans Rosenfeld 			seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
958f23e9faSHans Rosenfeld 			seg->fc_step = cfg[CFG_NUM_IOCBS].low;
9682527734SSukumar Swaminathan 			break;
97fcf3ce44SJohn Forte 
9882527734SSukumar Swaminathan 		case MEM_MBOX:
998f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "MBOX Pool",
1008f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
10182527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_MBOX;
10282527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (MAILBOXQ);
1038f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_nodes + 32;
1048f23e9faSHans Rosenfeld 			seg->fc_lo_water = 32;
1058f23e9faSHans Rosenfeld 			seg->fc_step = 1;
10682527734SSukumar Swaminathan 			break;
107fcf3ce44SJohn Forte 
10882527734SSukumar Swaminathan 		case MEM_BPL:
10982527734SSukumar Swaminathan 			if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
11082527734SSukumar Swaminathan 				continue;
11182527734SSukumar Swaminathan 			}
1128f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "BPL Pool",
1138f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
11482527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BPL;
11582527734SSukumar Swaminathan 			seg->fc_memsize	= hba->sli.sli3.mem_bpl_size;
11682527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
11782527734SSukumar Swaminathan 			seg->fc_memalign = 32;
1188f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_iotag;
1198f23e9faSHans Rosenfeld 			seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
1208f23e9faSHans Rosenfeld 			seg->fc_step = cfg[CFG_NUM_IOCBS].low;
12182527734SSukumar Swaminathan 			break;
122fcf3ce44SJohn Forte 
12382527734SSukumar Swaminathan 		case MEM_BUF:
12482527734SSukumar Swaminathan 			/* These are the unsolicited ELS buffers. */
1258f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "BUF Pool",
1268f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
12782527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BUF;
12882527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_BUF_SIZE;
12982527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
13082527734SSukumar Swaminathan 			seg->fc_memalign = 32;
1318f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_ELSBUF_COUNT + MEM_BUF_COUNT;
1328f23e9faSHans Rosenfeld 			seg->fc_lo_water = MEM_ELSBUF_COUNT;
1338f23e9faSHans Rosenfeld 			seg->fc_step = 1;
13482527734SSukumar Swaminathan 			break;
135291a2b48SSukumar Swaminathan 
13682527734SSukumar Swaminathan 		case MEM_IPBUF:
13782527734SSukumar Swaminathan 			/* These are the unsolicited IP buffers. */
13882527734SSukumar Swaminathan 			if (cfg[CFG_NETWORK_ON].current == 0) {
13982527734SSukumar Swaminathan 				continue;
14082527734SSukumar Swaminathan 			}
141fcf3ce44SJohn Forte 
1428f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "IPBUF Pool",
1438f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
14482527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IPBUF;
14582527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_IPBUF_SIZE;
14682527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
14782527734SSukumar Swaminathan 			seg->fc_memalign = 32;
1488f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_IPBUF_COUNT;
1498f23e9faSHans Rosenfeld 			seg->fc_lo_water = 0;
1508f23e9faSHans Rosenfeld 			seg->fc_step = 4;
15182527734SSukumar Swaminathan 			break;
152fcf3ce44SJohn Forte 
15382527734SSukumar Swaminathan 		case MEM_CTBUF:
15482527734SSukumar Swaminathan 			/* These are the unsolicited CT buffers. */
1558f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "CTBUF Pool",
1568f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
15782527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_CTBUF;
15882527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_CTBUF_SIZE;
15982527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
16082527734SSukumar Swaminathan 			seg->fc_memalign = 32;
1618f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_CTBUF_COUNT;
1628f23e9faSHans Rosenfeld 			seg->fc_lo_water = MEM_CTBUF_COUNT;
1638f23e9faSHans Rosenfeld 			seg->fc_step = 1;
16482527734SSukumar Swaminathan 			break;
165fcf3ce44SJohn Forte 
166*a3170057SPaul Winder 		case MEM_SGL1K:
167*a3170057SPaul Winder 			(void) strlcpy(seg->fc_label, "1K SGL Pool",
168*a3170057SPaul Winder 			    sizeof (seg->fc_label));
169*a3170057SPaul Winder 			seg->fc_memtag	= MEM_SGL1K;
170*a3170057SPaul Winder 			seg->fc_memsize	= 0x400;
171*a3170057SPaul Winder 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
172*a3170057SPaul Winder 			seg->fc_memalign = 32;
173*a3170057SPaul Winder 			seg->fc_hi_water = 0x5000;
174*a3170057SPaul Winder 			seg->fc_lo_water = 0;
175*a3170057SPaul Winder 			seg->fc_step = 0x100;
176*a3170057SPaul Winder 			break;
177*a3170057SPaul Winder 
178*a3170057SPaul Winder 		case MEM_SGL2K:
179*a3170057SPaul Winder 			(void) strlcpy(seg->fc_label, "2K SGL Pool",
180*a3170057SPaul Winder 			    sizeof (seg->fc_label));
181*a3170057SPaul Winder 			seg->fc_memtag	= MEM_SGL2K;
182*a3170057SPaul Winder 			seg->fc_memsize	= 0x800;
183*a3170057SPaul Winder 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
184*a3170057SPaul Winder 			seg->fc_memalign = 32;
185*a3170057SPaul Winder 			seg->fc_hi_water = 0x5000;
186*a3170057SPaul Winder 			seg->fc_lo_water = 0;
187*a3170057SPaul Winder 			seg->fc_step = 0x100;
188*a3170057SPaul Winder 			break;
189*a3170057SPaul Winder 
190*a3170057SPaul Winder 		case MEM_SGL4K:
191*a3170057SPaul Winder 			(void) strlcpy(seg->fc_label, "4K SGL Pool",
192*a3170057SPaul Winder 			    sizeof (seg->fc_label));
193*a3170057SPaul Winder 			seg->fc_memtag	= MEM_SGL4K;
194*a3170057SPaul Winder 			seg->fc_memsize	= 0x1000;
195*a3170057SPaul Winder 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
196*a3170057SPaul Winder 			seg->fc_memalign = 32;
197*a3170057SPaul Winder 			seg->fc_hi_water = 0x5000;
198*a3170057SPaul Winder 			seg->fc_lo_water = 0;
199*a3170057SPaul Winder 			seg->fc_step = 0x100;
200*a3170057SPaul Winder 			break;
201*a3170057SPaul Winder 
20282527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
2038f23e9faSHans Rosenfeld 		case MEM_FCTBUF:
20482527734SSukumar Swaminathan 			/* These are the unsolicited FCT buffers. */
2058f23e9faSHans Rosenfeld 			if (!(port->flag & EMLXS_TGT_ENABLED)) {
20682527734SSukumar Swaminathan 				continue;
20782527734SSukumar Swaminathan 			}
208fcf3ce44SJohn Forte 
2098f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "FCTBUF Pool",
2108f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
21182527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_FCTBUF;
21282527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_FCTBUF_SIZE;
21382527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
21482527734SSukumar Swaminathan 			seg->fc_memalign = 32;
2158f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_FCTBUF_COUNT;
2168f23e9faSHans Rosenfeld 			seg->fc_lo_water = 0;
2178f23e9faSHans Rosenfeld 			seg->fc_step = 8;
21882527734SSukumar Swaminathan 			break;
2198f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
220fcf3ce44SJohn Forte 
22182527734SSukumar Swaminathan 		default:
22282527734SSukumar Swaminathan 			continue;
223fcf3ce44SJohn Forte 		}
224fcf3ce44SJohn Forte 
22582527734SSukumar Swaminathan 		if (seg->fc_memsize == 0) {
22682527734SSukumar Swaminathan 			continue;
22782527734SSukumar Swaminathan 		}
228fcf3ce44SJohn Forte 
2298f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_create(hba, seg);
2308f23e9faSHans Rosenfeld 
2318f23e9faSHans Rosenfeld 		if (seg->fc_numblks < seg->fc_lo_water) {
2328f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
2338f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d flags=%x lo=%d hi=%d",
2348f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks,
2358f23e9faSHans Rosenfeld 			    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
2368f23e9faSHans Rosenfeld 			    seg->fc_hi_water);
2378f23e9faSHans Rosenfeld 
2388f23e9faSHans Rosenfeld 			goto failed;
2398f23e9faSHans Rosenfeld 		}
2408f23e9faSHans Rosenfeld 	}
2418f23e9faSHans Rosenfeld 
2428f23e9faSHans Rosenfeld 	hba->sli.sli3.bpl_table = NULL;
2438f23e9faSHans Rosenfeld 	seg = &hba->memseg[MEM_BPL];
2448f23e9faSHans Rosenfeld 
2458f23e9faSHans Rosenfeld 	/* If SLI3 and MEM_BPL pool is static */
2468f23e9faSHans Rosenfeld 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK) &&
2478f23e9faSHans Rosenfeld 	    !(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
2488f23e9faSHans Rosenfeld 		/*
2498f23e9faSHans Rosenfeld 		 * Allocate and Initialize bpl_table
2508f23e9faSHans Rosenfeld 		 * This is for increased performance.
2518f23e9faSHans Rosenfeld 		 */
2528f23e9faSHans Rosenfeld 		bzero(buf_info, sizeof (MBUF_INFO));
2538f23e9faSHans Rosenfeld 		buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
2548f23e9faSHans Rosenfeld 
2558f23e9faSHans Rosenfeld 		(void) emlxs_mem_alloc(hba, buf_info);
2568f23e9faSHans Rosenfeld 		if (buf_info->virt == NULL) {
2578f23e9faSHans Rosenfeld 
2588f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
2598f23e9faSHans Rosenfeld 			    &emlxs_mem_alloc_failed_msg,
2608f23e9faSHans Rosenfeld 			    "BPL table buffer.");
2618f23e9faSHans Rosenfeld 
26282527734SSukumar Swaminathan 			goto failed;
263fcf3ce44SJohn Forte 		}
2648f23e9faSHans Rosenfeld 		hba->sli.sli3.bpl_table = buf_info->virt;
265291a2b48SSukumar Swaminathan 
2668f23e9faSHans Rosenfeld 		bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
2678f23e9faSHans Rosenfeld 		for (i = 0; i < hba->max_iotag; i++) {
2688f23e9faSHans Rosenfeld 			mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL);
2698f23e9faSHans Rosenfeld 			mp->flag |= MAP_TABLE_ALLOCATED;
2708f23e9faSHans Rosenfeld 			bpl_table[i] = mp;
2718f23e9faSHans Rosenfeld 		}
272fcf3ce44SJohn Forte 	}
273fcf3ce44SJohn Forte 
27482527734SSukumar Swaminathan 	return (1);
275fcf3ce44SJohn Forte 
27682527734SSukumar Swaminathan failed:
277fcf3ce44SJohn Forte 
27882527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
27982527734SSukumar Swaminathan 	return (0);
280fcf3ce44SJohn Forte 
28182527734SSukumar Swaminathan } /* emlxs_mem_alloc_buffer() */
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 
28482527734SSukumar Swaminathan /*
28582527734SSukumar Swaminathan  * emlxs_mem_free_buffer
28682527734SSukumar Swaminathan  *
28782527734SSukumar Swaminathan  * This routine will free iocb/data buffer space
28882527734SSukumar Swaminathan  * and TGTM resource.
28982527734SSukumar Swaminathan  */
29082527734SSukumar Swaminathan extern int
emlxs_mem_free_buffer(emlxs_hba_t * hba)29182527734SSukumar Swaminathan emlxs_mem_free_buffer(emlxs_hba_t *hba)
29282527734SSukumar Swaminathan {
2938f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
29482527734SSukumar Swaminathan 	emlxs_port_t *vport;
29582527734SSukumar Swaminathan 	int32_t j;
29682527734SSukumar Swaminathan 	MATCHMAP *mp;
29782527734SSukumar Swaminathan 	CHANNEL *cp;
29882527734SSukumar Swaminathan 	RING *rp;
29982527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
30082527734SSukumar Swaminathan 	MBUF_INFO bufinfo;
3018f23e9faSHans Rosenfeld 	MATCHMAP **bpl_table;
302fcf3ce44SJohn Forte 
30382527734SSukumar Swaminathan 	buf_info = &bufinfo;
304291a2b48SSukumar Swaminathan 
30582527734SSukumar Swaminathan 	for (j = 0; j < hba->chan_count; j++) {
30682527734SSukumar Swaminathan 		cp = &hba->chan[j];
307fcf3ce44SJohn Forte 
30882527734SSukumar Swaminathan 		/* Flush the ring */
30982527734SSukumar Swaminathan 		(void) emlxs_tx_channel_flush(hba, cp, 0);
31082527734SSukumar Swaminathan 	}
311fcf3ce44SJohn Forte 
31282527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
31382527734SSukumar Swaminathan 		/* free the mapped address match area for each ring */
31482527734SSukumar Swaminathan 		for (j = 0; j < MAX_RINGS; j++) {
31582527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[j];
316fcf3ce44SJohn Forte 
31782527734SSukumar Swaminathan 			while (rp->fc_mpoff) {
31882527734SSukumar Swaminathan 				uint64_t addr;
319fcf3ce44SJohn Forte 
32082527734SSukumar Swaminathan 				addr = 0;
32182527734SSukumar Swaminathan 				mp = (MATCHMAP *)(rp->fc_mpoff);
322fcf3ce44SJohn Forte 
32382527734SSukumar Swaminathan 				if ((j == hba->channel_els) ||
32482527734SSukumar Swaminathan 				    (j == hba->channel_ct) ||
32582527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
32682527734SSukumar Swaminathan 				    (j == hba->CHANNEL_FCT) ||
32782527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
32882527734SSukumar Swaminathan 				    (j == hba->channel_ip)) {
32982527734SSukumar Swaminathan 					addr = mp->phys;
33082527734SSukumar Swaminathan 				}
331fcf3ce44SJohn Forte 
33282527734SSukumar Swaminathan 				if ((mp = emlxs_mem_get_vaddr(hba, rp, addr))) {
33382527734SSukumar Swaminathan 					if (j == hba->channel_els) {
334a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
335a9800bebSGarrett D'Amore 						    MEM_ELSBUF, (void *)mp);
33682527734SSukumar Swaminathan 					} else if (j == hba->channel_ct) {
337a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
338a9800bebSGarrett D'Amore 						    MEM_CTBUF, (void *)mp);
33982527734SSukumar Swaminathan 					} else if (j == hba->channel_ip) {
340a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
341a9800bebSGarrett D'Amore 						    MEM_IPBUF, (void *)mp);
34282527734SSukumar Swaminathan 					}
34382527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
34482527734SSukumar Swaminathan 					else if (j == hba->CHANNEL_FCT) {
345a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
346a9800bebSGarrett D'Amore 						    MEM_FCTBUF, (void *)mp);
34782527734SSukumar Swaminathan 					}
34882527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
349fcf3ce44SJohn Forte 
35082527734SSukumar Swaminathan 				}
35182527734SSukumar Swaminathan 			}
352fcf3ce44SJohn Forte 		}
35382527734SSukumar Swaminathan 	}
35482527734SSukumar Swaminathan 
35582527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
35682527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_ELS_HBQ_ID);
35782527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_IP_HBQ_ID);
35882527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_CT_HBQ_ID);
359291a2b48SSukumar Swaminathan 
3608f23e9faSHans Rosenfeld 		if (port->flag & EMLXS_TGT_ENABLED) {
36182527734SSukumar Swaminathan 			emlxs_hbq_free_all(hba, EMLXS_FCT_HBQ_ID);
36282527734SSukumar Swaminathan 		}
363fcf3ce44SJohn Forte 	}
364fcf3ce44SJohn Forte 
36582527734SSukumar Swaminathan 	/* Free the nodes */
36682527734SSukumar Swaminathan 	for (j = 0; j < MAX_VPORTS; j++) {
36782527734SSukumar Swaminathan 		vport = &VPORT(j);
36882527734SSukumar Swaminathan 		if (vport->node_count) {
36982527734SSukumar Swaminathan 			emlxs_node_destroy_all(vport);
37082527734SSukumar Swaminathan 		}
37182527734SSukumar Swaminathan 	}
372fcf3ce44SJohn Forte 
37382527734SSukumar Swaminathan 	/* Make sure the mailbox queue is empty */
37482527734SSukumar Swaminathan 	emlxs_mb_flush(hba);
375fcf3ce44SJohn Forte 
37682527734SSukumar Swaminathan 	if (hba->fc_table) {
377fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
37882527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (emlxs_buf_t *);
37982527734SSukumar Swaminathan 		buf_info->virt = hba->fc_table;
38082527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
38182527734SSukumar Swaminathan 		hba->fc_table = NULL;
38282527734SSukumar Swaminathan 	}
383fcf3ce44SJohn Forte 
3848f23e9faSHans Rosenfeld 	if (hba->sli.sli3.bpl_table) {
3858f23e9faSHans Rosenfeld 		/* Return MEM_BPLs to their pool */
3868f23e9faSHans Rosenfeld 		bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
3878f23e9faSHans Rosenfeld 		for (j = 0; j < hba->max_iotag; j++) {
3888f23e9faSHans Rosenfeld 			mp = bpl_table[j];
3898f23e9faSHans Rosenfeld 			mp->flag &= ~MAP_TABLE_ALLOCATED;
3908f23e9faSHans Rosenfeld 			emlxs_mem_put(hba, MEM_BPL, (void*)mp);
3918f23e9faSHans Rosenfeld 		}
3928f23e9faSHans Rosenfeld 
39382527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
39482527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
3958f23e9faSHans Rosenfeld 		buf_info->virt = hba->sli.sli3.bpl_table;
39682527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
3978f23e9faSHans Rosenfeld 		hba->sli.sli3.bpl_table = NULL;
39882527734SSukumar Swaminathan 	}
399fcf3ce44SJohn Forte 
40082527734SSukumar Swaminathan 	/* Free the memory segments */
40182527734SSukumar Swaminathan 	for (j = 0; j < FC_MAX_SEG; j++) {
4028f23e9faSHans Rosenfeld 		emlxs_mem_pool_destroy(hba, &hba->memseg[j]);
40382527734SSukumar Swaminathan 	}
404291a2b48SSukumar Swaminathan 
40582527734SSukumar Swaminathan 	return (0);
406fcf3ce44SJohn Forte 
40782527734SSukumar Swaminathan } /* emlxs_mem_free_buffer() */
408fcf3ce44SJohn Forte 
409fcf3ce44SJohn Forte 
4108f23e9faSHans Rosenfeld /* Must hold EMLXS_MEMGET_LOCK when calling */
4118f23e9faSHans Rosenfeld static uint32_t
emlxs_mem_pool_alloc(emlxs_hba_t * hba,MEMSEG * seg,uint32_t count)4128f23e9faSHans Rosenfeld emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
41382527734SSukumar Swaminathan {
41482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
41582527734SSukumar Swaminathan 	uint8_t *bp = NULL;
41682527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
41782527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
41882527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
41982527734SSukumar Swaminathan 	uint32_t i;
4208f23e9faSHans Rosenfeld 	uint32_t fc_numblks;
421fcf3ce44SJohn Forte 
4228f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
4238f23e9faSHans Rosenfeld 		return (0);
4248f23e9faSHans Rosenfeld 	}
425fcf3ce44SJohn Forte 
4268f23e9faSHans Rosenfeld 	if (seg->fc_numblks >= seg->fc_hi_water) {
4278f23e9faSHans Rosenfeld 		return (0);
4288f23e9faSHans Rosenfeld 	}
4298f23e9faSHans Rosenfeld 
4308f23e9faSHans Rosenfeld 	if (count == 0) {
4318f23e9faSHans Rosenfeld 		return (0);
4328f23e9faSHans Rosenfeld 	}
433fcf3ce44SJohn Forte 
4348f23e9faSHans Rosenfeld 	if (count > (seg->fc_hi_water - seg->fc_numblks)) {
4358f23e9faSHans Rosenfeld 		count = (seg->fc_hi_water - seg->fc_numblks);
4368f23e9faSHans Rosenfeld 	}
437fcf3ce44SJohn Forte 
4388f23e9faSHans Rosenfeld 	buf_info = &local_buf_info;
4398f23e9faSHans Rosenfeld 	fc_numblks = seg->fc_numblks;
4408f23e9faSHans Rosenfeld 
4418f23e9faSHans Rosenfeld 	/* Check for initial allocation */
4428f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
4438f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
4448f23e9faSHans Rosenfeld 		    "%s alloc:%d n=%d s=%d f=%x l=%d,%d,%d "
4458f23e9faSHans Rosenfeld 		    "f=%d:%d",
4468f23e9faSHans Rosenfeld 		    seg->fc_label, count, seg->fc_numblks,
4478f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
4488f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
4498f23e9faSHans Rosenfeld 		    seg->fc_low);
45082527734SSukumar Swaminathan 	}
451291a2b48SSukumar Swaminathan 
45282527734SSukumar Swaminathan 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
45382527734SSukumar Swaminathan 		goto vmem_pool;
454fcf3ce44SJohn Forte 	}
455fcf3ce44SJohn Forte 
45682527734SSukumar Swaminathan /* dma_pool */
45782527734SSukumar Swaminathan 
4588f23e9faSHans Rosenfeld 	for (i = 0; i < count; i++) {
459fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
460fcf3ce44SJohn Forte 		buf_info->size = sizeof (MATCHMAP);
461fcf3ce44SJohn Forte 		buf_info->align = sizeof (void *);
462fcf3ce44SJohn Forte 
463fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
464fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
465fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
4668f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
4678f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
468fcf3ce44SJohn Forte 
4698f23e9faSHans Rosenfeld 			goto done;
470fcf3ce44SJohn Forte 		}
471291a2b48SSukumar Swaminathan 
47282527734SSukumar Swaminathan 		mp = (MATCHMAP *)buf_info->virt;
47382527734SSukumar Swaminathan 		bzero(mp, sizeof (MATCHMAP));
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
47682527734SSukumar Swaminathan 		buf_info->size  = seg->fc_memsize;
47782527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
47882527734SSukumar Swaminathan 		buf_info->align = seg->fc_memalign;
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
481fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
482fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
4838f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
4848f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
485fcf3ce44SJohn Forte 
48682527734SSukumar Swaminathan 			/* Free the mp object */
48782527734SSukumar Swaminathan 			bzero(buf_info, sizeof (MBUF_INFO));
48882527734SSukumar Swaminathan 			buf_info->size = sizeof (MATCHMAP);
489a9800bebSGarrett D'Amore 			buf_info->virt = (void *)mp;
49082527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
49182527734SSukumar Swaminathan 
4928f23e9faSHans Rosenfeld 			goto done;
493fcf3ce44SJohn Forte 		}
494fcf3ce44SJohn Forte 		bp = (uint8_t *)buf_info->virt;
49582527734SSukumar Swaminathan 		bzero(bp, seg->fc_memsize);
49682527734SSukumar Swaminathan 
49782527734SSukumar Swaminathan 		mp->virt = buf_info->virt;
49882527734SSukumar Swaminathan 		mp->phys = buf_info->phys;
49982527734SSukumar Swaminathan 		mp->size = buf_info->size;
50082527734SSukumar Swaminathan