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  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans 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 /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2011 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29*8f23e9faSHans Rosenfeld /* #define EMLXS_POOL_DEBUG */
30*8f23e9faSHans Rosenfeld 
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_MEM_C);
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte 
34*8f23e9faSHans Rosenfeld static uint32_t emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg,
35*8f23e9faSHans Rosenfeld 			uint32_t count);
36*8f23e9faSHans Rosenfeld static void emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count);
37*8f23e9faSHans Rosenfeld 
38*8f23e9faSHans Rosenfeld 
39fcf3ce44SJohn Forte extern int32_t
40fcf3ce44SJohn Forte emlxs_mem_alloc_buffer(emlxs_hba_t *hba)
41fcf3ce44SJohn Forte {
42fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
43fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
44fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
4582527734SSukumar Swaminathan 	MEMSEG *seg;
46fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
47fcf3ce44SJohn Forte 	int32_t i;
4882527734SSukumar Swaminathan 	MATCHMAP *mp;
49*8f23e9faSHans Rosenfeld 	MATCHMAP **bpl_table;
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte 	buf_info = &bufinfo;
52fcf3ce44SJohn Forte 	cfg = &CFG;
53fcf3ce44SJohn Forte 
5482527734SSukumar Swaminathan 	bzero(hba->memseg, sizeof (hba->memseg));
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte 	/* Allocate the fc_table */
57fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
5882527734SSukumar Swaminathan 	buf_info->size = (hba->max_iotag * sizeof (emlxs_buf_t *));
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
61fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
62fcf3ce44SJohn Forte 
63fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
64fcf3ce44SJohn Forte 		    "fc_table buffer.");
65fcf3ce44SJohn Forte 
6682527734SSukumar Swaminathan 		goto failed;
67fcf3ce44SJohn Forte 	}
6882527734SSukumar Swaminathan 	hba->fc_table = buf_info->virt;
6982527734SSukumar Swaminathan 	bzero(hba->fc_table, buf_info->size);
70fcf3ce44SJohn Forte 
7182527734SSukumar Swaminathan 	/* Prepare the memory pools */
7282527734SSukumar Swaminathan 	for (i = 0; i < FC_MAX_SEG; i++) {
7382527734SSukumar Swaminathan 		seg = &hba->memseg[i];
74fcf3ce44SJohn Forte 
7582527734SSukumar Swaminathan 		switch (i) {
7682527734SSukumar Swaminathan 		case MEM_NLP:
77*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "Node Pool",
78*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
7982527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_NLP;
8082527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (NODELIST);
81*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_nodes + 2;
82*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = 2;
83*8f23e9faSHans Rosenfeld 			seg->fc_step = 1;
8482527734SSukumar Swaminathan 			break;
85fcf3ce44SJohn Forte 
8682527734SSukumar Swaminathan 		case MEM_IOCB:
87*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "IOCB Pool",
88*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
8982527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IOCB;
9082527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (IOCBQ);
91*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = cfg[CFG_NUM_IOCBS].current;
92*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
93*8f23e9faSHans Rosenfeld 			seg->fc_step = cfg[CFG_NUM_IOCBS].low;
9482527734SSukumar Swaminathan 			break;
95fcf3ce44SJohn Forte 
9682527734SSukumar Swaminathan 		case MEM_MBOX:
97*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "MBOX Pool",
98*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
9982527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_MBOX;
10082527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (MAILBOXQ);
101*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_nodes + 32;
102*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = 32;
103*8f23e9faSHans Rosenfeld 			seg->fc_step = 1;
10482527734SSukumar Swaminathan 			break;
105fcf3ce44SJohn Forte 
10682527734SSukumar Swaminathan 		case MEM_BPL:
10782527734SSukumar Swaminathan 			if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
10882527734SSukumar Swaminathan 				continue;
10982527734SSukumar Swaminathan 			}
110*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "BPL Pool",
111*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
11282527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BPL;
11382527734SSukumar Swaminathan 			seg->fc_memsize	= hba->sli.sli3.mem_bpl_size;
11482527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
11582527734SSukumar Swaminathan 			seg->fc_memalign = 32;
116*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = hba->max_iotag;
117*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
118*8f23e9faSHans Rosenfeld 			seg->fc_step = cfg[CFG_NUM_IOCBS].low;
11982527734SSukumar Swaminathan 			break;
120fcf3ce44SJohn Forte 
12182527734SSukumar Swaminathan 		case MEM_BUF:
12282527734SSukumar Swaminathan 			/* These are the unsolicited ELS buffers. */
123*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "BUF Pool",
124*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
12582527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BUF;
12682527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_BUF_SIZE;
12782527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
12882527734SSukumar Swaminathan 			seg->fc_memalign = 32;
129*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_ELSBUF_COUNT + MEM_BUF_COUNT;
130*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = MEM_ELSBUF_COUNT;
131*8f23e9faSHans Rosenfeld 			seg->fc_step = 1;
13282527734SSukumar Swaminathan 			break;
133291a2b48SSukumar Swaminathan 
13482527734SSukumar Swaminathan 		case MEM_IPBUF:
13582527734SSukumar Swaminathan 			/* These are the unsolicited IP buffers. */
13682527734SSukumar Swaminathan 			if (cfg[CFG_NETWORK_ON].current == 0) {
13782527734SSukumar Swaminathan 				continue;
13882527734SSukumar Swaminathan 			}
139fcf3ce44SJohn Forte 
140*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "IPBUF Pool",
141*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
14282527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IPBUF;
14382527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_IPBUF_SIZE;
14482527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
14582527734SSukumar Swaminathan 			seg->fc_memalign = 32;
146*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_IPBUF_COUNT;
147*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = 0;
148*8f23e9faSHans Rosenfeld 			seg->fc_step = 4;
14982527734SSukumar Swaminathan 			break;
150fcf3ce44SJohn Forte 
15182527734SSukumar Swaminathan 		case MEM_CTBUF:
15282527734SSukumar Swaminathan 			/* These are the unsolicited CT buffers. */
153*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "CTBUF Pool",
154*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
15582527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_CTBUF;
15682527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_CTBUF_SIZE;
15782527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
15882527734SSukumar Swaminathan 			seg->fc_memalign = 32;
159*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_CTBUF_COUNT;
160*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = MEM_CTBUF_COUNT;
161*8f23e9faSHans Rosenfeld 			seg->fc_step = 1;
16282527734SSukumar Swaminathan 			break;
163fcf3ce44SJohn Forte 
16482527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
165*8f23e9faSHans Rosenfeld 		case MEM_FCTBUF:
16682527734SSukumar Swaminathan 			/* These are the unsolicited FCT buffers. */
167*8f23e9faSHans Rosenfeld 			if (!(port->flag & EMLXS_TGT_ENABLED)) {
16882527734SSukumar Swaminathan 				continue;
16982527734SSukumar Swaminathan 			}
170fcf3ce44SJohn Forte 
171*8f23e9faSHans Rosenfeld 			(void) strlcpy(seg->fc_label, "FCTBUF Pool",
172*8f23e9faSHans Rosenfeld 			    sizeof (seg->fc_label));
17382527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_FCTBUF;
17482527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_FCTBUF_SIZE;
17582527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
17682527734SSukumar Swaminathan 			seg->fc_memalign = 32;
177*8f23e9faSHans Rosenfeld 			seg->fc_hi_water = MEM_FCTBUF_COUNT;
178*8f23e9faSHans Rosenfeld 			seg->fc_lo_water = 0;
179*8f23e9faSHans Rosenfeld 			seg->fc_step = 8;
18082527734SSukumar Swaminathan 			break;
181*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
182fcf3ce44SJohn Forte 
18382527734SSukumar Swaminathan 		default:
18482527734SSukumar Swaminathan 			continue;
185fcf3ce44SJohn Forte 		}
186fcf3ce44SJohn Forte 
18782527734SSukumar Swaminathan 		if (seg->fc_memsize == 0) {
18882527734SSukumar Swaminathan 			continue;
18982527734SSukumar Swaminathan 		}
190fcf3ce44SJohn Forte 
191*8f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_create(hba, seg);
192*8f23e9faSHans Rosenfeld 
193*8f23e9faSHans Rosenfeld 		if (seg->fc_numblks < seg->fc_lo_water) {
194*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
195*8f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d flags=%x lo=%d hi=%d",
196*8f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks,
197*8f23e9faSHans Rosenfeld 			    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
198*8f23e9faSHans Rosenfeld 			    seg->fc_hi_water);
199*8f23e9faSHans Rosenfeld 
200*8f23e9faSHans Rosenfeld 			goto failed;
201*8f23e9faSHans Rosenfeld 		}
202*8f23e9faSHans Rosenfeld 	}
203*8f23e9faSHans Rosenfeld 
204*8f23e9faSHans Rosenfeld 	hba->sli.sli3.bpl_table = NULL;
205*8f23e9faSHans Rosenfeld 	seg = &hba->memseg[MEM_BPL];
206*8f23e9faSHans Rosenfeld 
207*8f23e9faSHans Rosenfeld 	/* If SLI3 and MEM_BPL pool is static */
208*8f23e9faSHans Rosenfeld 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK) &&
209*8f23e9faSHans Rosenfeld 	    !(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
210*8f23e9faSHans Rosenfeld 		/*
211*8f23e9faSHans Rosenfeld 		 * Allocate and Initialize bpl_table
212*8f23e9faSHans Rosenfeld 		 * This is for increased performance.
213*8f23e9faSHans Rosenfeld 		 */
214*8f23e9faSHans Rosenfeld 		bzero(buf_info, sizeof (MBUF_INFO));
215*8f23e9faSHans Rosenfeld 		buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
216*8f23e9faSHans Rosenfeld 
217*8f23e9faSHans Rosenfeld 		(void) emlxs_mem_alloc(hba, buf_info);
218*8f23e9faSHans Rosenfeld 		if (buf_info->virt == NULL) {
219*8f23e9faSHans Rosenfeld 
220*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
221*8f23e9faSHans Rosenfeld 			    &emlxs_mem_alloc_failed_msg,
222*8f23e9faSHans Rosenfeld 			    "BPL table buffer.");
223*8f23e9faSHans Rosenfeld 
22482527734SSukumar Swaminathan 			goto failed;
225fcf3ce44SJohn Forte 		}
226*8f23e9faSHans Rosenfeld 		hba->sli.sli3.bpl_table = buf_info->virt;
227291a2b48SSukumar Swaminathan 
228*8f23e9faSHans Rosenfeld 		bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
229*8f23e9faSHans Rosenfeld 		for (i = 0; i < hba->max_iotag; i++) {
230*8f23e9faSHans Rosenfeld 			mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL);
231*8f23e9faSHans Rosenfeld 			mp->flag |= MAP_TABLE_ALLOCATED;
232*8f23e9faSHans Rosenfeld 			bpl_table[i] = mp;
233*8f23e9faSHans Rosenfeld 		}
234fcf3ce44SJohn Forte 	}
235fcf3ce44SJohn Forte 
23682527734SSukumar Swaminathan 	return (1);
237fcf3ce44SJohn Forte 
23882527734SSukumar Swaminathan failed:
239fcf3ce44SJohn Forte 
24082527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
24182527734SSukumar Swaminathan 	return (0);
242fcf3ce44SJohn Forte 
24382527734SSukumar Swaminathan } /* emlxs_mem_alloc_buffer() */
244fcf3ce44SJohn Forte 
245fcf3ce44SJohn Forte 
24682527734SSukumar Swaminathan /*
24782527734SSukumar Swaminathan  * emlxs_mem_free_buffer
24882527734SSukumar Swaminathan  *
24982527734SSukumar Swaminathan  * This routine will free iocb/data buffer space
25082527734SSukumar Swaminathan  * and TGTM resource.
25182527734SSukumar Swaminathan  */
25282527734SSukumar Swaminathan extern int
25382527734SSukumar Swaminathan emlxs_mem_free_buffer(emlxs_hba_t *hba)
25482527734SSukumar Swaminathan {
255*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
25682527734SSukumar Swaminathan 	emlxs_port_t *vport;
25782527734SSukumar Swaminathan 	int32_t j;
25882527734SSukumar Swaminathan 	MATCHMAP *mp;
25982527734SSukumar Swaminathan 	CHANNEL *cp;
26082527734SSukumar Swaminathan 	RING *rp;
26182527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
26282527734SSukumar Swaminathan 	MBUF_INFO bufinfo;
263*8f23e9faSHans Rosenfeld 	MATCHMAP **bpl_table;
264fcf3ce44SJohn Forte 
26582527734SSukumar Swaminathan 	buf_info = &bufinfo;
266291a2b48SSukumar Swaminathan 
26782527734SSukumar Swaminathan 	for (j = 0; j < hba->chan_count; j++) {
26882527734SSukumar Swaminathan 		cp = &hba->chan[j];
269fcf3ce44SJohn Forte 
27082527734SSukumar Swaminathan 		/* Flush the ring */
27182527734SSukumar Swaminathan 		(void) emlxs_tx_channel_flush(hba, cp, 0);
27282527734SSukumar Swaminathan 	}
273fcf3ce44SJohn Forte 
27482527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
27582527734SSukumar Swaminathan 		/* free the mapped address match area for each ring */
27682527734SSukumar Swaminathan 		for (j = 0; j < MAX_RINGS; j++) {
27782527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[j];
278fcf3ce44SJohn Forte 
27982527734SSukumar Swaminathan 			while (rp->fc_mpoff) {
28082527734SSukumar Swaminathan 				uint64_t addr;
281fcf3ce44SJohn Forte 
28282527734SSukumar Swaminathan 				addr = 0;
28382527734SSukumar Swaminathan 				mp = (MATCHMAP *)(rp->fc_mpoff);
284fcf3ce44SJohn Forte 
28582527734SSukumar Swaminathan 				if ((j == hba->channel_els) ||
28682527734SSukumar Swaminathan 				    (j == hba->channel_ct) ||
28782527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
28882527734SSukumar Swaminathan 				    (j == hba->CHANNEL_FCT) ||
28982527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
29082527734SSukumar Swaminathan 				    (j == hba->channel_ip)) {
29182527734SSukumar Swaminathan 					addr = mp->phys;
29282527734SSukumar Swaminathan 				}
293fcf3ce44SJohn Forte 
29482527734SSukumar Swaminathan 				if ((mp = emlxs_mem_get_vaddr(hba, rp, addr))) {
29582527734SSukumar Swaminathan 					if (j == hba->channel_els) {
296a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
297a9800bebSGarrett D'Amore 						    MEM_ELSBUF, (void *)mp);
29882527734SSukumar Swaminathan 					} else if (j == hba->channel_ct) {
299a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
300a9800bebSGarrett D'Amore 						    MEM_CTBUF, (void *)mp);
30182527734SSukumar Swaminathan 					} else if (j == hba->channel_ip) {
302a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
303a9800bebSGarrett D'Amore 						    MEM_IPBUF, (void *)mp);
30482527734SSukumar Swaminathan 					}
30582527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
30682527734SSukumar Swaminathan 					else if (j == hba->CHANNEL_FCT) {
307a9800bebSGarrett D'Amore 						emlxs_mem_put(hba,
308a9800bebSGarrett D'Amore 						    MEM_FCTBUF, (void *)mp);
30982527734SSukumar Swaminathan 					}
31082527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
311fcf3ce44SJohn Forte 
31282527734SSukumar Swaminathan 				}
31382527734SSukumar Swaminathan 			}
314fcf3ce44SJohn Forte 		}
31582527734SSukumar Swaminathan 	}
31682527734SSukumar Swaminathan 
31782527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
31882527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_ELS_HBQ_ID);
31982527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_IP_HBQ_ID);
32082527734SSukumar Swaminathan 		emlxs_hbq_free_all(hba, EMLXS_CT_HBQ_ID);
321291a2b48SSukumar Swaminathan 
322*8f23e9faSHans Rosenfeld 		if (port->flag & EMLXS_TGT_ENABLED) {
32382527734SSukumar Swaminathan 			emlxs_hbq_free_all(hba, EMLXS_FCT_HBQ_ID);
32482527734SSukumar Swaminathan 		}
325fcf3ce44SJohn Forte 	}
326fcf3ce44SJohn Forte 
32782527734SSukumar Swaminathan 	/* Free the nodes */
32882527734SSukumar Swaminathan 	for (j = 0; j < MAX_VPORTS; j++) {
32982527734SSukumar Swaminathan 		vport = &VPORT(j);
33082527734SSukumar Swaminathan 		if (vport->node_count) {
33182527734SSukumar Swaminathan 			emlxs_node_destroy_all(vport);
33282527734SSukumar Swaminathan 		}
33382527734SSukumar Swaminathan 	}
334fcf3ce44SJohn Forte 
33582527734SSukumar Swaminathan 	/* Make sure the mailbox queue is empty */
33682527734SSukumar Swaminathan 	emlxs_mb_flush(hba);
337fcf3ce44SJohn Forte 
33882527734SSukumar Swaminathan 	if (hba->fc_table) {
339fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
34082527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (emlxs_buf_t *);
34182527734SSukumar Swaminathan 		buf_info->virt = hba->fc_table;
34282527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
34382527734SSukumar Swaminathan 		hba->fc_table = NULL;
34482527734SSukumar Swaminathan 	}
345fcf3ce44SJohn Forte 
346*8f23e9faSHans Rosenfeld 	if (hba->sli.sli3.bpl_table) {
347*8f23e9faSHans Rosenfeld 		/* Return MEM_BPLs to their pool */
348*8f23e9faSHans Rosenfeld 		bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
349*8f23e9faSHans Rosenfeld 		for (j = 0; j < hba->max_iotag; j++) {
350*8f23e9faSHans Rosenfeld 			mp = bpl_table[j];
351*8f23e9faSHans Rosenfeld 			mp->flag &= ~MAP_TABLE_ALLOCATED;
352*8f23e9faSHans Rosenfeld 			emlxs_mem_put(hba, MEM_BPL, (void*)mp);
353*8f23e9faSHans Rosenfeld 		}
354*8f23e9faSHans Rosenfeld 
35582527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
35682527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
357*8f23e9faSHans Rosenfeld 		buf_info->virt = hba->sli.sli3.bpl_table;
35882527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
359*8f23e9faSHans Rosenfeld 		hba->sli.sli3.bpl_table = NULL;
36082527734SSukumar Swaminathan 	}
361fcf3ce44SJohn Forte 
36282527734SSukumar Swaminathan 	/* Free the memory segments */
36382527734SSukumar Swaminathan 	for (j = 0; j < FC_MAX_SEG; j++) {
364*8f23e9faSHans Rosenfeld 		emlxs_mem_pool_destroy(hba, &hba->memseg[j]);
36582527734SSukumar Swaminathan 	}
366291a2b48SSukumar Swaminathan 
36782527734SSukumar Swaminathan 	return (0);
368fcf3ce44SJohn Forte 
36982527734SSukumar Swaminathan } /* emlxs_mem_free_buffer() */
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 
372*8f23e9faSHans Rosenfeld /* Must hold EMLXS_MEMGET_LOCK when calling */
373*8f23e9faSHans Rosenfeld static uint32_t
374*8f23e9faSHans Rosenfeld emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
37582527734SSukumar Swaminathan {
37682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
37782527734SSukumar Swaminathan 	uint8_t *bp = NULL;
37882527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
37982527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
38082527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
38182527734SSukumar Swaminathan 	uint32_t i;
382*8f23e9faSHans Rosenfeld 	uint32_t fc_numblks;
383fcf3ce44SJohn Forte 
384*8f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
385*8f23e9faSHans Rosenfeld 		return (0);
386*8f23e9faSHans Rosenfeld 	}
387fcf3ce44SJohn Forte 
388*8f23e9faSHans Rosenfeld 	if (seg->fc_numblks >= seg->fc_hi_water) {
389*8f23e9faSHans Rosenfeld 		return (0);
390*8f23e9faSHans Rosenfeld 	}
391*8f23e9faSHans Rosenfeld 
392*8f23e9faSHans Rosenfeld 	if (count == 0) {
393*8f23e9faSHans Rosenfeld 		return (0);
394*8f23e9faSHans Rosenfeld 	}
395fcf3ce44SJohn Forte 
396*8f23e9faSHans Rosenfeld 	if (count > (seg->fc_hi_water - seg->fc_numblks)) {
397*8f23e9faSHans Rosenfeld 		count = (seg->fc_hi_water - seg->fc_numblks);
398*8f23e9faSHans Rosenfeld 	}
399fcf3ce44SJohn Forte 
400*8f23e9faSHans Rosenfeld 	buf_info = &local_buf_info;
401*8f23e9faSHans Rosenfeld 	fc_numblks = seg->fc_numblks;
402*8f23e9faSHans Rosenfeld 
403*8f23e9faSHans Rosenfeld 	/* Check for initial allocation */
404*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
405*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
406*8f23e9faSHans Rosenfeld 		    "%s alloc:%d n=%d s=%d f=%x l=%d,%d,%d "
407*8f23e9faSHans Rosenfeld 		    "f=%d:%d",
408*8f23e9faSHans Rosenfeld 		    seg->fc_label, count, seg->fc_numblks,
409*8f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
410*8f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
411*8f23e9faSHans Rosenfeld 		    seg->fc_low);
41282527734SSukumar Swaminathan 	}
413291a2b48SSukumar Swaminathan 
41482527734SSukumar Swaminathan 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
41582527734SSukumar Swaminathan 		goto vmem_pool;
416fcf3ce44SJohn Forte 	}
417fcf3ce44SJohn Forte 
41882527734SSukumar Swaminathan /* dma_pool */
41982527734SSukumar Swaminathan 
420*8f23e9faSHans Rosenfeld 	for (i = 0; i < count; i++) {
421fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
422fcf3ce44SJohn Forte 		buf_info->size = sizeof (MATCHMAP);
423fcf3ce44SJohn Forte 		buf_info->align = sizeof (void *);
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
426fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
427fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
428*8f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
429*8f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
430fcf3ce44SJohn Forte 
431*8f23e9faSHans Rosenfeld 			goto done;
432fcf3ce44SJohn Forte 		}
433291a2b48SSukumar Swaminathan 
43482527734SSukumar Swaminathan 		mp = (MATCHMAP *)buf_info->virt;
43582527734SSukumar Swaminathan 		bzero(mp, sizeof (MATCHMAP));
436fcf3ce44SJohn Forte 
437fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
43882527734SSukumar Swaminathan 		buf_info->size  = seg->fc_memsize;
43982527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
44082527734SSukumar Swaminathan 		buf_info->align = seg->fc_memalign;
441fcf3ce44SJohn Forte 
442fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
443fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
444fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
445*8f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
446*8f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
447fcf3ce44SJohn Forte 
44882527734SSukumar Swaminathan 			/* Free the mp object */
44982527734SSukumar Swaminathan 			bzero(buf_info, sizeof (MBUF_INFO));
45082527734SSukumar Swaminathan 			buf_info->size = sizeof (MATCHMAP);
451a9800bebSGarrett D'Amore 			buf_info->virt = (void *)mp;
45282527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
45382527734SSukumar Swaminathan 
454*8f23e9faSHans Rosenfeld 			goto done;
455fcf3ce44SJohn Forte 		}
456fcf3ce44SJohn Forte 		bp = (uint8_t *)buf_info->virt;
45782527734SSukumar Swaminathan 		bzero(bp, seg->fc_memsize);
45882527734SSukumar Swaminathan 
45982527734SSukumar Swaminathan 		mp->virt = buf_info->virt;
46082527734SSukumar Swaminathan 		mp->phys = buf_info->phys;
46182527734SSukumar Swaminathan 		mp->size = buf_info->size;
46282527734SSukumar Swaminathan 		mp->dma_handle = buf_info->dma_handle;
46382527734SSukumar Swaminathan 		mp->data_handle = buf_info->data_handle;
46482527734SSukumar Swaminathan 		mp->tag = seg->fc_memtag;
46582527734SSukumar Swaminathan 		mp->segment = seg;
46682527734SSukumar Swaminathan 		mp->flag |= MAP_POOL_ALLOCATED;
46782527734SSukumar Swaminathan 
468*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
469*8f23e9faSHans Rosenfeld 		if (mp->tag >= MEM_FCTSEG) {
470*8f23e9faSHans Rosenfeld 			if (emlxs_fct_stmf_alloc(hba, mp)) {
471*8f23e9faSHans Rosenfeld 				/* Free the DMA memory itself */
472*8f23e9faSHans Rosenfeld 				emlxs_mem_free(hba, buf_info);
473*8f23e9faSHans Rosenfeld 
474*8f23e9faSHans Rosenfeld 				/* Free the mp object */
475*8f23e9faSHans Rosenfeld 				bzero(buf_info, sizeof (MBUF_INFO));
476*8f23e9faSHans Rosenfeld 				buf_info->size = sizeof (MATCHMAP);
477*8f23e9faSHans Rosenfeld 				buf_info->virt = (void *)mp;
478*8f23e9faSHans Rosenfeld 				emlxs_mem_free(hba, buf_info);
479*8f23e9faSHans Rosenfeld 
480*8f23e9faSHans Rosenfeld 				goto done;
481*8f23e9faSHans Rosenfeld 			}
482*8f23e9faSHans Rosenfeld 		}
483*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
484*8f23e9faSHans Rosenfeld 
48582527734SSukumar Swaminathan 		/* Add the buffer desc to the tail of the pool freelist */
48682527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
48782527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)mp;
48882527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
48982527734SSukumar Swaminathan 		} else {
49082527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)mp;
49182527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
492fcf3ce44SJohn Forte 		}
49382527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)mp;
494*8f23e9faSHans Rosenfeld 
495*8f23e9faSHans Rosenfeld 		seg->fc_numblks++;
496*8f23e9faSHans Rosenfeld 		seg->fc_total_memsize += (seg->fc_memsize + sizeof (MATCHMAP));
497fcf3ce44SJohn Forte 	}
498fcf3ce44SJohn Forte 
499*8f23e9faSHans Rosenfeld 	goto done;
500fcf3ce44SJohn Forte 
50182527734SSukumar Swaminathan vmem_pool:
502fcf3ce44SJohn Forte 
503*8f23e9faSHans Rosenfeld 	for (i = 0; i < count; i++) {
504*8f23e9faSHans Rosenfeld 		bzero(buf_info, sizeof (MBUF_INFO));
505*8f23e9faSHans Rosenfeld 		buf_info->size  = seg->fc_memsize;
506fcf3ce44SJohn Forte 
507*8f23e9faSHans Rosenfeld 		(void) emlxs_mem_alloc(hba, buf_info);
508*8f23e9faSHans Rosenfeld 		if (buf_info->virt == NULL) {
509*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
510*8f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d",
511*8f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks, seg->fc_memsize);
512fcf3ce44SJohn Forte 
513*8f23e9faSHans Rosenfeld 			goto done;
514*8f23e9faSHans Rosenfeld 		}
515*8f23e9faSHans Rosenfeld 		bp = (uint8_t *)buf_info->virt;
516fcf3ce44SJohn Forte 
51782527734SSukumar Swaminathan 		/* Add the buffer to the tail of the pool freelist */
51882527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
51982527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)bp;
52082527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
52182527734SSukumar Swaminathan 		} else {
52282527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)bp;
52382527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
52482527734SSukumar Swaminathan 		}
52582527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)bp;
526fcf3ce44SJohn Forte 
527*8f23e9faSHans Rosenfeld 		seg->fc_numblks++;
528*8f23e9faSHans Rosenfeld 		seg->fc_total_memsize += seg->fc_memsize;
52982527734SSukumar Swaminathan 	}
530fcf3ce44SJohn Forte 
531*8f23e9faSHans Rosenfeld done:
532fcf3ce44SJohn Forte 
533*8f23e9faSHans Rosenfeld 	return ((seg->fc_numblks - fc_numblks));
534291a2b48SSukumar Swaminathan 
53582527734SSukumar Swaminathan } /* emlxs_mem_pool_alloc() */
536fcf3ce44SJohn Forte 
537fcf3ce44SJohn Forte 
538*8f23e9faSHans Rosenfeld /* Must hold EMLXS_MEMGET_LOCK & EMLXS_MEMPUT_LOCK when calling */
539*8f23e9faSHans Rosenfeld static void
540*8f23e9faSHans Rosenfeld emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
54182527734SSukumar Swaminathan {
54282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
54382527734SSukumar Swaminathan 	uint8_t *bp = NULL;
54482527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
54582527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
54682527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
547fcf3ce44SJohn Forte 
548*8f23e9faSHans Rosenfeld 	if ((seg->fc_memsize == 0) ||
549*8f23e9faSHans Rosenfeld 	    (seg->fc_numblks == 0) ||
550*8f23e9faSHans Rosenfeld 	    (count == 0)) {
551*8f23e9faSHans Rosenfeld 		return;
552*8f23e9faSHans Rosenfeld 	}
553fcf3ce44SJohn Forte 
554*8f23e9faSHans Rosenfeld 	/* Check max count */
555*8f23e9faSHans Rosenfeld 	if (count > seg->fc_numblks) {
556*8f23e9faSHans Rosenfeld 		count = seg->fc_numblks;
557fcf3ce44SJohn Forte 	}
558fcf3ce44SJohn Forte 
559*8f23e9faSHans Rosenfeld 	/* Move memput list to memget list */
560*8f23e9faSHans Rosenfeld 	if (seg->fc_memput_ptr) {
561*8f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == NULL) {
562*8f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = seg->fc_memput_ptr;
563*8f23e9faSHans Rosenfeld 		} else {
564*8f23e9faSHans Rosenfeld 			*((uint8_t **)(seg->fc_memget_end)) =\
565*8f23e9faSHans Rosenfeld 			    seg->fc_memput_ptr;
566*8f23e9faSHans Rosenfeld 		}
567*8f23e9faSHans Rosenfeld 		seg->fc_memget_end = seg->fc_memput_end;
568*8f23e9faSHans Rosenfeld 		seg->fc_memget_cnt += seg->fc_memput_cnt;
569fcf3ce44SJohn Forte 
570*8f23e9faSHans Rosenfeld 		seg->fc_memput_ptr = NULL;
571*8f23e9faSHans Rosenfeld 		seg->fc_memput_end = NULL;
572*8f23e9faSHans Rosenfeld 		seg->fc_memput_cnt = 0;
573*8f23e9faSHans Rosenfeld 	}
574fcf3ce44SJohn Forte 
575*8f23e9faSHans Rosenfeld 	buf_info = &local_buf_info;
576fcf3ce44SJohn Forte 
577*8f23e9faSHans Rosenfeld 	/* Check for final deallocation */
578*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
579*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
580*8f23e9faSHans Rosenfeld 		    "%s free:%d n=%d s=%d f=%x l=%d,%d,%d "
581*8f23e9faSHans Rosenfeld 		    "f=%d:%d",
582*8f23e9faSHans Rosenfeld 		    seg->fc_label, count, seg->fc_numblks,
583*8f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
584*8f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
585*8f23e9faSHans Rosenfeld 		    seg->fc_low);
586*8f23e9faSHans Rosenfeld 	}
587fcf3ce44SJohn Forte 
588*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
589*8f23e9faSHans Rosenfeld 		goto vmem_pool;
59082527734SSukumar Swaminathan 	}
591fcf3ce44SJohn Forte 
592*8f23e9faSHans Rosenfeld dma_pool:
593fcf3ce44SJohn Forte 
59482527734SSukumar Swaminathan 	/* Free memory associated with all buffers on get buffer pool */
595*8f23e9faSHans Rosenfeld 	while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
596*8f23e9faSHans Rosenfeld 		/* Remove buffer from list */
597*8f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == bp) {
598*8f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = NULL;
599*8f23e9faSHans Rosenfeld 			seg->fc_memget_end = NULL;
600*8f23e9faSHans Rosenfeld 			seg->fc_memget_cnt = 0;
601*8f23e9faSHans Rosenfeld 
602*8f23e9faSHans Rosenfeld 		} else {
603*8f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = *((uint8_t **)bp);
604*8f23e9faSHans Rosenfeld 			seg->fc_memget_cnt--;
605*8f23e9faSHans Rosenfeld 		}
60682527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
607fcf3ce44SJohn Forte 
608*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
609*8f23e9faSHans Rosenfeld 		if (mp->tag >= MEM_FCTSEG) {
610*8f23e9faSHans Rosenfeld 			emlxs_fct_stmf_free(hba, mp);
611*8f23e9faSHans Rosenfeld 		}
612*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
613*8f23e9faSHans Rosenfeld 
614*8f23e9faSHans Rosenfeld 		/* Free the DMA memory itself */
61582527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
61682527734SSukumar Swaminathan 		buf_info->size = mp->size;
61782527734SSukumar Swaminathan 		buf_info->virt = mp->virt;
61882527734SSukumar Swaminathan 		buf_info->phys = mp->phys;
61982527734SSukumar Swaminathan 		buf_info->dma_handle = mp->dma_handle;
62082527734SSukumar Swaminathan 		buf_info->data_handle = mp->data_handle;
62182527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
62282527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
623fcf3ce44SJohn Forte 
624*8f23e9faSHans Rosenfeld 		/* Free the handle */
62582527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
62682527734SSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
627a9800bebSGarrett D'Amore 		buf_info->virt = (void *)mp;
62882527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
629*8f23e9faSHans Rosenfeld 
630*8f23e9faSHans Rosenfeld 		seg->fc_numblks--;
631*8f23e9faSHans Rosenfeld 		seg->fc_total_memsize -= (seg->fc_memsize + sizeof (MATCHMAP));
632*8f23e9faSHans Rosenfeld 
633*8f23e9faSHans Rosenfeld 		count--;
634fcf3ce44SJohn Forte 	}
635291a2b48SSukumar Swaminathan 
636*8f23e9faSHans Rosenfeld 	return;
637fcf3ce44SJohn Forte 
638*8f23e9faSHans Rosenfeld vmem_pool:
639291a2b48SSukumar Swaminathan 
640*8f23e9faSHans Rosenfeld 	/* Free memory associated with all buffers on get buffer pool */
641*8f23e9faSHans Rosenfeld 	while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
642*8f23e9faSHans Rosenfeld 		/* Remove buffer from list */
643*8f23e9faSHans Rosenfeld 		if (seg->fc_memget_end == bp) {
644*8f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = NULL;
645*8f23e9faSHans Rosenfeld 			seg->fc_memget_end = NULL;
646*8f23e9faSHans Rosenfeld 			seg->fc_memget_cnt = 0;
647*8f23e9faSHans Rosenfeld 
648*8f23e9faSHans Rosenfeld 		} else {
649*8f23e9faSHans Rosenfeld 			seg->fc_memget_ptr = *((uint8_t **)bp);
650*8f23e9faSHans Rosenfeld 			seg->fc_memget_cnt--;
651*8f23e9faSHans Rosenfeld 		}
652*8f23e9faSHans Rosenfeld 
653*8f23e9faSHans Rosenfeld 		/* Free the Virtual memory itself */
65482527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
655*8f23e9faSHans Rosenfeld 		buf_info->size = seg->fc_memsize;
656*8f23e9faSHans Rosenfeld 		buf_info->virt = bp;
65782527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
658*8f23e9faSHans Rosenfeld 
659*8f23e9faSHans Rosenfeld 		seg->fc_numblks--;
660*8f23e9faSHans Rosenfeld 		seg->fc_total_memsize -= seg->fc_memsize;
661*8f23e9faSHans Rosenfeld 
662*8f23e9faSHans Rosenfeld 		count--;
663291a2b48SSukumar Swaminathan 	}
664fcf3ce44SJohn Forte 
66582527734SSukumar Swaminathan 	return;
666fcf3ce44SJohn Forte 
66782527734SSukumar Swaminathan } /* emlxs_mem_pool_free() */
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte 
670*8f23e9faSHans Rosenfeld extern uint32_t
671*8f23e9faSHans Rosenfeld emlxs_mem_pool_create(emlxs_hba_t *hba, MEMSEG *seg)
67282527734SSukumar Swaminathan {
673*8f23e9faSHans Rosenfeld 	emlxs_config_t *cfg = &CFG;
674291a2b48SSukumar Swaminathan 
67582527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
676*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
67782527734SSukumar Swaminathan 
678*8f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
679*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
68082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMGET_LOCK);
681*8f23e9faSHans Rosenfeld 
682*8f23e9faSHans Rosenfeld 		return (0);
683*8f23e9faSHans Rosenfeld 	}
684*8f23e9faSHans Rosenfeld 
685*8f23e9faSHans Rosenfeld 	/* Sanity check hi > lo */
686*8f23e9faSHans Rosenfeld 	if (seg->fc_lo_water > seg->fc_hi_water) {
687*8f23e9faSHans Rosenfeld 		seg->fc_hi_water = seg->fc_lo_water;
688*8f23e9faSHans Rosenfeld 	}
689*8f23e9faSHans Rosenfeld 
690*8f23e9faSHans Rosenfeld 	/* If dynamic pools are disabled, then force pool to max level */
691*8f23e9faSHans Rosenfeld 	if (cfg[CFG_MEM_DYNAMIC].current == 0) {
692*8f23e9faSHans Rosenfeld 		seg->fc_lo_water = seg->fc_hi_water;
693fcf3ce44SJohn Forte 	}
694291a2b48SSukumar Swaminathan 
695*8f23e9faSHans Rosenfeld 	/* If pool is dynamic, then fc_step must be >0 */
696*8f23e9faSHans Rosenfeld 	/* Otherwise, fc_step must be 0 */
697*8f23e9faSHans Rosenfeld 	if (seg->fc_lo_water != seg->fc_hi_water) {
698*8f23e9faSHans Rosenfeld 		seg->fc_memflag |= FC_MEMSEG_DYNAMIC;
699fcf3ce44SJohn Forte 
700*8f23e9faSHans Rosenfeld 		if (seg->fc_step == 0) {
701*8f23e9faSHans Rosenfeld 			seg->fc_step = 1;
70282527734SSukumar Swaminathan 		}
703*8f23e9faSHans Rosenfeld 	} else {
704*8f23e9faSHans Rosenfeld 		seg->fc_step = 0;
70582527734SSukumar Swaminathan 	}
706fcf3ce44SJohn Forte 
707*8f23e9faSHans Rosenfeld 	seg->fc_numblks = 0;
708*8f23e9faSHans Rosenfeld 	seg->fc_total_memsize = 0;
709*8f23e9faSHans Rosenfeld 	seg->fc_low = 0;
710fcf3ce44SJohn Forte 
711*8f23e9faSHans Rosenfeld 	(void) emlxs_mem_pool_alloc(hba, seg,  seg->fc_lo_water);
712fcf3ce44SJohn Forte 
713*8f23e9faSHans Rosenfeld 	seg->fc_memflag |= (FC_MEMSEG_PUT_ENABLED|FC_MEMSEG_GET_ENABLED);
714291a2b48SSukumar Swaminathan 
715*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
716*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
717fcf3ce44SJohn Forte 
718*8f23e9faSHans Rosenfeld 	return (seg->fc_numblks);
719*8f23e9faSHans Rosenfeld 
720*8f23e9faSHans Rosenfeld } /* emlxs_mem_pool_create() */
721fcf3ce44SJohn Forte 
722fcf3ce44SJohn Forte 
723*8f23e9faSHans Rosenfeld extern void
724*8f23e9faSHans Rosenfeld emlxs_mem_pool_destroy(emlxs_hba_t *hba, MEMSEG *seg)
725*8f23e9faSHans Rosenfeld {
726*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
727*8f23e9faSHans Rosenfeld 
728*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
729*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
730*8f23e9faSHans Rosenfeld 
731*8f23e9faSHans Rosenfeld 	if (seg->fc_memsize == 0) {
732*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
733*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
734*8f23e9faSHans Rosenfeld 		return;
735*8f23e9faSHans Rosenfeld 	}
736*8f23e9faSHans Rosenfeld 
737*8f23e9faSHans Rosenfeld 	/* Leave FC_MEMSEG_PUT_ENABLED set for now */
738*8f23e9faSHans Rosenfeld 	seg->fc_memflag &= ~FC_MEMSEG_GET_ENABLED;
739*8f23e9faSHans Rosenfeld 
740*8f23e9faSHans Rosenfeld 	/* Try to free all objects */
741*8f23e9faSHans Rosenfeld 	emlxs_mem_pool_free(hba, seg, seg->fc_numblks);
742*8f23e9faSHans Rosenfeld 
743*8f23e9faSHans Rosenfeld 	if (seg->fc_numblks) {
744*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
745*8f23e9faSHans Rosenfeld 		    "mem_pool_destroy: %s leak detected: "
746*8f23e9faSHans Rosenfeld 		    "%d objects still allocated.",
747*8f23e9faSHans Rosenfeld 		    seg->fc_label, seg->fc_numblks);
74882527734SSukumar Swaminathan 	} else {
749*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
750*8f23e9faSHans Rosenfeld 		    "mem_pool_destroy: %s destroyed.",
751*8f23e9faSHans Rosenfeld 		    seg->fc_label);
752*8f23e9faSHans Rosenfeld 
753*8f23e9faSHans Rosenfeld 		/* Clear all */
754*8f23e9faSHans Rosenfeld 		bzero(seg, sizeof (MEMSEG));
755*8f23e9faSHans Rosenfeld 	}
756*8f23e9faSHans Rosenfeld 
757*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
758*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
759*8f23e9faSHans Rosenfeld 
760*8f23e9faSHans Rosenfeld 	return;
761*8f23e9faSHans Rosenfeld 
762*8f23e9faSHans Rosenfeld } /* emlxs_mem_pool_destroy() */
763*8f23e9faSHans Rosenfeld 
764*8f23e9faSHans Rosenfeld 
765*8f23e9faSHans Rosenfeld extern void
766*8f23e9faSHans Rosenfeld emlxs_mem_pool_clean(emlxs_hba_t *hba, MEMSEG *seg)
767*8f23e9faSHans Rosenfeld {
768*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
769*8f23e9faSHans Rosenfeld 	uint32_t clean_count;
770*8f23e9faSHans Rosenfeld 	uint32_t free_count;
771*8f23e9faSHans Rosenfeld 	uint32_t free_pad;
772*8f23e9faSHans Rosenfeld 
773*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
774*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMPUT_LOCK);
775*8f23e9faSHans Rosenfeld 
776*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
777*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMPUT_LOCK);
778*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
779*8f23e9faSHans Rosenfeld 		return;
780*8f23e9faSHans Rosenfeld 	}
781*8f23e9faSHans Rosenfeld 
782*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
783*8f23e9faSHans Rosenfeld 		goto done;
784*8f23e9faSHans Rosenfeld 	}
785*8f23e9faSHans Rosenfeld 
786*8f23e9faSHans Rosenfeld #ifdef EMLXS_POOL_DEBUG
787*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
788*8f23e9faSHans Rosenfeld 	    "%s clean: n=%d s=%d f=%x l=%d,%d,%d "
789*8f23e9faSHans Rosenfeld 	    "f=%d:%d",
790*8f23e9faSHans Rosenfeld 	    seg->fc_label, seg->fc_numblks,
791*8f23e9faSHans Rosenfeld 	    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
792*8f23e9faSHans Rosenfeld 	    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
793*8f23e9faSHans Rosenfeld 	    seg->fc_low);
794*8f23e9faSHans Rosenfeld #endif /* EMLXS_POOL_DEBUG */
795*8f23e9faSHans Rosenfeld 
796*8f23e9faSHans Rosenfeld 	/* Calculatge current free count */
797*8f23e9faSHans Rosenfeld 	free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
798*8f23e9faSHans Rosenfeld 
799*8f23e9faSHans Rosenfeld 	/* Reset fc_low value to current free count */
800*8f23e9faSHans Rosenfeld 	clean_count = seg->fc_low;
801*8f23e9faSHans Rosenfeld 	seg->fc_low = free_count;
802*8f23e9faSHans Rosenfeld 
803*8f23e9faSHans Rosenfeld 	/* Return if pool is already at lo water mark */
804*8f23e9faSHans Rosenfeld 	if (seg->fc_numblks <= seg->fc_lo_water) {
805*8f23e9faSHans Rosenfeld 		goto done;
806*8f23e9faSHans Rosenfeld 	}
807*8f23e9faSHans Rosenfeld 
808*8f23e9faSHans Rosenfeld 	/* Return if there is nothing to clean */
809*8f23e9faSHans Rosenfeld 	if ((free_count == 0) ||
810*8f23e9faSHans Rosenfeld 	    (clean_count <= 1)) {
811*8f23e9faSHans Rosenfeld 		goto done;
812*8f23e9faSHans Rosenfeld 	}
813*8f23e9faSHans Rosenfeld 
814*8f23e9faSHans Rosenfeld 	/* Calculate a 3 percent free pad count (1 being minimum) */
815*8f23e9faSHans Rosenfeld 	if (seg->fc_numblks > 66) {
816*8f23e9faSHans Rosenfeld 		free_pad = ((seg->fc_numblks * 3)/100);
817*8f23e9faSHans Rosenfeld 	} else {
818*8f23e9faSHans Rosenfeld 		free_pad = 1;
819*8f23e9faSHans Rosenfeld 	}
820*8f23e9faSHans Rosenfeld 
821*8f23e9faSHans Rosenfeld 	/* Return if fc_low is below pool free pad */
822*8f23e9faSHans Rosenfeld 	if (clean_count <= free_pad) {
823*8f23e9faSHans Rosenfeld 		goto done;
824*8f23e9faSHans Rosenfeld 	}
825*8f23e9faSHans Rosenfeld 
826*8f23e9faSHans Rosenfeld 	clean_count -= free_pad;
827*8f23e9faSHans Rosenfeld 
828*8f23e9faSHans Rosenfeld 	/* clean_count can't exceed minimum pool levels */
829*8f23e9faSHans Rosenfeld 	if (clean_count > (seg->fc_numblks - seg->fc_lo_water)) {
830*8f23e9faSHans Rosenfeld 		clean_count = (seg->fc_numblks - seg->fc_lo_water);
831*8f23e9faSHans Rosenfeld 	}
832*8f23e9faSHans Rosenfeld 
833*8f23e9faSHans Rosenfeld 	emlxs_mem_pool_free(hba, seg, clean_count);
834*8f23e9faSHans Rosenfeld 
835*8f23e9faSHans Rosenfeld done:
836*8f23e9faSHans Rosenfeld 	if (seg->fc_last != seg->fc_numblks) {
837*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
838*8f23e9faSHans Rosenfeld 		    "%s update: n=%d->%d s=%d f=%x l=%d,%d,%d "
839*8f23e9faSHans Rosenfeld 		    "f=%d:%d",
840*8f23e9faSHans Rosenfeld 		    seg->fc_label, seg->fc_last, seg->fc_numblks,
841*8f23e9faSHans Rosenfeld 		    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
842*8f23e9faSHans Rosenfeld 		    seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
843*8f23e9faSHans Rosenfeld 		    seg->fc_low);
844*8f23e9faSHans Rosenfeld 
845*8f23e9faSHans Rosenfeld 		seg->fc_last = seg->fc_numblks;
846*8f23e9faSHans Rosenfeld 	}
847*8f23e9faSHans Rosenfeld 
848*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMPUT_LOCK);
849*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_MEMGET_LOCK);
850*8f23e9faSHans Rosenfeld 	return;
851*8f23e9faSHans Rosenfeld 
852*8f23e9faSHans Rosenfeld } /* emlxs_mem_pool_clean() */
853*8f23e9faSHans Rosenfeld 
854*8f23e9faSHans Rosenfeld 
855*8f23e9faSHans Rosenfeld extern void *
856*8f23e9faSHans Rosenfeld emlxs_mem_pool_get(emlxs_hba_t *hba, MEMSEG *seg)
857*8f23e9faSHans Rosenfeld {
858*8f23e9faSHans Rosenfeld 	emlxs_port_t	*port = &PPORT;
859*8f23e9faSHans Rosenfeld 	void		*bp = NULL;
860*8f23e9faSHans Rosenfeld 	MATCHMAP	*mp;
861*8f23e9faSHans Rosenfeld 	uint32_t	free_count;
862*8f23e9faSHans Rosenfeld 
863*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_MEMGET_LOCK);
864*8f23e9faSHans Rosenfeld 
865*8f23e9faSHans Rosenfeld 	/* Check if memory pool is GET enabled */
866*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
867*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
868*8f23e9faSHans Rosenfeld 		return (NULL);
869*8f23e9faSHans Rosenfeld 	}
870*8f23e9faSHans Rosenfeld 
871*8f23e9faSHans Rosenfeld 	/* If no entries on memget list, then check memput list */
872*8f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr) {
87382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MEMPUT_LOCK);
87482527734SSukumar Swaminathan 		if (seg->fc_memput_ptr) {
87582527734SSukumar Swaminathan 			/*
87682527734SSukumar Swaminathan 			 * Move list from memput to memget
87782527734SSukumar Swaminathan 			 */
87882527734SSukumar Swaminathan 			seg->fc_memget_ptr = seg->fc_memput_ptr;
87982527734SSukumar Swaminathan 			seg->fc_memget_end = seg->fc_memput_end;
88082527734SSukumar Swaminathan 			seg->fc_memget_cnt = seg->fc_memput_cnt;
88182527734SSukumar Swaminathan 			seg->fc_memput_ptr = NULL;
88282527734SSukumar Swaminathan 			seg->fc_memput_end = NULL;
88382527734SSukumar Swaminathan 			seg->fc_memput_cnt = 0;
884fcf3ce44SJohn Forte 		}
88582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
886*8f23e9faSHans Rosenfeld 	}
887*8f23e9faSHans Rosenfeld 
888*8f23e9faSHans Rosenfeld 	/* If no entries on memget list, then pool is empty */
889*8f23e9faSHans Rosenfeld 	/* Try to allocate more if pool is dynamic */
890*8f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr &&
891*8f23e9faSHans Rosenfeld 	    (seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
892*8f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_alloc(hba, seg,  seg->fc_step);
893*8f23e9faSHans Rosenfeld 		seg->fc_low = 0;
894*8f23e9faSHans Rosenfeld 	}
89582527734SSukumar Swaminathan 
896*8f23e9faSHans Rosenfeld 	/* If no entries on memget list, then pool is empty */
897*8f23e9faSHans Rosenfeld 	if (!seg->fc_memget_ptr) {
89882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
89982527734SSukumar Swaminathan 		    "%s empty.", seg->fc_label);
900*8f23e9faSHans Rosenfeld 
901*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_MEMGET_LOCK);
902*8f23e9faSHans Rosenfeld 		return (NULL);
903*8f23e9faSHans Rosenfeld 	}
904*8f23e9faSHans Rosenfeld 
905*8f23e9faSHans Rosenfeld 	/* Remove an entry from the get list */
906*8f23e9faSHans Rosenfeld 	bp = seg->fc_memget_ptr;
907*8f23e9faSHans Rosenfeld 
908*8f23e9faSHans Rosenfeld 	if (seg->fc_memget_end == bp) {
909*8f23e9faSHans Rosenfeld 		seg->fc_memget_ptr = NULL;
910*8f23e9faSHans Rosenfeld 		seg->fc_memget_end = NULL;
911*8f23e9faSHans Rosenfeld 		seg->fc_memget_cnt = 0;
912*8f23e9faSHans Rosenfeld 
913*8f23e9faSHans Rosenfeld 	} else {
914*8f23e9faSHans Rosenfeld 		seg->fc_memget_ptr = *((uint8_t **)bp);
915*8f23e9faSHans Rosenfeld 		seg->fc_memget_cnt--;
916*8f23e9faSHans Rosenfeld 	}
917*8f23e9faSHans Rosenfeld 
918*8f23e9faSHans Rosenfeld 	/* Initialize buffer */
919*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
920*8f23e9faSHans Rosenfeld 		bzero(bp, seg->fc_memsize);
921*8f23e9faSHans Rosenfeld 	} else {
922*8f23e9faSHans Rosenfeld 		mp = (MATCHMAP *)bp;
923*8f23e9faSHans Rosenfeld 		mp->fc_mptr = NULL;
924*8f23e9faSHans Rosenfeld 		mp->flag |= MAP_POOL_ALLOCATED;
925*8f23e9faSHans Rosenfeld 	}
926*8f23e9faSHans Rosenfeld 
927*8f23e9faSHans Rosenfeld 	/* Set fc_low if pool is dynamic */
928*8f23e9faSHans Rosenfeld 	if (seg->fc_memflag & FC_MEMSEG_DYNAMIC) {
929*8f23e9faSHans Rosenfeld 		free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
930*8f23e9faSHans Rosenfeld 		if (free_count < seg->fc_low) {
931*8f23e9faSHans Rosenfeld 			seg->fc_low = free_count;
932*8f23e9faSHans Rosenfeld 		}
933fcf3ce44SJohn Forte 	}
934fcf3ce44SJohn Forte 
93582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
93682527734SSukumar Swaminathan 
93782527734SSukumar Swaminathan 	return (bp);
938fcf3ce44SJohn Forte 
93982527734SSukumar Swaminathan } /* emlxs_mem_pool_get() */
940fcf3ce44SJohn Forte 
941fcf3ce44SJohn Forte 
942a9800bebSGarrett D'Amore extern void
943a9800bebSGarrett D'Amore emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, void *bp)
94482527734SSukumar Swaminathan {
945a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
946a9800bebSGarrett D'Amore 	MATCHMAP	*mp;
947fcf3ce44SJohn Forte 
94882527734SSukumar Swaminathan 	/* Free the pool object */
94982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
95082527734SSukumar Swaminathan 
951*8f23e9faSHans Rosenfeld 	/* Check if memory pool is PUT enabled */
952*8f23e9faSHans Rosenfeld 	if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
95382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
954a9800bebSGarrett D'Amore 		return;
955fcf3ce44SJohn Forte 	}
956291a2b48SSukumar Swaminathan 
95782527734SSukumar Swaminathan 	/* Check if buffer was just freed */
958*8f23e9faSHans Rosenfeld 	if ((seg->fc_memput_end == bp) || (seg->fc_memget_end == bp)) {
95982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
96082527734SSukumar Swaminathan 		    "%s: Freeing free object: bp=%p", seg->fc_label, bp);
961fcf3ce44SJohn Forte 
96282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
963a9800bebSGarrett D'Amore 		return;
964fcf3ce44SJohn Forte 	}
965fcf3ce44SJohn Forte 
966*8f23e9faSHans Rosenfeld 	/* Validate DMA buffer */
96782527734SSukumar Swaminathan 	if (seg->fc_memflag & FC_MBUF_DMA) {
96882527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
969291a2b48SSukumar Swaminathan 
97082527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED) ||
97182527734SSukumar Swaminathan 		    (mp->segment != seg)) {
97282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
973*8f23e9faSHans Rosenfeld 			    "mem_pool_put: %s invalid: mp=%p " \
97482527734SSukumar Swaminathan 			    "tag=0x%x flag=%x", seg->fc_label,
97582527734SSukumar Swaminathan 			    mp, mp->tag, mp->flag);
976291a2b48SSukumar Swaminathan 
97782527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
978fcf3ce44SJohn Forte 
97982527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMPUT_LOCK);
980fcf3ce44SJohn Forte 
98182527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
98282527734SSukumar Swaminathan 			    NULL, NULL);
98382527734SSukumar Swaminathan 
984a9800bebSGarrett D'Amore 			return;
985fcf3ce44SJohn Forte 		}
986fcf3ce44SJohn Forte 	}
987fcf3ce44SJohn Forte 
988*8f23e9faSHans Rosenfeld 	/* Release buffer to the end of the memput list */
98982527734SSukumar Swaminathan 	if (seg->fc_memput_end == NULL) {
99082527734SSukumar Swaminathan 		seg->fc_memput_ptr = bp;
99182527734SSukumar Swaminathan 		seg->fc_memput_cnt = 1;
99282527734SSukumar Swaminathan 	} else {
993a9800bebSGarrett D'Amore 		*((void **)(seg->fc_memput_end)) = bp;
99482527734SSukumar Swaminathan 		seg->fc_memput_cnt++;
99582527734SSukumar Swaminathan 	}
99682527734SSukumar Swaminathan 	seg->fc_memput_end = bp;
997a9800bebSGarrett D'Amore 	*((void **)(bp)) = NULL;
99882527734SSukumar Swaminathan 
99982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
1000fcf3ce44SJohn Forte 
1001*8f23e9faSHans Rosenfeld 	/* This is for late PUT's after an initial */
1002*8f23e9faSHans Rosenfeld 	/* emlxs_mem_pool_destroy call */
1003*8f23e9faSHans Rosenfeld 	if ((seg->fc_memflag & FC_MEMSEG_PUT_ENABLED) &&
1004*8f23e9faSHans Rosenfeld 	    !(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
1005*8f23e9faSHans Rosenfeld 		emlxs_mem_pool_destroy(hba, seg);
1006*8f23e9faSHans Rosenfeld 	}
1007*8f23e9faSHans Rosenfeld 
1008a9800bebSGarrett D'Amore 	return;
1009fcf3ce44SJohn Forte 
101082527734SSukumar Swaminathan } /* emlxs_mem_pool_put() */
1011fcf3ce44SJohn Forte 
101282527734SSukumar Swaminathan 
101382527734SSukumar Swaminathan extern MATCHMAP *
101482527734SSukumar Swaminathan emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size)
1015fcf3ce44SJohn Forte {
1016fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1017fcf3ce44SJohn Forte 	uint8_t *bp = NULL;
101882527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
1019fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1020fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1021fcf3ce44SJohn Forte 
1022fcf3ce44SJohn Forte 	buf_info = &bufinfo;
1023fcf3ce44SJohn Forte 
1024fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
1025fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
1026fcf3ce44SJohn Forte 	buf_info->align = sizeof (void *);
1027fcf3ce44SJohn Forte 
1028fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
1029fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
1030fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1031fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC buffer.");
1032fcf3ce44SJohn Forte 
103382527734SSukumar Swaminathan 		return (NULL);
1034fcf3ce44SJohn Forte 	}
1035291a2b48SSukumar Swaminathan 
103682527734SSukumar Swaminathan 	mp = (MATCHMAP *)buf_info->virt;
103782527734SSukumar Swaminathan 	bzero(mp, sizeof (MATCHMAP));
1038fcf3ce44SJohn Forte 
1039fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
104082527734SSukumar Swaminathan 	buf_info->size = size;
104182527734SSukumar Swaminathan 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1042fcf3ce44SJohn Forte 	buf_info->align = 32;
1043fcf3ce44SJohn Forte 
1044fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
1045fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
1046fcf3ce44SJohn Forte 
1047fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1048fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC DMA buffer.");
1049fcf3ce44SJohn Forte 
105082527734SSukumar Swaminathan 		/* Free the mp object */
1051728bdc9bSSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1052728bdc9bSSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
1053a9800bebSGarrett D'Amore 		buf_info->virt = (void *)mp;
1054728bdc9bSSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
1055728bdc9bSSukumar Swaminathan 
1056fcf3ce44SJohn Forte 		return (0);
1057fcf3ce44SJohn Forte 	}
1058fcf3ce44SJohn Forte 	bp = (uint8_t *)buf_info->virt;
1059*8f23e9faSHans Rosenfeld 	bzero(bp, buf_info->size);
1060fcf3ce44SJohn Forte 
106182527734SSukumar Swaminathan 	mp->virt = buf_info->virt;
106282527734SSukumar Swaminathan 	mp->phys = buf_info->phys;
106382527734SSukumar Swaminathan 	mp->size = buf_info->size;
106482527734SSukumar Swaminathan 	mp->dma_handle = buf_info->dma_handle;
106582527734SSukumar Swaminathan 	mp->data_handle = buf_info->data_handle;
106682527734SSukumar Swaminathan 	mp->tag = MEM_BUF;
106782527734SSukumar Swaminathan 	mp->flag |= MAP_BUF_ALLOCATED;
1068fcf3ce44SJohn Forte 
106982527734SSukumar Swaminathan 	return (mp);
1070fcf3ce44SJohn Forte 
107182527734SSukumar Swaminathan } /* emlxs_mem_buf_alloc() */
1072fcf3ce44SJohn Forte 
1073fcf3ce44SJohn Forte 
1074a9800bebSGarrett D'Amore extern void
107582527734SSukumar Swaminathan emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp)
1076fcf3ce44SJohn Forte {
1077fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1078fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1079fcf3ce44SJohn Forte 
1080fcf3ce44SJohn Forte 	buf_info = &bufinfo;
1081fcf3ce44SJohn Forte 
108282527734SSukumar Swaminathan 	if (!(mp->flag & MAP_BUF_ALLOCATED)) {
1083a9800bebSGarrett D'Amore 		return;
1084fcf3ce44SJohn Forte 	}
1085fcf3ce44SJohn Forte 
1086fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
108782527734SSukumar Swaminathan 	buf_info->size = mp->size;
108882527734SSukumar Swaminathan 	buf_info->virt = mp->virt;
108982527734SSukumar Swaminathan 	buf_info->phys = mp->phys;
109082527734SSukumar Swaminathan 	buf_info->dma_handle = mp->dma_handle;
109182527734SSukumar Swaminathan 	buf_info->data_handle = mp->data_handle;
1092fcf3ce44SJohn Forte 	buf_info->flags = FC_MBUF_DMA;
1093fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
1094fcf3ce44SJohn Forte 
1095fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
1096fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
1097a9800bebSGarrett D'Amore 	buf_info->virt = (void *)mp;
1098fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
1099fcf3ce44SJohn Forte 
1100a9800bebSGarrett D'Amore 	return;
1101fcf3ce44SJohn Forte 
110282527734SSukumar Swaminathan } /* emlxs_mem_buf_free() */
1103fcf3ce44SJohn Forte 
1104fcf3ce44SJohn Forte 
1105a9800bebSGarrett D'Amore extern void *
1106*8f23e9faSHans Rosenfeld emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id)
1107fcf3ce44SJohn Forte {
1108a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
1109a9800bebSGarrett D'Amore 	void		*bp;
1110a9800bebSGarrett D'Amore 	MAILBOXQ	*mbq;
1111a9800bebSGarrett D'Amore 	IOCBQ		*iocbq;
1112a9800bebSGarrett D'Amore 	NODELIST	*node;
1113a9800bebSGarrett D'Amore 	MEMSEG		*seg;
1114fcf3ce44SJohn Forte 
111582527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
1116291a2b48SSukumar Swaminathan 
111782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1118*8f23e9faSHans Rosenfeld 		    "mem_get: Invalid segment id = %d",
111982527734SSukumar Swaminathan 		    seg_id);
1120fcf3ce44SJohn Forte 
1121fcf3ce44SJohn Forte 		return (NULL);
1122fcf3ce44SJohn Forte 	}
112382527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
1124fcf3ce44SJohn Forte 
112582527734SSukumar Swaminathan 	/* Alloc a buffer from the pool */
1126*8f23e9faSHans Rosenfeld 	bp = emlxs_mem_pool_get(hba, seg);
1127fcf3ce44SJohn Forte 
112882527734SSukumar Swaminathan 	if (bp) {
112982527734SSukumar Swaminathan 		switch (seg_id) {
1130fcf3ce44SJohn Forte 		case MEM_MBOX:
1131291a2b48SSukumar Swaminathan 			mbq = (MAILBOXQ *)bp;
1132fcf3ce44SJohn Forte 			mbq->flag |= MBQ_POOL_ALLOCATED;
1133fcf3ce44SJohn Forte 			break;
1134fcf3ce44SJohn Forte 
1135fcf3ce44SJohn Forte 		case MEM_IOCB:
1136291a2b48SSukumar Swaminathan 			iocbq = (IOCBQ *)bp;
1137fcf3ce44SJohn Forte 			iocbq->flag |= IOCB_POOL_ALLOCATED;
1138fcf3ce44SJohn Forte 			break;
1139fcf3ce44SJohn Forte 
1140fcf3ce44SJohn Forte 		case MEM_NLP:
1141291a2b48SSukumar Swaminathan 			node = (NODELIST *)bp;
1142fcf3ce44SJohn Forte 			node->flag |= NODE_POOL_ALLOCATED;
1143fcf3ce44SJohn Forte 			break;
1144fcf3ce44SJohn Forte 		}
1145fcf3ce44SJohn Forte 	}
1146fcf3ce44SJohn Forte 
1147fcf3ce44SJohn Forte 	return (bp);
1148fcf3ce44SJohn Forte 
114982527734SSukumar Swaminathan } /* emlxs_mem_get() */
1150fcf3ce44SJohn Forte 
1151fcf3ce44SJohn Forte 
1152a9800bebSGarrett D'Amore extern void
1153a9800bebSGarrett D'Amore emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, void *bp)
1154fcf3ce44SJohn Forte {
1155a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
1156a9800bebSGarrett D'Amore 	MAILBOXQ	*mbq;
1157a9800bebSGarrett D'Amore 	IOCBQ		*iocbq;
1158a9800bebSGarrett D'Amore 	NODELIST	*node;
1159a9800bebSGarrett D'Amore 	MEMSEG		*seg;
1160a9800bebSGarrett D'Amore 	MATCHMAP	*mp;
1161fcf3ce44SJohn Forte 
116282527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
116382527734SSukumar Swaminathan 
116482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1165*8f23e9faSHans Rosenfeld 		    "mem_put: Invalid segment id = %d: bp=%p",
116682527734SSukumar Swaminathan 		    seg_id, bp);
1167291a2b48SSukumar Swaminathan 
1168a9800bebSGarrett D'Amore 		return;
1169fcf3ce44SJohn Forte 	}
117082527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
1171291a2b48SSukumar Swaminathan 
117282527734SSukumar Swaminathan 	/* Verify buffer */
117382527734SSukumar Swaminathan 	switch (seg_id) {
1174fcf3ce44SJohn Forte 	case MEM_MBOX:
1175291a2b48SSukumar Swaminathan 		mbq = (MAILBOXQ *)bp;
1176fcf3ce44SJohn Forte 
1177fcf3ce44SJohn Forte 		if (!(mbq->flag & MBQ_POOL_ALLOCATED)) {
1178a9800bebSGarrett D'Amore 			return;
1179fcf3ce44SJohn Forte 		}
1180fcf3ce44SJohn Forte 		break;
1181fcf3ce44SJohn Forte 
1182fcf3ce44SJohn Forte 	case MEM_IOCB:
1183291a2b48SSukumar Swaminathan 		iocbq = (IOCBQ *)bp;
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 		if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) {
1186a9800bebSGarrett D'Amore 			return;
1187fcf3ce44SJohn Forte 		}
1188291a2b48SSukumar Swaminathan 
1189291a2b48SSukumar Swaminathan 		/* Any IOCBQ with a packet attached did not come */
1190291a2b48SSukumar Swaminathan 		/* from our pool */
1191fcf3ce44SJohn Forte 		if (iocbq->sbp) {
1192a9800bebSGarrett D'Amore 			return;
1193fcf3ce44SJohn Forte 		}
1194fcf3ce44SJohn Forte 		break;
1195fcf3ce44SJohn Forte 
1196fcf3ce44SJohn Forte 	case MEM_NLP:
1197291a2b48SSukumar Swaminathan 		node = (NODELIST *)bp;
1198fcf3ce44SJohn Forte 
1199fcf3ce44SJohn Forte 		if (!(node->flag & NODE_POOL_ALLOCATED)) {
1200a9800bebSGarrett D'Amore 			return;
1201fcf3ce44SJohn Forte 		}
1202fcf3ce44SJohn Forte 		break;
1203fcf3ce44SJohn Forte 
1204fcf3ce44SJohn Forte 	default:
120582527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
1206fcf3ce44SJohn Forte 
120782527734SSukumar Swaminathan 		if (mp->flag & MAP_BUF_ALLOCATED) {
1208a9800bebSGarrett D'Amore 			emlxs_mem_buf_free(hba, mp);
1209a9800bebSGarrett D'Amore 			return;
1210fcf3ce44SJohn Forte 		}
1211291a2b48SSukumar Swaminathan 
121282527734SSukumar Swaminathan 		if (mp->flag & MAP_TABLE_ALLOCATED) {
1213a9800bebSGarrett D'Amore 			return;
1214fcf3ce44SJohn Forte 		}
1215291a2b48SSukumar Swaminathan 
121682527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED)) {
1217a9800bebSGarrett D'Amore 			return;
1218fcf3ce44SJohn Forte 		}
1219fcf3ce44SJohn Forte 		break;
1220fcf3ce44SJohn Forte 	}
1221fcf3ce44SJohn Forte 
122282527734SSukumar Swaminathan 	/* Free a buffer to the pool */
1223a9800bebSGarrett D'Amore 	emlxs_mem_pool_put(hba, seg, bp);
1224291a2b48SSukumar Swaminathan 
1225a9800bebSGarrett D'Amore 	return;
1226fcf3ce44SJohn Forte 
122782527734SSukumar Swaminathan } /* emlxs_mem_put() */
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 
1230fcf3ce44SJohn Forte /*
1231fcf3ce44SJohn Forte  * Look up the virtual address given a mapped address
1232fcf3ce44SJohn Forte  */
123382527734SSukumar Swaminathan /* SLI3 */
1234fcf3ce44SJohn Forte extern MATCHMAP *
1235fcf3ce44SJohn Forte emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp)
1236fcf3ce44SJohn Forte {
1237fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1238fcf3ce44SJohn Forte 	MATCHMAP *prev;
1239fcf3ce44SJohn Forte 	MATCHMAP *mp;
1240fcf3ce44SJohn Forte 
124182527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1242291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1243fcf3ce44SJohn Forte 		prev = 0;
1244fcf3ce44SJohn Forte 
1245fcf3ce44SJohn Forte 		while (mp) {
1246fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1247fcf3ce44SJohn Forte 				if (prev == 0) {
1248fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1249fcf3ce44SJohn Forte 				} else {
1250fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1251fcf3ce44SJohn Forte 				}
1252fcf3ce44SJohn Forte 
1253a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1254a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1255fcf3ce44SJohn Forte 				}
1256291a2b48SSukumar Swaminathan 
1257a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1258fcf3ce44SJohn Forte 
125982527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1260fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1261fcf3ce44SJohn Forte 
1262fcf3ce44SJohn Forte 				HBASTATS.ElsUbPosted--;
1263fcf3ce44SJohn Forte 
1264fcf3ce44SJohn Forte 				return (mp);
1265fcf3ce44SJohn Forte 			}
1266291a2b48SSukumar Swaminathan 
1267fcf3ce44SJohn Forte 			prev = mp;
1268291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1269fcf3ce44SJohn Forte 		}
1270fcf3ce44SJohn Forte 
1271fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1272fcf3ce44SJohn Forte 		    "ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1273fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1274fcf3ce44SJohn Forte 
127582527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1276fcf3ce44SJohn Forte 
1277291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1278fcf3ce44SJohn Forte 		prev = 0;
1279fcf3ce44SJohn Forte 
1280fcf3ce44SJohn Forte 		while (mp) {
1281fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1282fcf3ce44SJohn Forte 				if (prev == 0) {
1283fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1284fcf3ce44SJohn Forte 				} else {
1285fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1286fcf3ce44SJohn Forte 				}
1287fcf3ce44SJohn Forte 
1288a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1289a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1290fcf3ce44SJohn Forte 				}
1291291a2b48SSukumar Swaminathan 
1292a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1293fcf3ce44SJohn Forte 
129482527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1295fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1296fcf3ce44SJohn Forte 
1297fcf3ce44SJohn Forte 				HBASTATS.CtUbPosted--;
1298fcf3ce44SJohn Forte 
1299fcf3ce44SJohn Forte 				return (mp);
1300fcf3ce44SJohn Forte 			}
1301291a2b48SSukumar Swaminathan 
1302fcf3ce44SJohn Forte 			prev = mp;
1303291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1304fcf3ce44SJohn Forte 		}
1305fcf3ce44SJohn Forte 
1306fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1307fcf3ce44SJohn Forte 		    "CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1308fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1309fcf3ce44SJohn Forte 
131082527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1311fcf3ce44SJohn Forte 
1312291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1313fcf3ce44SJohn Forte 		prev = 0;
1314fcf3ce44SJohn Forte 
1315fcf3ce44SJohn Forte 		while (mp) {
1316fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1317fcf3ce44SJohn Forte 				if (prev == 0) {
1318fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1319fcf3ce44SJohn Forte 				} else {
1320fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1321fcf3ce44SJohn Forte 				}
1322fcf3ce44SJohn Forte 
1323a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1324a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1325fcf3ce44SJohn Forte 				}
1326291a2b48SSukumar Swaminathan 
1327a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1328fcf3ce44SJohn Forte 
132982527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1330fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1331fcf3ce44SJohn Forte 
1332fcf3ce44SJohn Forte 				HBASTATS.IpUbPosted--;
1333fcf3ce44SJohn Forte 
1334fcf3ce44SJohn Forte 				return (mp);
1335fcf3ce44SJohn Forte 			}
1336291a2b48SSukumar Swaminathan 
1337fcf3ce44SJohn Forte 			prev = mp;
1338291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1339fcf3ce44SJohn Forte 		}
1340fcf3ce44SJohn Forte 
1341fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1342fcf3ce44SJohn Forte 		    "IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1343fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
134682527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1347291a2b48SSukumar Swaminathan 		mp = (MATCHMAP *)rp->fc_mpoff;
1348fcf3ce44SJohn Forte 		prev = 0;
1349fcf3ce44SJohn Forte 
1350fcf3ce44SJohn Forte 		while (mp) {
1351fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1352fcf3ce44SJohn Forte 				if (prev == 0) {
1353fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1354fcf3ce44SJohn Forte 				} else {
1355fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1356fcf3ce44SJohn Forte 				}
1357fcf3ce44SJohn Forte 
1358a9800bebSGarrett D'Amore 				if (rp->fc_mpon == mp) {
1359a9800bebSGarrett D'Amore 					rp->fc_mpon = (void *)prev;
1360fcf3ce44SJohn Forte 				}
1361291a2b48SSukumar Swaminathan 
1362a9800bebSGarrett D'Amore 				mp->fc_mptr = NULL;
1363fcf3ce44SJohn Forte 
136482527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1365fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1366fcf3ce44SJohn Forte 
1367fcf3ce44SJohn Forte 				HBASTATS.FctUbPosted--;
1368fcf3ce44SJohn Forte 
1369fcf3ce44SJohn Forte 				return (mp);
1370fcf3ce44SJohn Forte 			}
1371291a2b48SSukumar Swaminathan 
1372fcf3ce44SJohn Forte 			prev = mp;
1373291a2b48SSukumar Swaminathan 			mp = (MATCHMAP *)mp->fc_mptr;
1374fcf3ce44SJohn Forte 		}
1375fcf3ce44SJohn Forte 
1376fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1377fcf3ce44SJohn Forte 		    "FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1378fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1379fcf3ce44SJohn Forte 
1380291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
1381fcf3ce44SJohn Forte 	}
1382fcf3ce44SJohn Forte 
1383fcf3ce44SJohn Forte 	return (0);
1384fcf3ce44SJohn Forte 
138582527734SSukumar Swaminathan } /* emlxs_mem_get_vaddr() */
1386fcf3ce44SJohn Forte 
1387fcf3ce44SJohn Forte 
1388fcf3ce44SJohn Forte /*
1389291a2b48SSukumar Swaminathan  * Given a virtual address bp, generate the physical mapped address and
1390291a2b48SSukumar Swaminathan  * place it where addr points to. Save the address pair for lookup later.
1391fcf3ce44SJohn Forte  */
139282527734SSukumar Swaminathan /* SLI3 */
1393fcf3ce44SJohn Forte extern void
1394291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp,
1395291a2b48SSukumar Swaminathan     uint32_t *haddr, uint32_t *laddr)
1396fcf3ce44SJohn Forte {
139782527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1398fcf3ce44SJohn Forte 		/*
1399291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1400291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1401291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1402fcf3ce44SJohn Forte 		 */
1403a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1404fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1405a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1406a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1407fcf3ce44SJohn Forte 		} else {
1408291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1409a9800bebSGarrett D'Amore 			    (void *)mp;
1410a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1411fcf3ce44SJohn Forte 		}
1412fcf3ce44SJohn Forte 
1413fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1414291a2b48SSukumar Swaminathan 
1415291a2b48SSukumar Swaminathan 			/* return mapped address */
141682527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1417fcf3ce44SJohn Forte 			/* return mapped address */
141882527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1419fcf3ce44SJohn Forte 		} else {
1420fcf3ce44SJohn Forte 			/* return mapped address */
142182527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1422fcf3ce44SJohn Forte 		}
1423fcf3ce44SJohn Forte 
1424fcf3ce44SJohn Forte 		HBASTATS.ElsUbPosted++;
1425fcf3ce44SJohn Forte 
142682527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1427fcf3ce44SJohn Forte 		/*
1428291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1429291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1430291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1431fcf3ce44SJohn Forte 		 */
1432a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1433fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1434a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1435a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1436fcf3ce44SJohn Forte 		} else {
1437291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1438a9800bebSGarrett D'Amore 			    (void *)mp;
1439a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1440fcf3ce44SJohn Forte 		}
1441fcf3ce44SJohn Forte 
1442fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1443fcf3ce44SJohn Forte 			/* return mapped address */
144482527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1445291a2b48SSukumar Swaminathan 			/* return mapped address */
144682527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1447fcf3ce44SJohn Forte 		} else {
1448fcf3ce44SJohn Forte 			/* return mapped address */
144982527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1450fcf3ce44SJohn Forte 		}
1451fcf3ce44SJohn Forte 
1452fcf3ce44SJohn Forte 		HBASTATS.CtUbPosted++;
1453fcf3ce44SJohn Forte 
1454fcf3ce44SJohn Forte 
145582527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1456fcf3ce44SJohn Forte 		/*
1457291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1458291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1459291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1460fcf3ce44SJohn Forte 		 */
1461a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1462fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1463a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1464a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1465fcf3ce44SJohn Forte 		} else {
1466291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1467a9800bebSGarrett D'Amore 			    (void *)mp;
1468a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1469fcf3ce44SJohn Forte 		}
1470fcf3ce44SJohn Forte 
1471fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1472fcf3ce44SJohn Forte 			/* return mapped address */
147382527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
147482527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1475fcf3ce44SJohn Forte 		} else {
147682527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1477fcf3ce44SJohn Forte 		}
1478fcf3ce44SJohn Forte 
1479fcf3ce44SJohn Forte 		HBASTATS.IpUbPosted++;
1480fcf3ce44SJohn Forte 
1481fcf3ce44SJohn Forte 
1482fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
148382527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1484fcf3ce44SJohn Forte 		/*
1485291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1486291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1487291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1488fcf3ce44SJohn Forte 		 */
1489a9800bebSGarrett D'Amore 		mp->fc_mptr = NULL;
1490fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1491a9800bebSGarrett D'Amore 			rp->fc_mpoff = (void *)mp;
1492a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1493fcf3ce44SJohn Forte 		} else {
1494291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1495a9800bebSGarrett D'Amore 			    (void *)mp;
1496a9800bebSGarrett D'Amore 			rp->fc_mpon = (void *)mp;
1497fcf3ce44SJohn Forte 		}
1498fcf3ce44SJohn Forte 
1499fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1500fcf3ce44SJohn Forte 			/* return mapped address */
150182527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1502291a2b48SSukumar Swaminathan 			/* return mapped address */
150382527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1504fcf3ce44SJohn Forte 		} else {
1505fcf3ce44SJohn Forte 			/* return mapped address */
150682527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1507fcf3ce44SJohn Forte 		}
1508fcf3ce44SJohn Forte 
1509fcf3ce44SJohn Forte 		HBASTATS.FctUbPosted++;
151082527734SSukumar Swaminathan 
1511291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
1512fcf3ce44SJohn Forte 	}
151382527734SSukumar Swaminathan } /* emlxs_mem_map_vaddr() */
1514fcf3ce44SJohn Forte 
1515fcf3ce44SJohn Forte 
151682527734SSukumar Swaminathan /* SLI3 */
1517291a2b48SSukumar Swaminathan uint32_t
1518fcf3ce44SJohn Forte emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id)
1519fcf3ce44SJohn Forte {
1520fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1521fcf3ce44SJohn Forte 	HBQ_INIT_t *hbq;
1522fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1523fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1524fcf3ce44SJohn Forte 
152582527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
1526fcf3ce44SJohn Forte 
1527fcf3ce44SJohn Forte 	if (hbq->HBQ_host_buf.virt == 0) {
1528fcf3ce44SJohn Forte 		buf_info = &bufinfo;
1529fcf3ce44SJohn Forte 
1530fcf3ce44SJohn Forte 		/* Get the system's page size in a DDI-compliant way. */
1531fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
1532fcf3ce44SJohn Forte 		buf_info->size = hbq->HBQ_numEntries * sizeof (HBQE_t);
1533fcf3ce44SJohn Forte 		buf_info->flags = FC_MBUF_DMA;
1534fcf3ce44SJohn Forte 		buf_info->align = 4096;
1535fcf3ce44SJohn Forte 
1536fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
1537fcf3ce44SJohn Forte 
1538fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
1539fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
1540fcf3ce44SJohn Forte 			    "Unable to alloc HBQ.");
1541fcf3ce44SJohn Forte 			return (ENOMEM);
1542fcf3ce44SJohn Forte 		}
1543291a2b48SSukumar Swaminathan 
1544a9800bebSGarrett D'Amore 		hbq->HBQ_host_buf.virt = buf_info->virt;
1545fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.phys = buf_info->phys;
1546fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.data_handle = buf_info->data_handle;
1547fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle;
1548fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.size = buf_info->size;
1549fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.tag = hbq_id;
1550fcf3ce44SJohn Forte 
1551fcf3ce44SJohn Forte 		bzero((char *)hbq->HBQ_host_buf.virt, buf_info->size);
1552fcf3ce44SJohn Forte 	}
1553fcf3ce44SJohn Forte 
1554fcf3ce44SJohn Forte 	return (0);
1555fcf3ce44SJohn Forte 
155682527734SSukumar Swaminathan } /* emlxs_hbq_alloc() */
1557