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
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
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
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 		mp->dma_handle = buf_info->dma_handle;
50182527734SSukumar Swaminathan 		mp->data_handle = buf_info->data_handle;
50282527734SSukumar Swaminathan 		mp->tag = seg->fc_memtag;
50382527734SSukumar Swaminathan 		mp->segment = seg;
50482527734SSukumar Swaminathan 		mp->flag |= MAP_POOL_ALLOCATED;
50582527734SSukumar Swaminathan 
5068f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
5078f23e9faSHans Rosenfeld 		if (mp->tag >= MEM_FCTSEG) {
5088f23e9faSHans Rosenfeld 			if (emlxs_fct_stmf_alloc(hba, mp)) {
5098f23e9faSHans Rosenfeld 				/* Free the DMA memory itself */
5108f23e9faSHans Rosenfeld 				emlxs_mem_free(hba, buf_info);
5118f23e9faSHans Rosenfeld 
5128f23e9faSHans Rosenfeld 				/* Free the mp object */
5138f23e9faSHans Rosenfeld 				bzero(buf_info, sizeof (MBUF_INFO));
5148f23e9faSHans Rosenfeld 				buf_info->size = sizeof (MATCHMAP);
5158f23e9faSHans Rosenfeld 				buf_info->virt = (void *)mp;
5168f23e9faSHans Rosenfeld 				emlxs_mem_free(hba, buf_info);
5178f23e9faSHans Rosenfeld 
5188f23e9faSHans Rosenfeld 				goto done;
5198f23e9faSHans Rosenfeld 			}
5208f23e9faSHans Rosenfeld 		}
5218f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
5228f23e9faSHans Rosenfeld 
52382527734SSukumar Swaminathan 		/* Add the buffer desc to the tail of the pool freelist */
52482527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
52582527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)mp;
52682527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
52782527734SSukumar Swaminathan 		} else {
52882527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)mp;
52982527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
530fcf3ce44SJohn Forte 		}
53182527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)mp;
5328f23e9faSHans Rosenfeld 
5338f23e9faSHans Rosenfeld 		seg->fc_numblks++;
5348f23e9faSHans Rosenfeld 		seg->fc_total_memsize += (seg->fc_memsize + sizeof (MATCHMAP));
535fcf3ce44SJohn Forte 	}
536fcf3ce44SJohn Forte 
5378f23e9faSHans Rosenfeld 	goto done;
538fcf3ce44SJohn Forte 
53982527734SSukumar Swaminathan vmem_pool:
540fcf3ce44SJohn Forte 
5418f23e9faSHans Rosenfeld 	for (i = 0; i < count; i++) {
5428f23e9faSHans Rosenfeld 		bzero(buf_info, sizeof (MBUF_INFO));
5438f23e9faSHans Rosenfeld 		buf_info->size  = seg->fc_memsize;
544fcf3ce44SJohn Forte 
5458f23e9faSHans Rosenfeld 		(void) emlxs_mem_alloc(hba, buf_info);
5468f23e9faSHans Rosenfeld 		if (buf_info->virt == NULL) {
5478f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
5488f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
5498f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
550fcf3ce44SJohn Forte 
5518f23e9faSHans Rosenfeld 			goto done;
5528f23e9faSHans Rosenfeld 		}
5538f23e9faSHans Rosenfeld 		bp = (uint8_t *)buf_info->virt;
554fcf3ce44SJohn Forte 
55582527734SSukumar Swaminathan 		/* Add the buffer to the tail of the pool freelist */
55682527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
55782527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)bp;
55882527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
55982527734SSukumar Swaminathan 		} else {
56082527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)bp;
56182527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
56282527734SSukumar Swaminathan 		}
56382527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)bp;
564fcf3ce44SJohn Forte 
5658f23e9faSHans Rosenfeld 		seg->fc_numblks++;
5668f23e9faSHans Rosenfeld 		seg->fc_total_memsize += seg->fc_memsize;
56782527734SSukumar Swaminathan 	}
568fcf3ce44SJohn Forte 
5698f23e9faSHans Rosenfeld done:
570fcf3ce44SJohn Forte 
5718f23e9faSHans Rosenfeld 	return ((seg->fc_numblks - fc_numblks));
572291a2b48SSukumar Swaminathan 
57382527734SSukumar Swaminathan } /* emlxs_mem_pool_alloc() */
574fcf3ce44SJohn Forte 
575fcf3ce44SJohn Forte 
5768f23e9faSHans Rosenfeld /* Must hold EMLXS_MEMGET_LOCK & EMLXS_MEMPUT_LOCK when calling */
5778f23e9faSHans Rosenfeld static void
5788f23e9faSHans Rosenfeld emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
57982527734SSukumar Swaminathan {
58082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
58182527734SSukumar Swaminathan 	uint8_t *bp = NULL;
58282527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
58382527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
58482527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
585fcf3ce44SJohn Forte 
5868f23e9faSHans Rosenfeld 	if ((seg->fc_memsize == 0) ||
5878f23e9faSHans Rosenfeld 	    (seg->fc_numblks == 0) ||
5888f23e9faSHans Rosenfeld 	    (count == 0)) {
5898f23e9faSHans Rosenfeld 		return;
5908f23e9faSHans Rosenfeld 	}
591fcf3ce44SJohn Forte 
5928f23e9faSHans Rosenfeld 	/* Check max count */
5938f23e9faSHans Rosenfeld 	if (count > seg->fc_numblks) {
5948f23e9faSHans Rosenfeld 		count = seg->fc_numblks;
595fcf3ce44SJohn Forte 	}
596fcf3ce44SJohn Forte 
5978f23e9faSHans Rosenfeld 	/* Move memput list to memget list */
5988f23e9faSHans Rosenfeld 	if (seg->fc_memput_ptr) {
5998f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == NULL) {
6008f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = seg->fc_memput_ptr;
6018f23e9faSHans Rosenfeld 		} else {
6028f23e9faSHans Rosenfeld 			*((uint8_t **)(seg->fc_memget_end)) =\
6038f23e9faSHans Rosenfeld 			    seg->fc_memput_ptr;
6048f23e9faSHans Rosenfeld 		}
6058f23e9faSHans Rosenfeld 		seg->fc_memget_end = seg->fc_memput_end;
6068f23e9faSHans Rosenfeld 		seg->fc_memget_cnt += seg->fc_memput_cnt;
607fcf3ce44SJohn Forte 
6088f23e9faSHans Rosenfeld 		seg->fc_memput_ptr = NULL;
6098f23e9faSHans Rosenfeld 		seg->fc_memput_end = NULL;
6108f23e9faSHans Rosenfeld 		seg->fc_memput_cnt = 0;
6118f23e9faSHans Rosenfeld 	}
612fcf3ce44SJohn Forte 
6138f23e9faSHans Rosenfeld 	buf_info = &local_buf_info;
614fcf3ce44SJohn Forte 
6158f23e9faSHans Rosenfeld 	/* Check for final deallocation */
6168f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
6178f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
6188f23e9faSHans Rosenfeld 		    "%s free:%d n=%d s=%d f=%x l=%d,%d,%d "
6198f23e9faSHans Rosenfeld 		    "f=%d:%d",
6208f23e9faSHans Rosenfeld 		    seg->fc_label, count, seg->fc_numblks,
6218f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
6228f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
6238f23e9faSHans Rosenfeld 		    seg->fc_low);
6248f23e9faSHans Rosenfeld 	}
625fcf3ce44SJohn Forte 
6268f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
6278f23e9faSHans Rosenfeld 		goto vmem_pool;
62882527734SSukumar Swaminathan 	}
629fcf3ce44SJohn Forte 
6308f23e9faSHans Rosenfeld dma_pool:
631fcf3ce44SJohn Forte 
63282527734SSukumar Swaminathan 	/* Free memory associated with all buffers on get buffer pool */
6338f23e9faSHans Rosenfeld 	while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
6348f23e9faSHans Rosenfeld 		/* Remove buffer from list */
6358f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == bp) {
6368f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = NULL;
6378f23e9faSHans Rosenfeld 			seg->fc_memget_end = NULL;
6388f23e9faSHans Rosenfeld 			seg->fc_memget_cnt = 0;
6398f23e9faSHans Rosenfeld 
6408f23e9faSHans Rosenfeld 		} else {
6418f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = *((uint8_t **)bp);
6428f23e9faSHans Rosenfeld 			seg->fc_memget_cnt--;
6438f23e9faSHans Rosenfeld 		}
64482527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
645fcf3ce44SJohn Forte 
6468f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
6478f23e9faSHans Rosenfeld 		if (mp->tag >= MEM_FCTSEG) {
6488f23e9faSHans Rosenfeld 			emlxs_fct_stmf_free(hba, mp);
6498f23e9faSHans Rosenfeld 		}
6508f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
6518f23e9faSHans Rosenfeld 
6528f23e9faSHans Rosenfeld 		/* Free the DMA memory itself */
65382527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
65482527734SSukumar Swaminathan 		buf_info->size = mp->size;
65582527734SSukumar Swaminathan 		buf_info->virt = mp->virt;
65682527734SSukumar Swaminathan 		buf_info->phys = mp->phys;
65782527734SSukumar Swaminathan 		buf_info->dma_handle = mp->dma_handle;
65882527734SSukumar Swaminathan 		buf_info->data_handle = mp->data_handle;
65982527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
66082527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
661fcf3ce44SJohn Forte 
6628f23e9faSHans Rosenfeld 		/* Free the handle */
66382527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
66482527734SSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
665a9800bebSGarrett D'Amore 		buf_info->virt = (void *)mp;
66682527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
6678f23e9faSHans Rosenfeld 
6688f23e9faSHans Rosenfeld 		seg->fc_numblks--;
6698f23e9faSHans Rosenfeld 		seg->fc_total_memsize -= (seg->fc_memsize + sizeof (MATCHMAP));
6708f23e9faSHans Rosenfeld 
6718f23e9faSHans Rosenfeld 		count--;
672fcf3ce44SJohn Forte 	}
673291a2b48SSukumar Swaminathan 
6748f23e9faSHans Rosenfeld 	return;
675fcf3ce44SJohn Forte 
6768f23e9faSHans Rosenfeld vmem_pool:
677291a2b48SSukumar Swaminathan 
6788f23e9faSHans Rosenfeld 	/* Free memory associated with all buffers on get buffer pool */
6798f23e9faSHans Rosenfeld 	while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
6808f23e9faSHans Rosenfeld 		/* Remove buffer from list */
6818f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == bp) {
6828f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = NULL;
6838f23e9faSHans Rosenfeld 			seg->fc_memget_end = NULL;
6848f23e9faSHans Rosenfeld 			seg->fc_memget_cnt = 0;
6858f23e9faSHans Rosenfeld 
6868f23e9faSHans Rosenfeld 		} else {
6878f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = *((uint8_t **)bp);
6888f23e9faSHans Rosenfeld 			seg->fc_memget_cnt--;
6898f23e9faSHans Rosenfeld 		}
6908f23e9faSHans Rosenfeld 
6918f23e9faSHans Rosenfeld 		/* Free the Virtual memory itself */
69282527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
6938f23e9faSHans Rosenfeld 		buf_info->size = seg->fc_memsize;
6948f23e9faSHans Rosenfeld 		buf_info->virt = bp;
69582527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
6968f23e9faSHans Rosenfeld 
6978f23e9faSHans Rosenfeld 		seg->fc_numblks--;
6988f23e9faSHans Rosenfeld 		seg->fc_total_memsize -= seg->fc_memsize;
6998f23e9faSHans Rosenfeld 
7008f23e9faSHans Rosenfeld 		count--;
701291a2b48SSukumar Swaminathan 	}
702fcf3ce44SJohn Forte 
70382527734SSukumar Swaminathan 	return;
704fcf3ce44SJohn Forte 
70582527734SSukumar Swaminathan } /* emlxs_mem_pool_free() */
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 
7088f23e9faSHans Rosenfeld extern uint32_t
7098f23e9faSHans Rosenfeld emlxs_mem_pool_create(emlxs_hba_t *hba, MEMSEG *seg)
71082527734SSukumar Swaminathan {
7118f23e9faSHans Rosenfeld 	emlxs_config_t *cfg = &CFG;
712291a2b48SSukumar Swaminathan 
71382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
7148f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
71582527734SSukumar Swaminathan 
7168f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
7178f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
71882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMGET_LOCK);
7198f23e9faSHans Rosenfeld 
7208f23e9faSHans Rosenfeld 		return (0);
7218f23e9faSHans Rosenfeld 	}
7228f23e9faSHans Rosenfeld 
7238f23e9faSHans Rosenfeld 	/* Sanity check hi > lo */
7248f23e9faSHans Rosenfeld 	if (seg->fc_lo_water > seg->fc_hi_water) {
7258f23e9faSHans Rosenfeld 		seg->fc_hi_water = seg->fc_lo_water;
7268f23e9faSHans Rosenfeld 	}
7278f23e9faSHans Rosenfeld 
7288f23e9faSHans Rosenfeld 	/* If dynamic pools are disabled, then force pool to max level */
7298f23e9faSHans Rosenfeld 	if (cfg[CFG_MEM_DYNAMIC].current == 0) {
7308f23e9faSHans Rosenfeld 		seg->fc_lo_water = seg->fc_hi_water;
731fcf3ce44SJohn Forte 	}
732291a2b48SSukumar Swaminathan 
7338f23e9faSHans Rosenfeld 	/* If pool is dynamic, then fc_step must be >0 */
7348f23e9faSHans Rosenfeld 	/* Otherwise, fc_step must be 0 */
7358f23e9faSHans Rosenfeld 	if (seg->fc_lo_water != seg->fc_hi_water) {
7368f23e9faSHans Rosenfeld 		seg->fc_memflag |= FC_MEMSEG_DYNAMIC;
737fcf3ce44SJohn Forte 
7388f23e9faSHans Rosenfeld 		if (seg->fc_step == 0) {
7398f23e9faSHans Rosenfeld 			seg->fc_step = 1;
74082527734SSukumar Swaminathan 		}
7418f23e9faSHans Rosenfeld 	} else {
7428f23e9faSHans Rosenfeld 		seg->fc_step = 0;
74382527734SSukumar Swaminathan 	}
744fcf3ce44SJohn Forte 
7458f23e9faSHans Rosenfeld 	seg->fc_numblks = 0;
7468f23e9faSHans Rosenfeld 	seg->fc_total_memsize = 0;
7478f23e9faSHans Rosenfeld 	seg->fc_low = 0;
748fcf3ce44SJohn Forte 
749*a3170057SPaul Winder 	(void) emlxs_mem_pool_alloc(hba, seg, seg->fc_lo_water);
750fcf3ce44SJohn Forte 
7518f23e9faSHans Rosenfeld 	seg->fc_memflag |= (FC_MEMSEG_PUT_ENABLED|FC_MEMSEG_GET_ENABLED);
752291a2b48SSukumar Swaminathan 
7538f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
7548f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
755fcf3ce44SJohn Forte 
7568f23e9faSHans Rosenfeld 	return (seg->fc_numblks);
7578f23e9faSHans Rosenfeld 
7588f23e9faSHans Rosenfeld } /* emlxs_mem_pool_create() */
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 
7618f23e9faSHans Rosenfeld extern void
7628f23e9faSHans Rosenfeld emlxs_mem_pool_destroy(emlxs_hba_t *hba, MEMSEG *seg)
7638f23e9faSHans Rosenfeld {
7648f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
7658f23e9faSHans Rosenfeld 
7668f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
7678f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
7688f23e9faSHans Rosenfeld 
7698f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
7708f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
7718f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
7728f23e9faSHans Rosenfeld 		return;
7738f23e9faSHans Rosenfeld 	}
7748f23e9faSHans Rosenfeld 
7758f23e9faSHans Rosenfeld 	/* Leave FC_MEMSEG_PUT_ENABLED set for now */
7768f23e9faSHans Rosenfeld 	seg->fc_memflag &= ~FC_MEMSEG_GET_ENABLED;
7778f23e9faSHans Rosenfeld 
7788f23e9faSHans Rosenfeld 	/* Try to free all objects */
7798f23e9faSHans Rosenfeld 	emlxs_mem_pool_free(hba, seg, seg->fc_numblks);
7808f23e9faSHans Rosenfeld 
7818f23e9faSHans Rosenfeld 	if (seg->fc_numblks) {
7828f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
7838f23e9faSHans Rosenfeld 		    "mem_pool_destroy: %s leak detected: "
7848f23e9faSHans Rosenfeld 		    "%d objects still allocated.",
7858f23e9faSHans Rosenfeld 		    seg->fc_label, seg->fc_numblks);
78682527734SSukumar Swaminathan 	} else {
7878f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
7888f23e9faSHans Rosenfeld 		    "mem_pool_destroy: %s destroyed.",
7898f23e9faSHans Rosenfeld 		    seg->fc_label);
7908f23e9faSHans Rosenfeld 
7918f23e9faSHans Rosenfeld 		/* Clear all */
7928f23e9faSHans Rosenfeld 		bzero(seg, sizeof (MEMSEG));
7938f23e9faSHans Rosenfeld 	}
7948f23e9faSHans Rosenfeld 
7958f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
7968f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
7978f23e9faSHans Rosenfeld 
7988f23e9faSHans Rosenfeld 	return;
7998f23e9faSHans Rosenfeld 
8008f23e9faSHans Rosenfeld } /* emlxs_mem_pool_destroy() */
8018f23e9faSHans Rosenfeld 
8028f23e9faSHans Rosenfeld 
8038f23e9faSHans Rosenfeld extern void
8048f23e9faSHans Rosenfeld emlxs_mem_pool_clean(emlxs_hba_t *hba, MEMSEG *seg)
8058f23e9faSHans Rosenfeld {
8068f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
8078f23e9faSHans Rosenfeld 	uint32_t clean_count;
8088f23e9faSHans Rosenfeld 	uint32_t free_count;
8098f23e9faSHans Rosenfeld 	uint32_t free_pad;
8108f23e9faSHans Rosenfeld 
8118f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
8128f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
8138f23e9faSHans Rosenfeld 
8148f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
8158f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
8168f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
8178f23e9faSHans Rosenfeld 		return;
8188f23e9faSHans Rosenfeld 	}
8198f23e9faSHans Rosenfeld 
8208f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
8218f23e9faSHans Rosenfeld 		goto done;
8228f23e9faSHans Rosenfeld 	}
8238f23e9faSHans Rosenfeld 
8248f23e9faSHans Rosenfeld #ifdef EMLXS_POOL_DEBUG
8258f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
8268f23e9faSHans Rosenfeld 	    "%s clean: n=%d s=%d f=%x l=%d,%d,%d "
8278f23e9faSHans Rosenfeld 	    "f=%d:%d",
8288f23e9faSHans Rosenfeld 	    seg->fc_label, seg->fc_numblks,
8298f23e9faSHans Rosenfeld 	    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
8308f23e9faSHans Rosenfeld 	    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
8318f23e9faSHans Rosenfeld 	    seg->fc_low);
8328f23e9faSHans Rosenfeld #endif /* EMLXS_POOL_DEBUG */
8338f23e9faSHans Rosenfeld 
8348f23e9faSHans Rosenfeld 	/* Calculatge current free count */
8358f23e9faSHans Rosenfeld 	free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
8368f23e9faSHans Rosenfeld 
8378f23e9faSHans Rosenfeld 	/* Reset fc_low value to current free count */
8388f23e9faSHans Rosenfeld 	clean_count = seg->fc_low;
8398f23e9faSHans Rosenfeld 	seg->fc_low = free_count;
8408f23e9faSHans Rosenfeld 
8418f23e9faSHans Rosenfeld 	/* Return if pool is already at lo water mark */
8428f23e9faSHans Rosenfeld 	if (seg->fc_numblks <= seg->fc_lo_water) {
8438f23e9faSHans Rosenfeld 		goto done;
8448f23e9faSHans Rosenfeld 	}
8458f23e9faSHans Rosenfeld 
8468f23e9faSHans Rosenfeld 	/* Return if there is nothing to clean */
8478f23e9faSHans Rosenfeld 	if ((free_count == 0) ||
8488f23e9faSHans Rosenfeld 	    (clean_count <= 1)) {
8498f23e9faSHans Rosenfeld 		goto done;
8508f23e9faSHans Rosenfeld 	}
8518f23e9faSHans Rosenfeld 
8528f23e9faSHans Rosenfeld 	/* Calculate a 3 percent free pad count (1 being minimum) */
8538f23e9faSHans Rosenfeld 	if (seg->fc_numblks > 66) {
8548f23e9faSHans Rosenfeld 		free_pad = ((seg->fc_numblks * 3)/100);
8558f23e9faSHans Rosenfeld 	} else {
8568f23e9faSHans Rosenfeld 		free_pad = 1;
8578f23e9faSHans Rosenfeld 	}
8588f23e9faSHans Rosenfeld 
8598f23e9faSHans Rosenfeld 	/* Return if fc_low is below pool free pad */
8608f23e9faSHans Rosenfeld 	if (clean_count <= free_pad) {
8618f23e9faSHans Rosenfeld 		goto done;
8628f23e9faSHans Rosenfeld 	}
8638f23e9faSHans Rosenfeld 
8648f23e9faSHans Rosenfeld 	clean_count -= free_pad;
8658f23e9faSHans Rosenfeld 
8668f23e9faSHans Rosenfeld 	/* clean_count can't exceed minimum pool levels */
8678f23e9faSHans Rosenfeld 	if (clean_count > (seg->fc_numblks - seg->fc_lo_water)) {
8688f23e9faSHans Rosenfeld 		clean_count = (seg->fc_numblks - seg->fc_lo_water);
8698f23e9faSHans Rosenfeld 	}
8708f23e9faSHans Rosenfeld 
8718f23e9faSHans Rosenfeld 	emlxs_mem_pool_free(hba, seg, clean_count);
8728f23e9faSHans Rosenfeld 
8738f23e9faSHans Rosenfeld done:
8748f23e9faSHans Rosenfeld 	if (seg->fc_last != seg->fc_numblks) {
8758f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
8768f23e9faSHans Rosenfeld 		    "%s update: n=%d->%d s=%d f=%x l=%d,%d,%d "
8778f23e9faSHans Rosenfeld 		    "f=%d:%d",
8788f23e9faSHans Rosenfeld 		    seg->fc_label, seg->fc_last, seg->fc_numblks,
8798f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
8808f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
8818f23e9faSHans Rosenfeld 		    seg->fc_low);
8828f23e9faSHans Rosenfeld 
8838f23e9faSHans Rosenfeld 		seg->fc_last = seg->fc_numblks;
8848f23e9faSHans Rosenfeld 	}
8858f23e9faSHans Rosenfeld 
8868f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
8878f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
8888f23e9faSHans Rosenfeld 	return;
8898f23e9faSHans Rosenfeld 
8908f23e9faSHans Rosenfeld } /* emlxs_mem_pool_clean() */
8918f23e9faSHans Rosenfeld 
8928f23e9faSHans Rosenfeld 
8938f23e9faSHans Rosenfeld extern void *
8948f23e9faSHans Rosenfeld emlxs_mem_pool_get(emlxs_hba_t *hba, MEMSEG *seg)
8958f23e9faSHans Rosenfeld {
8968f23e9faSHans Rosenfeld 	emlxs_port_t	*port = &PPORT;
8978f23e9faSHans Rosenfeld 	void		*bp = NULL;
8988f23e9faSHans Rosenfeld 	MATCHMAP	*mp;
8998f23e9faSHans Rosenfeld 	uint32_t	free_count;
9008f23e9faSHans Rosenfeld 
9018f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
9028f23e9faSHans Rosenfeld 
9038f23e9faSHans Rosenfeld 	/* Check if memory pool is GET enabled */
9048f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
9058f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
9068f23e9faSHans Rosenfeld 		return (NULL);
9078f23e9faSHans Rosenfeld 	}
9088f23e9faSHans Rosenfeld 
9098f23e9faSHans Rosenfeld 	/* If no entries on memget list, then check memput list */
9108f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr) {
91182527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MEMPUT_LOCK);
91282527734SSukumar Swaminathan 		if (seg->fc_memput_ptr) {
91382527734SSukumar Swaminathan 			/*
91482527734SSukumar Swaminathan 			 * Move list from memput to memget
91582527734SSukumar Swaminathan 			 */
91682527734SSukumar Swaminathan 			seg->fc_memget_ptr = seg->fc_memput_ptr;
91782527734SSukumar Swaminathan 			seg->fc_memget_end = seg->fc_memput_end;
91882527734SSukumar Swaminathan 			seg->fc_memget_cnt = seg->fc_memput_cnt;
91982527734SSukumar Swaminathan 			seg->fc_memput_ptr = NULL;
92082527734SSukumar Swaminathan 			seg->fc_memput_end = NULL;
92182527734SSukumar Swaminathan 			seg->fc_memput_cnt = 0;
922fcf3ce44SJohn Forte 		}
92382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
9248f23e9faSHans Rosenfeld 	}
9258f23e9faSHans Rosenfeld 
9268f23e9faSHans Rosenfeld 	/* If no entries on memget list, then pool is empty */
9278f23e9faSHans Rosenfeld 	/* Try to allocate more if pool is dynamic */
9288f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr &&
9298f23e9faSHans Rosenfeld 	    (seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
9308f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_alloc(hba, seg,  seg->fc_step);
9318f23e9faSHans Rosenfeld 		seg->fc_low = 0;
9328f23e9faSHans Rosenfeld 	}
93382527734SSukumar Swaminathan 
9348f23e9faSHans Rosenfeld 	/* If no entries on memget list, then pool is empty */
9358f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr) {
93682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
93782527734SSukumar Swaminathan 		    "%s empty.", seg->fc_label);
9388f23e9faSHans Rosenfeld 
9398f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
9408f23e9faSHans Rosenfeld 		return (NULL);
9418f23e9faSHans Rosenfeld 	}
9428f23e9faSHans Rosenfeld 
9438f23e9faSHans Rosenfeld 	/* Remove an entry from the get list */
9448f23e9faSHans Rosenfeld 	bp = seg->fc_memget_ptr;
9458f23e9faSHans Rosenfeld 
9468f23e9faSHans Rosenfeld 	if (seg->fc_memget_end == bp) {
9478f23e9faSHans Rosenfeld 		seg->fc_memget_ptr = NULL;
9488f23e9faSHans Rosenfeld 		seg->fc_memget_end = NULL;
9498f23e9faSHans Rosenfeld 		seg->fc_memget_cnt = 0;
9508f23e9faSHans Rosenfeld 
9518f23e9faSHans Rosenfeld 	} else {
9528f23e9faSHans Rosenfeld 		seg->fc_memget_ptr = *((uint8_t **)bp);
9538f23e9faSHans Rosenfeld 		seg->fc_memget_cnt--;
9548f23e9faSHans Rosenfeld 	}
9558f23e9faSHans Rosenfeld 
9568f23e9faSHans Rosenfeld 	/* Initialize buffer */
9578f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
9588f23e9faSHans Rosenfeld 		bzero(bp, seg->fc_memsize);
9598f23e9faSHans Rosenfeld 	} else {
9608f23e9faSHans Rosenfeld 		mp = (MATCHMAP *)bp;
9618f23e9faSHans Rosenfeld 		mp->fc_mptr = NULL;
9628f23e9faSHans Rosenfeld 		mp->flag |= MAP_POOL_ALLOCATED;
9638f23e9faSHans Rosenfeld 	}
9648f23e9faSHans Rosenfeld 
9658f23e9faSHans Rosenfeld 	/* Set fc_low if pool is dynamic */
9668f23e9faSHans Rosenfeld 	if (seg->fc_memflag & FC_MEMSEG_DYNAMIC) {
9678f23e9faSHans Rosenfeld 		free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
9688f23e9faSHans Rosenfeld 		if (free_count < seg->fc_low) {
9698f23e9faSHans Rosenfeld 			seg->fc_low = free_count;
9708f23e9faSHans Rosenfeld 		}
971fcf3ce44SJohn Forte 	}
972fcf3ce44SJohn Forte 
97382527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
97482527734SSukumar Swaminathan 
97582527734SSukumar Swaminathan 	return (bp);
976fcf3ce44SJohn Forte 
97782527734SSukumar Swaminathan } /* emlxs_mem_pool_get() */
978fcf3ce44SJohn Forte 
979fcf3ce44SJohn Forte 
980a9800bebSGarrett D'Amore extern void
981a9800bebSGarrett D'Amore emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, void *bp)
98282527734SSukumar Swaminathan {
983a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
984a9800bebSGarrett D'Amore 	MATCHMAP	*mp;
985fcf3ce44SJohn Forte 
98682527734SSukumar Swaminathan 	/* Free the pool object */
98782527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
98882527734SSukumar Swaminathan 
9898f23e9faSHans Rosenfeld 	/* Check if memory pool is PUT enabled */
9908f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
99182527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
992a9800bebSGarrett D'Amore 		return;
993fcf3ce44SJohn Forte 	}
994291a2b48SSukumar Swaminathan 
99582527734SSukumar Swaminathan 	/* Check if buffer was just freed */
9968f23e9faSHans Rosenfeld 	if ((seg->fc_memput_end == bp) || (seg->fc_memget_end == bp)) {
99782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
99882527734SSukumar Swaminathan 		    "%s: Freeing free object: bp=%p", seg->fc_label, bp);
999fcf3ce44SJohn Forte 
100082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
1001a9800bebSGarrett D'Amore 		return;
1002fcf3ce44SJohn Forte 	}
1003fcf3ce44SJohn Forte 
10048f23e9faSHans Rosenfeld 	/* Validate DMA buffer */
100582527734SSukumar Swaminathan 	if (seg->fc_memflag & FC_MBUF_DMA) {
100682527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
1007291a2b48SSukumar Swaminathan 
100882527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED) ||
100982527734SSukumar Swaminathan 		    (mp->segment != seg)) {
101082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
10118f23e9faSHans Rosenfeld 			    "mem_pool_put: %s invalid: mp=%p " \
101282527734SSukumar Swaminathan 			    "tag=0x%x flag=%x", seg->fc_label,
101382527734SSukumar Swaminathan 			    mp, mp->tag, mp->flag);
1014291a2b48SSukumar Swaminathan 
101582527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1016fcf3ce44SJohn Forte 
101782527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMPUT_LOCK);
1018fcf3ce44SJohn Forte 
101982527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
102082527734SSukumar Swaminathan 			    NULL, NULL);
102182527734SSukumar Swaminathan 
1022a9800bebSGarrett D'Amore 			return;
1023fcf3ce44SJohn Forte 		}
1024fcf3ce44SJohn Forte 	}
1025fcf3ce44SJohn Forte 
10268f23e9faSHans Rosenfeld 	/* Release buffer to the end of the memput list */
102782527734SSukumar Swaminathan 	if (seg->fc_memput_end == NULL) {
102882527734SSukumar Swaminathan 		seg->fc_memput_ptr = bp;
102982527734SSukumar Swaminathan 		seg->fc_memput_cnt = 1;
103082527734SSukumar Swaminathan 	} else {
1031a9800bebSGarrett D'Amore 		*((void **)(seg->fc_memput_end)) = bp;
103282527734SSukumar Swaminathan 		seg->fc_memput_cnt++;
103382527734SSukumar Swaminathan 	}
103482527734SSukumar Swaminathan 	seg->fc_memput_end = bp;
1035a9800bebSGarrett D'Amore 	*((void **)(bp)) = NULL;
103682527734SSukumar Swaminathan 
103782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
1038fcf3ce44SJohn Forte 
10398f23e9faSHans Rosenfeld 	/* This is for late PUT's after an initial */
10408f23e9faSHans Rosenfeld 	/* emlxs_mem_pool_destroy call */
10418f23e9faSHans Rosenfeld 	if ((seg->fc_memflag & FC_MEMSEG_PUT_ENABLED) &&
10428f23e9faSHans Rosenfeld 	    !(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
10438f23e9faSHans Rosenfeld 		emlxs_mem_pool_destroy(hba, seg);
10448f23e9faSHans Rosenfeld 	}
10458f23e9faSHans Rosenfeld 
1046a9800bebSGarrett D'Amore 	return;
1047fcf3ce44SJohn Forte 
104882527734SSukumar Swaminathan } /* emlxs_mem_pool_put() */
1049fcf3ce44SJohn Forte 
105082527734SSukumar Swaminathan 
105182527734SSukumar Swaminathan extern MATCHMAP *
105282527734SSukumar Swaminathan emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size)
1053fcf3ce44SJohn Forte {
1054fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1055fcf3ce44SJohn Forte 	uint8_t *bp = NULL;
105682527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
1057fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1058fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1059fcf3ce44SJohn Forte 
1060fcf3ce44SJohn Forte 	buf_info = &bufinfo;
1061fcf3ce44SJohn Forte 
1062fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
1063fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
1064fcf3ce44SJohn Forte 	buf_info->align = sizeof (void *);
1065fcf3ce44SJohn Forte 
1066fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
1067fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
1068fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1069fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC buffer.");
1070fcf3ce44SJohn Forte 
107182527734SSukumar Swaminathan 		return (NULL);
1072fcf3ce44SJohn Forte 	}
1073291a2b48SSukumar Swaminathan 
107482527734SSukumar Swaminathan 	mp = (MATCHMAP *)buf_info->virt;
107582527734SSukumar Swaminathan 	bzero(mp, sizeof (MATCHMAP));
1076fcf3ce44SJohn Forte 
1077fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
107882527734SSukumar Swaminathan 	buf_info->size = size;
1079*a3170057SPaul Winder 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG;
1080fcf3ce44SJohn Forte 	buf_info->align = 32;
1081fcf3ce44SJohn Forte 
1082fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
1083fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
1084fcf3ce44SJohn Forte 
1085fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1086fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC DMA buffer.");
1087fcf3ce44SJohn Forte 
108882527734SSukumar Swaminathan 		/* Free the mp object */
1089728bdc9bSSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1090728bdc9bSSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
1091a9800bebSGarrett D'Amore 		buf_info->virt = (void *)mp;
1092728bdc9bSSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
1093728bdc9bSSukumar Swaminathan 
1094*a3170057SPaul Winder 		return (NULL);
1095fcf3ce44SJohn Forte 	}
1096fcf3ce44SJohn Forte 	bp = (uint8_t *)buf_info->virt;
10978f23e9faSHans Rosenfeld 	bzero(bp, buf_info->size);
1098fcf3ce44SJohn Forte 
109982527734SSukumar Swaminathan 	mp->virt = buf_info->virt;
110082527734SSukumar Swaminathan 	mp->phys = buf_info->phys;
110182527734SSukumar Swaminathan 	mp->size = buf_info->size;
110282527734SSukumar Swaminathan 	mp->dma_handle = buf_info->dma_handle;
110382527734SSukumar Swaminathan 	mp->data_handle = buf_info->data_handle;
110482527734SSukumar Swaminathan 	mp->tag = MEM_BUF;
110582527734SSukumar Swaminathan 	mp->flag |= MAP_BUF_ALLOCATED;
1106fcf3ce44SJohn Forte 
110782527734SSukumar Swaminathan 	return (mp);
1108fcf3ce44SJohn Forte 
110982527734SSukumar Swaminathan } /* emlxs_mem_buf_alloc() */
1110fcf3ce44SJohn Forte 
1111fcf3ce44SJohn Forte 
1112a9800bebSGarrett D'Amore extern void
111382527734SSukumar Swaminathan emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp)
1114fcf3ce44SJohn Forte {
1115fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1116fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1117fcf3ce44SJohn Forte 
1118fcf3ce44SJohn Forte 	buf_info = &bufinfo;
1119fcf3ce44SJohn Forte 
112082527734SSukumar Swaminathan 	if (!(mp->flag & MAP_BUF_ALLOCATED)) {
1121a9800bebSGarrett D'Amore 		return;
1122fcf3ce44SJohn Forte 	}
1123fcf3ce44SJohn Forte 
1124fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
112582527734SSukumar Swaminathan 	buf_info->size = mp->size;
112682527734SSukumar Swaminathan 	buf_info->virt = mp->virt;
112782527734SSukumar Swaminathan 	buf_info->phys = mp->phys;
112882527734SSukumar Swaminathan 	buf_info->dma_handle = mp->dma_handle;
112982527734SSukumar Swaminathan 	buf_info->data_handle = mp->data_handle;
1130fcf3ce44SJohn Forte 	buf_info->flags = FC_MBUF_DMA;
1131fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
1132fcf3ce44SJohn Forte 
1133fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
1134fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
1135a9800bebSGarrett D'Amore 	buf_info->virt = (void *)mp;
1136fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
1137fcf3ce44SJohn Forte 
1138a9800bebSGarrett D'Amore 	return;
1139fcf3ce44SJohn Forte 
114082527734SSukumar Swaminathan } /* emlxs_mem_buf_free() */
1141fcf3ce44SJohn Forte 
1142fcf3ce44SJohn Forte 
1143a9800bebSGarrett D'Amore extern void *
11448f23e9faSHans Rosenfeld emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id)
1145fcf3ce44SJohn Forte {
1146a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
1147a9800bebSGarrett D'Amore 	void		*bp;
1148a9800bebSGarrett D'Amore 	MAILBOXQ	*mbq;
1149a9800bebSGarrett D'Amore 	IOCBQ		*iocbq;
1150a9800bebSGarrett D'Amore 	NODELIST	*node;
1151a9800bebSGarrett D'Amore 	MEMSEG		*seg;
1152fcf3ce44SJohn Forte 
115382527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
1154291a2b48SSukumar Swaminathan 
115582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
11568f23e9faSHans Rosenfeld 		    "mem_get: Invalid segment id = %d",
115782527734SSukumar Swaminathan 		    seg_id);
1158fcf3ce44SJohn Forte 
1159fcf3ce44SJohn Forte 		return (NULL);
1160fcf3ce44SJohn Forte 	}
116182527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
1162fcf3ce44SJohn Forte 
116382527734SSukumar Swaminathan 	/* Alloc a buffer from the pool */
11648f23e9faSHans Rosenfeld 	bp = emlxs_mem_pool_get(hba, seg);
1165fcf3ce44SJohn Forte 
116682527734SSukumar Swaminathan 	if (bp) {
116782527734SSukumar Swaminathan 		switch (seg_id) {
1168fcf3ce44SJohn Forte 		case MEM_MBOX:
1169291a2b48SSukumar Swaminathan 			mbq = (MAILBOXQ *)bp;
1170fcf3ce44SJohn Forte 			mbq->flag |= MBQ_POOL_ALLOCATED;
1171fcf3ce44SJohn Forte 			break;
1172fcf3ce44SJohn Forte 
1173fcf3ce44SJohn Forte 		case MEM_IOCB:
1174291a2b48SSukumar Swaminathan 			iocbq = (IOCBQ *)bp;
1175fcf3ce44SJohn Forte 			iocbq->flag |= IOCB_POOL_ALLOCATED;
1176fcf3ce44SJohn Forte 			break;
1177fcf3ce44SJohn Forte 
1178fcf3ce44SJohn Forte 		case MEM_NLP:
1179291a2b48SSukumar Swaminathan 			node = (NODELIST *)bp;
1180fcf3ce44SJohn Forte 			node->flag |= NODE_POOL_ALLOCATED;
1181fcf3ce44SJohn Forte 			break;
1182fcf3ce44SJohn Forte 		}
1183fcf3ce44SJohn Forte 	}
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 	return (bp);
1186fcf3ce44SJohn Forte 
118782527734SSukumar Swaminathan } /* emlxs_mem_get() */
1188fcf3ce44SJohn Forte 
1189fcf3ce44SJohn Forte 
1190a9800bebSGarrett D'Amore extern void
1191a9800bebSGarrett D'Amore emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, void *bp)
1192fcf3ce44SJohn Forte {
1193a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
1194a9800bebSGarrett D'Amore 	MAILBOXQ	*mbq;
1195a9800bebSGarrett D'Amore 	IOCBQ		*iocbq;
1196a9800bebSGarrett D'Amore 	NODELIST	*node;
1197a9800bebSGarrett D'Amore 	MEMSEG		*seg;
1198a9800bebSGarrett D'Amore 	MATCHMAP	*mp;
1199fcf3ce44SJohn Forte 
120082527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
120182527734SSukumar Swaminathan 
120282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
12038f23e9faSHans Rosenfeld 		    "mem_put: Invalid segment id = %d: bp=%p",
120482527734SSukumar Swaminathan 		    seg_id, bp);
1205291a2b48SSukumar Swaminathan 
1206a9800bebSGarrett D'Amore 		return;
1207fcf3ce44SJohn Forte 	}
120882527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
1209291a2b48SSukumar Swaminathan 
121082527734SSukumar Swaminathan 	/* Verify buffer */
121182527734SSukumar Swaminathan 	switch (seg_id) {
1212fcf3ce44SJohn Forte 	case MEM_MBOX:
1213291a2b48SSukumar Swaminathan 		mbq = (MAILBOXQ *)bp;
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 		if (!(mbq->flag & MBQ_POOL_ALLOCATED)) {
1216a9800bebSGarrett D'Amore 			return;
1217fcf3ce44SJohn Forte 		}
1218fcf3ce44SJohn Forte 		break;
1219fcf3ce44SJohn Forte 
1220fcf3ce44SJohn Forte 	case MEM_IOCB:
1221291a2b48SSukumar Swaminathan 		iocbq = (IOCBQ *)bp;
1222fcf3ce44SJohn Forte 
1223fcf3ce44SJohn Forte 		if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) {
1224a9800bebSGarrett D'Amore 			return;
1225fcf3ce44SJohn Forte 		}
1226291a2b48SSukumar Swaminathan 
1227291a2b48SSukumar Swaminathan 		/* Any IOCBQ with a packet attached did not come */
1228291a2b48SSukumar Swaminathan 		/* from our pool */
1229fcf3ce44SJohn Forte 		if (iocbq->sbp) {
1230a9800bebSGarrett D'Amore 			return;
1231fcf3ce44SJohn Forte 		}
1232fcf3ce44SJohn Forte 		break;
1233fcf3ce44SJohn Forte 
1234fcf3ce44SJohn Forte 	case MEM_NLP:
1235291a2b48SSukumar Swaminathan 		node = (NODELIST *)bp;
1236fcf3ce44SJohn Forte 
1237fcf3ce44SJohn Forte 		if (!(node->flag & NODE_POOL_ALLOCATED)) {
1238a9800bebSGarrett D'Amore 			return;
1239fcf3ce44SJohn Forte 		}
1240fcf3ce44SJohn Forte 		break;
1241fcf3ce44SJohn Forte 
1242fcf3ce44SJohn Forte 	default:
124382527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
1244fcf3ce44SJohn Forte 
124582527734SSukumar Swaminathan 		if (mp->flag & MAP_BUF_ALLOCATED) {
1246a9800bebSGarrett D'Amore 			emlxs_mem_buf_free(hba, mp);
1247a9800bebSGarrett D'Amore 			return;
1248fcf3ce44SJohn Forte 		}
1249291a2b48SSukumar Swaminathan 
125082527734SSukumar Swaminathan 		if (mp->flag & MAP_TABLE_ALLOCATED) {
1251a9800bebSGarrett D'Amore 			return;
1252fcf3ce44SJohn Forte 		}
1253291a2b48SSukumar Swaminathan 
125482527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED)) {
1255a9800bebSGarrett D'Amore 			return;
1256fcf3ce44SJohn Forte 		}
1257fcf3ce44SJohn Forte 		break;
1258fcf3ce44SJohn Forte 	}
1259fcf3ce44SJohn Forte 
126082527734SSukumar Swaminathan 	/* Free a buffer to the pool */
1261a9800bebSGarrett D'Amore 	emlxs_mem_pool_put(hba, seg, bp);
1262291a2b48SSukumar Swaminathan 
1263a9800bebSGarrett D'Amore 	return;
1264fcf3ce44SJohn Forte 
126582527734SSukumar Swaminathan } /* emlxs_mem_put() */
1266fcf3ce44SJohn Forte 
1267fcf3ce44SJohn Forte 
1268fcf3ce44SJohn Forte /*
1269fcf3ce44SJohn Forte  * Look up the virtual address given a mapped address
1270fcf3ce44SJohn Forte  */
127182527734SSukumar Swaminathan /* SLI3 */
1272fcf3ce44SJohn Forte extern MATCHMAP *
1273fcf3ce44SJohn Forte emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp)
1274fcf3ce44SJohn Forte {
1275fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1276fcf3ce44SJohn Forte 	MATCHMAP *prev;
1277fcf3ce44SJohn Forte 	MATCHMAP *mp;
1278fcf3ce44SJohn Forte 
127982527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1280291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1281fcf3ce44SJohn Forte 		prev = 0;
1282fcf3ce44SJohn Forte 
1283fcf3ce44SJohn Forte 		while (mp) {
1284fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1285fcf3ce44SJohn Forte 				if (prev == 0) {
1286fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1287fcf3ce44SJohn Forte 				} else {
1288fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1289fcf3ce44SJohn Forte 				}
1290fcf3ce44SJohn Forte 
1291a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1292a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1293fcf3ce44SJohn Forte 				}
1294291a2b48SSukumar Swaminathan 
1295a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1296fcf3ce44SJohn Forte 
129782527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1298fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1299fcf3ce44SJohn Forte 
1300fcf3ce44SJohn Forte 				HBASTATS.ElsUbPosted--;
1301fcf3ce44SJohn Forte 
1302fcf3ce44SJohn Forte 				return (mp);
1303fcf3ce44SJohn Forte 			}
1304291a2b48SSukumar Swaminathan 
1305fcf3ce44SJohn Forte 			prev = mp;
1306291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1307fcf3ce44SJohn Forte 		}
1308fcf3ce44SJohn Forte 
1309fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1310fcf3ce44SJohn Forte 		    "ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1311fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1312fcf3ce44SJohn Forte 
131382527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1314fcf3ce44SJohn Forte 
1315291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1316fcf3ce44SJohn Forte 		prev = 0;
1317fcf3ce44SJohn Forte 
1318fcf3ce44SJohn Forte 		while (mp) {
1319fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1320fcf3ce44SJohn Forte 				if (prev == 0) {
1321fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1322fcf3ce44SJohn Forte 				} else {
1323fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1324fcf3ce44SJohn Forte 				}
1325fcf3ce44SJohn Forte 
1326a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1327a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1328fcf3ce44SJohn Forte 				}
1329291a2b48SSukumar Swaminathan 
1330a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1331fcf3ce44SJohn Forte 
133282527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1333fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1334fcf3ce44SJohn Forte 
1335fcf3ce44SJohn Forte 				HBASTATS.CtUbPosted--;
1336fcf3ce44SJohn Forte 
1337fcf3ce44SJohn Forte 				return (mp);
1338fcf3ce44SJohn Forte 			}
1339291a2b48SSukumar Swaminathan 
1340fcf3ce44SJohn Forte 			prev = mp;
1341291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1342fcf3ce44SJohn Forte 		}
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1345fcf3ce44SJohn Forte 		    "CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1346fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1347fcf3ce44SJohn Forte 
134882527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1349fcf3ce44SJohn Forte 
1350291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1351fcf3ce44SJohn Forte 		prev = 0;
1352fcf3ce44SJohn Forte 
1353fcf3ce44SJohn Forte 		while (mp) {
1354fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1355fcf3ce44SJohn Forte 				if (prev == 0) {
1356fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1357fcf3ce44SJohn Forte 				} else {
1358fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1359fcf3ce44SJohn Forte 				}
1360fcf3ce44SJohn Forte 
1361a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1362a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1363fcf3ce44SJohn Forte 				}
1364291a2b48SSukumar Swaminathan 
1365a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1366fcf3ce44SJohn Forte 
136782527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1368fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1369fcf3ce44SJohn Forte 
1370fcf3ce44SJohn Forte 				HBASTATS.IpUbPosted--;
1371fcf3ce44SJohn Forte 
1372fcf3ce44SJohn Forte 				return (mp);
1373fcf3ce44SJohn Forte 			}
1374291a2b48SSukumar Swaminathan 
1375fcf3ce44SJohn Forte 			prev = mp;
1376291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1377fcf3ce44SJohn Forte 		}
1378fcf3ce44SJohn Forte 
1379fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1380fcf3ce44SJohn Forte 		    "IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1381fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1382fcf3ce44SJohn Forte 
1383fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
138482527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1385291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1386fcf3ce44SJohn Forte 		prev = 0;
1387fcf3ce44SJohn Forte 
1388fcf3ce44SJohn Forte 		while (mp) {
1389fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1390fcf3ce44SJohn Forte 				if (prev == 0) {
1391fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1392fcf3ce44SJohn Forte 				} else {
1393fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1394fcf3ce44SJohn Forte 				}
1395fcf3ce44SJohn Forte 
1396a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1397a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1398fcf3ce44SJohn Forte 				}
1399291a2b48SSukumar Swaminathan 
1400a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1401fcf3ce44SJohn Forte 
140282527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1403fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1404fcf3ce44SJohn Forte 
1405fcf3ce44SJohn Forte 				HBASTATS.FctUbPosted--;
1406fcf3ce44SJohn Forte 
1407fcf3ce44SJohn Forte 				return (mp);
1408fcf3ce44SJohn Forte 			}
1409291a2b48SSukumar Swaminathan 
1410fcf3ce44SJohn Forte 			prev = mp;
1411291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1412fcf3ce44SJohn Forte 		}
1413fcf3ce44SJohn Forte 
1414fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1415fcf3ce44SJohn Forte 		    "FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1416fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1417fcf3ce44SJohn Forte 
1418291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
1419fcf3ce44SJohn Forte 	}
1420fcf3ce44SJohn Forte 
1421fcf3ce44SJohn Forte 	return (0);
1422fcf3ce44SJohn Forte 
142382527734SSukumar Swaminathan } /* emlxs_mem_get_vaddr() */
1424fcf3ce44SJohn Forte 
1425fcf3ce44SJohn Forte 
1426fcf3ce44SJohn Forte /*
1427291a2b48SSukumar Swaminathan  * Given a virtual address bp, generate the physical mapped address and
1428291a2b48SSukumar Swaminathan  * place it where addr points to. Save the address pair for lookup later.
1429fcf3ce44SJohn Forte  */
143082527734SSukumar Swaminathan /* SLI3 */
1431fcf3ce44SJohn Forte extern void
1432291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp,
1433291a2b48SSukumar Swaminathan     uint32_t *haddr, uint32_t *laddr)
1434fcf3ce44SJohn Forte {
143582527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1436fcf3ce44SJohn Forte 		/*
1437291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1438291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1439291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1440fcf3ce44SJohn Forte 		 */
1441a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1442fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1443a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1444a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1445fcf3ce44SJohn Forte 		} else {
1446291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1447a9800bebSGarrett D'Amore 			    (void *)mp;
1448a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1449fcf3ce44SJohn Forte 		}
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1452291a2b48SSukumar Swaminathan 
1453291a2b48SSukumar Swaminathan 			/* return mapped address */
145482527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1455fcf3ce44SJohn Forte 			/* return mapped address */
145682527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1457fcf3ce44SJohn Forte 		} else {
1458fcf3ce44SJohn Forte 			/* return mapped address */
145982527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1460fcf3ce44SJohn Forte 		}
1461fcf3ce44SJohn Forte 
1462fcf3ce44SJohn Forte 		HBASTATS.ElsUbPosted++;
1463fcf3ce44SJohn Forte 
146482527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1465fcf3ce44SJohn Forte 		/*
1466291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1467291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1468291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1469fcf3ce44SJohn Forte 		 */
1470a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1471fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1472a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1473a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1474fcf3ce44SJohn Forte 		} else {
1475291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1476a9800bebSGarrett D'Amore 			    (void *)mp;
1477a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1478fcf3ce44SJohn Forte 		}
1479fcf3ce44SJohn Forte 
1480fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1481fcf3ce44SJohn Forte 			/* return mapped address */
148282527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1483291a2b48SSukumar Swaminathan 			/* return mapped address */
148482527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1485fcf3ce44SJohn Forte 		} else {
1486fcf3ce44SJohn Forte 			/* return mapped address */
148782527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1488fcf3ce44SJohn Forte 		}
1489fcf3ce44SJohn Forte 
1490fcf3ce44SJohn Forte 		HBASTATS.CtUbPosted++;
1491fcf3ce44SJohn Forte 
1492fcf3ce44SJohn Forte 
149382527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1494fcf3ce44SJohn Forte 		/*
1495291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1496291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1497291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1498fcf3ce44SJohn Forte 		 */
1499a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1500fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1501a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1502a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1503fcf3ce44SJohn Forte 		} else {
1504291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1505a9800bebSGarrett D'Amore 			    (void *)mp;
1506a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1507fcf3ce44SJohn Forte 		}
1508fcf3ce44SJohn Forte 
1509fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1510fcf3ce44SJohn Forte 			/* return mapped address */
151182527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
151282527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1513fcf3ce44SJohn Forte 		} else {
151482527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1515fcf3ce44SJohn Forte 		}
1516fcf3ce44SJohn Forte 
1517fcf3ce44SJohn Forte 		HBASTATS.IpUbPosted++;
1518fcf3ce44SJohn Forte 
1519fcf3ce44SJohn Forte 
1520fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
152182527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1522fcf3ce44SJohn Forte 		/*
1523291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1524291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1525291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1526fcf3ce44SJohn Forte 		 */
1527a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1528fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1529a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1530a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1531fcf3ce44SJohn Forte 		} else {
1532291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1533a9800bebSGarrett D'Amore 			    (void *)mp;
1534a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1535fcf3ce44SJohn Forte 		}
1536fcf3ce44SJohn Forte 
1537fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1538fcf3ce44SJohn Forte 			/* return mapped address */
153982527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1540291a2b48SSukumar Swaminathan 			/* return mapped address */
154182527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1542fcf3ce44SJohn Forte 		} else {
1543fcf3ce44SJohn Forte 			/* return mapped address */
154482527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1545fcf3ce44SJohn Forte 		}
1546fcf3ce44SJohn Forte 
1547fcf3ce44SJohn Forte 		HBASTATS.FctUbPosted++;
154882527734SSukumar Swaminathan 
1549291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
1550fcf3ce44SJohn Forte 	}
155182527734SSukumar Swaminathan } /* emlxs_mem_map_vaddr() */
1552fcf3ce44SJohn Forte 
1553fcf3ce44SJohn Forte 
155482527734SSukumar Swaminathan /* SLI3 */
1555291a2b48SSukumar Swaminathan uint32_t
1556fcf3ce44SJohn Forte emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id)
1557fcf3ce44SJohn Forte {
1558fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1559fcf3ce44SJohn Forte 	HBQ_INIT_t *hbq;
1560fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1561fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1562fcf3ce44SJohn Forte 
156382527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
1564fcf3ce44SJohn Forte 
1565fcf3ce44SJohn Forte 	if (hbq->HBQ_host_buf.virt == 0) {
1566fcf3ce44SJohn Forte 		buf_info = &bufinfo;
1567fcf3ce44SJohn Forte 
1568fcf3ce44SJohn Forte 		/* Get the system's page size in a DDI-compliant way. */
1569fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
1570fcf3ce44SJohn Forte 		buf_info->size = hbq->HBQ_numEntries * sizeof (HBQE_t);
1571fcf3ce44SJohn Forte 		buf_info->flags = FC_MBUF_DMA;
1572fcf3ce44SJohn Forte 		buf_info->align = 4096;
1573fcf3ce44SJohn Forte 
1574fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
1575fcf3ce44SJohn Forte 
1576fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
1577fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
1578fcf3ce44SJohn Forte 			    "Unable to alloc HBQ.");
1579fcf3ce44SJohn Forte 			return (ENOMEM);
1580fcf3ce44SJohn Forte 		}
1581291a2b48SSukumar Swaminathan 
1582a9800bebSGarrett D'Amore 		hbq->HBQ_host_buf.virt = buf_info->virt;
1583fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.phys = buf_info->phys;
1584fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.data_handle = buf_info->data_handle;
1585fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle;
1586fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.size = buf_info->size;
1587fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.tag = hbq_id;
1588fcf3ce44SJohn Forte 
1589fcf3ce44SJohn Forte 		bzero((char *)hbq->HBQ_host_buf.virt, buf_info->size);
1590fcf3ce44SJohn Forte 	}
1591fcf3ce44SJohn Forte 
1592fcf3ce44SJohn Forte 	return (0);
1593fcf3ce44SJohn Forte 
159482527734SSukumar Swaminathan } /* emlxs_hbq_alloc() */
1595