xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c (revision 825277341c15b6b0d2c4b8b622ae7b1d2bdc0390)
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  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
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 /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27*82527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_MEM_C);
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte extern int32_t
34fcf3ce44SJohn Forte emlxs_mem_alloc_buffer(emlxs_hba_t *hba)
35fcf3ce44SJohn Forte {
36fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
37fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
38fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
39*82527734SSukumar Swaminathan 	MEMSEG *seg;
40fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
41fcf3ce44SJohn Forte 	int32_t i;
42*82527734SSukumar Swaminathan 	int32_t cnt;
43fcf3ce44SJohn Forte #ifdef EMLXS_SPARC
44*82527734SSukumar Swaminathan 	MATCHMAP *mp;
45*82527734SSukumar Swaminathan 	MATCHMAP **fcp_bpl_table;
46fcf3ce44SJohn Forte #endif	/* EMLXS_SPARC */
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte 	buf_info = &bufinfo;
49fcf3ce44SJohn Forte 	cfg = &CFG;
50fcf3ce44SJohn Forte 
51*82527734SSukumar Swaminathan 	bzero(hba->memseg, sizeof (hba->memseg));
52fcf3ce44SJohn Forte 
53fcf3ce44SJohn Forte 	/*
54fcf3ce44SJohn Forte 	 * Initialize fc_table
55fcf3ce44SJohn Forte 	 */
56*82527734SSukumar Swaminathan 	cnt = cfg[CFG_NUM_IOTAGS].current;
57*82527734SSukumar Swaminathan 	if (cnt) {
58*82527734SSukumar Swaminathan 		hba->max_iotag = cnt;
59*82527734SSukumar Swaminathan 	}
60*82527734SSukumar Swaminathan 	/* ioatg 0 is not used, iotags 1 thru max_iotag-1 are used */
61fcf3ce44SJohn Forte 
62fcf3ce44SJohn Forte 	/* Allocate the fc_table */
63fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
64*82527734SSukumar Swaminathan 	buf_info->size = (hba->max_iotag * sizeof (emlxs_buf_t *));
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
67fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
68fcf3ce44SJohn Forte 
69fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
70fcf3ce44SJohn Forte 		    "fc_table buffer.");
71fcf3ce44SJohn Forte 
72*82527734SSukumar Swaminathan 		goto failed;
73fcf3ce44SJohn Forte 	}
74*82527734SSukumar Swaminathan 	hba->fc_table = buf_info->virt;
75*82527734SSukumar Swaminathan 	bzero(hba->fc_table, buf_info->size);
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte #ifdef EMLXS_SPARC
78*82527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
79fcf3ce44SJohn Forte 	/*
80*82527734SSukumar Swaminathan 	 * Allocate and Initialize FCP MEM_BPL table
81291a2b48SSukumar Swaminathan 	 * This is for increased performance on sparc
82fcf3ce44SJohn Forte 	 */
83fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
84*82527734SSukumar Swaminathan 	buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
87fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
90fcf3ce44SJohn Forte 		    "FCP BPL table buffer.");
91fcf3ce44SJohn Forte 
92*82527734SSukumar Swaminathan 		goto failed;
93fcf3ce44SJohn Forte 	}
94*82527734SSukumar Swaminathan 	hba->sli.sli3.fcp_bpl_table = buf_info->virt;
95*82527734SSukumar Swaminathan 	bzero(hba->sli.sli3.fcp_bpl_table, buf_info->size);
96fcf3ce44SJohn Forte 
97*82527734SSukumar Swaminathan 	/* Allocate a pool of BPLs for the FCP MEM_BPL table */
98*82527734SSukumar Swaminathan 	seg = &hba->sli.sli3.fcp_bpl_seg;
99*82527734SSukumar Swaminathan 	bzero(seg, sizeof (MEMSEG));
100*82527734SSukumar Swaminathan 	(void) strcpy(seg->fc_label, "FCP BPL Pool");
101*82527734SSukumar Swaminathan 	seg->fc_memtag	= MEM_BPL;
102*82527734SSukumar Swaminathan 	seg->fc_memsize	= (3 * sizeof (ULP_BDE64));
103*82527734SSukumar Swaminathan 	seg->fc_numblks	= hba->max_iotag;
104*82527734SSukumar Swaminathan 	seg->fc_reserved = 0;
105*82527734SSukumar Swaminathan 	seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
106*82527734SSukumar Swaminathan 	seg->fc_memalign = 32;
107fcf3ce44SJohn Forte 
108*82527734SSukumar Swaminathan 	if (emlxs_mem_pool_alloc(hba, seg) == NULL) {
109*82527734SSukumar Swaminathan 		goto failed;
110fcf3ce44SJohn Forte 	}
111fcf3ce44SJohn Forte 
112*82527734SSukumar Swaminathan 	/* Initialize the FCP MEM_BPL table */
113*82527734SSukumar Swaminathan 	fcp_bpl_table = (MATCHMAP**)hba->sli.sli3.fcp_bpl_table;
114*82527734SSukumar Swaminathan 	mp = (MATCHMAP*)seg->fc_memget_ptr;
115*82527734SSukumar Swaminathan 	for (i = 0; i < seg->fc_numblks; i++) {
116*82527734SSukumar Swaminathan 		mp->flag |= MAP_TABLE_ALLOCATED;
117*82527734SSukumar Swaminathan 		*fcp_bpl_table = mp;
118fcf3ce44SJohn Forte 
119*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)mp->fc_mptr;
120*82527734SSukumar Swaminathan 		fcp_bpl_table++;
121*82527734SSukumar Swaminathan 	}
122fcf3ce44SJohn Forte 	}
123fcf3ce44SJohn Forte #endif /* EMLXS_SPARC */
124fcf3ce44SJohn Forte 
125*82527734SSukumar Swaminathan 	/* Prepare the memory pools */
126fcf3ce44SJohn Forte 	for (i = 0; i < FC_MAX_SEG; i++) {
127*82527734SSukumar Swaminathan 		seg = &hba->memseg[i];
128fcf3ce44SJohn Forte 
129fcf3ce44SJohn Forte 		switch (i) {
130fcf3ce44SJohn Forte 		case MEM_NLP:
131*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "Node Pool");
132*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_NLP;
133*82527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (NODELIST);
134*82527734SSukumar Swaminathan 			seg->fc_numblks	= (int16_t)hba->max_nodes + 2;
135*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
136*82527734SSukumar Swaminathan 			seg->fc_memflag	= 0;
137fcf3ce44SJohn Forte 			break;
138*82527734SSukumar Swaminathan 
139fcf3ce44SJohn Forte 		case MEM_IOCB:
140*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "IOCB Pool");
141*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IOCB;
142*82527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (IOCBQ);
143*82527734SSukumar Swaminathan 			seg->fc_numblks	= (uint16_t)cfg[CFG_NUM_IOCBS].current;
144*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
145*82527734SSukumar Swaminathan 			seg->fc_memflag	= 0;
146fcf3ce44SJohn Forte 			break;
147*82527734SSukumar Swaminathan 
148fcf3ce44SJohn Forte 		case MEM_MBOX:
149*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "MBOX Pool");
150*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_MBOX;
151*82527734SSukumar Swaminathan 			seg->fc_memsize	= sizeof (MAILBOXQ);
152*82527734SSukumar Swaminathan 			seg->fc_numblks	= (int16_t)hba->max_nodes + 32;
153*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
154*82527734SSukumar Swaminathan 			seg->fc_memflag	= 0;
155fcf3ce44SJohn Forte 			break;
156*82527734SSukumar Swaminathan 
157fcf3ce44SJohn Forte 		case MEM_BPL:
158*82527734SSukumar Swaminathan 			if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
159*82527734SSukumar Swaminathan 				continue;
160*82527734SSukumar Swaminathan 			}
161*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "BPL Pool");
162*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BPL;
163*82527734SSukumar Swaminathan 			seg->fc_memsize	= hba->sli.sli3.mem_bpl_size;
164*82527734SSukumar Swaminathan 			seg->fc_numblks	= (int16_t)hba->max_iotag + 2;
165*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
166*82527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
167*82527734SSukumar Swaminathan 			seg->fc_memalign = 32;
168fcf3ce44SJohn Forte 			break;
169*82527734SSukumar Swaminathan 
170fcf3ce44SJohn Forte 		case MEM_BUF:
171*82527734SSukumar Swaminathan 			/* These are the unsolicited ELS buffers. */
172*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "BUF Pool");
173*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_BUF;
174*82527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_BUF_SIZE;
175*82527734SSukumar Swaminathan 			seg->fc_numblks	= MEM_ELSBUF_COUNT + MEM_BUF_COUNT;
176*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
177*82527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
178*82527734SSukumar Swaminathan 			seg->fc_memalign = 32;
179fcf3ce44SJohn Forte 			break;
180*82527734SSukumar Swaminathan 
181fcf3ce44SJohn Forte 		case MEM_IPBUF:
182*82527734SSukumar Swaminathan 			/* These are the unsolicited IP buffers. */
183*82527734SSukumar Swaminathan 			if (cfg[CFG_NETWORK_ON].current == 0) {
184*82527734SSukumar Swaminathan 				continue;
185fcf3ce44SJohn Forte 			}
186fcf3ce44SJohn Forte 
187*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "IPBUF Pool");
188*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_IPBUF;
189*82527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_IPBUF_SIZE;
190*82527734SSukumar Swaminathan 			seg->fc_numblks	= MEM_IPBUF_COUNT;
191*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
192*82527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
193*82527734SSukumar Swaminathan 			seg->fc_memalign = 32;
194*82527734SSukumar Swaminathan 			break;
195*82527734SSukumar Swaminathan 
196*82527734SSukumar Swaminathan 		case MEM_CTBUF:
197*82527734SSukumar Swaminathan 			/* These are the unsolicited CT buffers. */
198*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "CTBUF Pool");
199*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_CTBUF;
200*82527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_CTBUF_SIZE;
201*82527734SSukumar Swaminathan 			seg->fc_numblks	= MEM_CTBUF_COUNT;
202*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
203*82527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
204*82527734SSukumar Swaminathan 			seg->fc_memalign = 32;
205*82527734SSukumar Swaminathan 			break;
206*82527734SSukumar Swaminathan 
207*82527734SSukumar Swaminathan 		case MEM_FCTBUF:
208*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
209*82527734SSukumar Swaminathan 			/* These are the unsolicited FCT buffers. */
210*82527734SSukumar Swaminathan 			if (hba->tgt_mode == 0) {
211*82527734SSukumar Swaminathan 				continue;
212*82527734SSukumar Swaminathan 			}
213*82527734SSukumar Swaminathan 
214*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "FCTBUF Pool");
215*82527734SSukumar Swaminathan 			seg->fc_memtag	= MEM_FCTBUF;
216*82527734SSukumar Swaminathan 			seg->fc_memsize	= MEM_FCTBUF_SIZE;
217*82527734SSukumar Swaminathan 			seg->fc_numblks	= MEM_FCTBUF_COUNT;
218*82527734SSukumar Swaminathan 			seg->fc_reserved = 0;
219*82527734SSukumar Swaminathan 			seg->fc_memflag	= FC_MBUF_DMA | FC_MBUF_SNGLSG;
220*82527734SSukumar Swaminathan 			seg->fc_memalign = 32;
221*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
222*82527734SSukumar Swaminathan 			break;
223*82527734SSukumar Swaminathan 
224*82527734SSukumar Swaminathan 		default:
225*82527734SSukumar Swaminathan 			continue;
226*82527734SSukumar Swaminathan 		}
227*82527734SSukumar Swaminathan 
228*82527734SSukumar Swaminathan 		if (seg->fc_memsize == 0) {
229*82527734SSukumar Swaminathan 			continue;
230*82527734SSukumar Swaminathan 		}
231*82527734SSukumar Swaminathan 
232*82527734SSukumar Swaminathan 		if (emlxs_mem_pool_alloc(hba, seg) == NULL) {
233*82527734SSukumar Swaminathan 			goto failed;
234*82527734SSukumar Swaminathan 		}
235fcf3ce44SJohn Forte 
236fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
237*82527734SSukumar Swaminathan 		    "%s: seg=%p size=%x count=%d flags=%x base=%p",
238*82527734SSukumar Swaminathan 		    seg->fc_label, seg, seg->fc_memsize, seg->fc_numblks,
239*82527734SSukumar Swaminathan 		    seg->fc_memflag, seg->fc_memget_ptr);
240fcf3ce44SJohn Forte 	}
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 	return (1);
243fcf3ce44SJohn Forte 
244*82527734SSukumar Swaminathan failed:
245fcf3ce44SJohn Forte 
246*82527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
247*82527734SSukumar Swaminathan 	return (0);
248*82527734SSukumar Swaminathan 
249*82527734SSukumar Swaminathan } /* emlxs_mem_alloc_buffer() */
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte /*
253fcf3ce44SJohn Forte  * emlxs_mem_free_buffer
254fcf3ce44SJohn Forte  *
255fcf3ce44SJohn Forte  * This routine will free iocb/data buffer space
256fcf3ce44SJohn Forte  * and TGTM resource.
257fcf3ce44SJohn Forte  */
258fcf3ce44SJohn Forte extern int
259fcf3ce44SJohn Forte emlxs_mem_free_buffer(emlxs_hba_t *hba)
260fcf3ce44SJohn Forte {
261fcf3ce44SJohn Forte 	emlxs_port_t *vport;
262fcf3ce44SJohn Forte 	int32_t j;
263*82527734SSukumar Swaminathan 	MATCHMAP *mp;
264*82527734SSukumar Swaminathan 	CHANNEL *cp;
265fcf3ce44SJohn Forte 	RING *rp;
266fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
267fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 	buf_info = &bufinfo;
270fcf3ce44SJohn Forte 
271*82527734SSukumar Swaminathan 	for (j = 0; j < hba->chan_count; j++) {
272*82527734SSukumar Swaminathan 		cp = &hba->chan[j];
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte 		/* Flush the ring */
275*82527734SSukumar Swaminathan 		(void) emlxs_tx_channel_flush(hba, cp, 0);
276*82527734SSukumar Swaminathan 	}
277*82527734SSukumar Swaminathan 
278*82527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
279*82527734SSukumar Swaminathan 		/* free the mapped address match area for each ring */
280*82527734SSukumar Swaminathan 		for (j = 0; j < MAX_RINGS; j++) {
281*82527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[j];
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 			while (rp->fc_mpoff) {
284fcf3ce44SJohn Forte 				uint64_t addr;
285fcf3ce44SJohn Forte 
286fcf3ce44SJohn Forte 				addr = 0;
287*82527734SSukumar Swaminathan 				mp = (MATCHMAP *)(rp->fc_mpoff);
288fcf3ce44SJohn Forte 
289*82527734SSukumar Swaminathan 				if ((j == hba->channel_els) ||
290*82527734SSukumar Swaminathan 				    (j == hba->channel_ct) ||
291fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
292*82527734SSukumar Swaminathan 				    (j == hba->CHANNEL_FCT) ||
293fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */
294*82527734SSukumar Swaminathan 				    (j == hba->channel_ip)) {
295*82527734SSukumar Swaminathan 					addr = mp->phys;
296fcf3ce44SJohn Forte 				}
297291a2b48SSukumar Swaminathan 
298*82527734SSukumar Swaminathan 				if ((mp = emlxs_mem_get_vaddr(hba, rp, addr))) {
299*82527734SSukumar Swaminathan 					if (j == hba->channel_els) {
300*82527734SSukumar Swaminathan 						(void) emlxs_mem_put(hba,
301*82527734SSukumar Swaminathan 						    MEM_ELSBUF, (uint8_t *)mp);
302*82527734SSukumar Swaminathan 					} else if (j == hba->channel_ct) {
303*82527734SSukumar Swaminathan 						(void) emlxs_mem_put(hba,
304*82527734SSukumar Swaminathan 						    MEM_CTBUF, (uint8_t *)mp);
305*82527734SSukumar Swaminathan 					} else if (j == hba->channel_ip) {
306*82527734SSukumar Swaminathan 						(void) emlxs_mem_put(hba,
307*82527734SSukumar Swaminathan 						    MEM_IPBUF, (uint8_t *)mp);
308fcf3ce44SJohn Forte 					}
309fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
310*82527734SSukumar Swaminathan 					else if (j == hba->CHANNEL_FCT) {
311*82527734SSukumar Swaminathan 						(void) emlxs_mem_put(hba,
312*82527734SSukumar Swaminathan 						    MEM_FCTBUF, (uint8_t *)mp);
313fcf3ce44SJohn Forte 					}
314fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 				}
317fcf3ce44SJohn Forte 			}
318fcf3ce44SJohn Forte 		}
319*82527734SSukumar Swaminathan 	}
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
322fcf3ce44SJohn Forte 		emlxs_hbq_free_all(hba, EMLXS_ELS_HBQ_ID);
323fcf3ce44SJohn Forte 		emlxs_hbq_free_all(hba, EMLXS_IP_HBQ_ID);
324fcf3ce44SJohn Forte 		emlxs_hbq_free_all(hba, EMLXS_CT_HBQ_ID);
325*82527734SSukumar Swaminathan 
326fcf3ce44SJohn Forte 		if (hba->tgt_mode) {
327fcf3ce44SJohn Forte 			emlxs_hbq_free_all(hba, EMLXS_FCT_HBQ_ID);
328fcf3ce44SJohn Forte 		}
329fcf3ce44SJohn Forte 	}
330fcf3ce44SJohn Forte 
331fcf3ce44SJohn Forte 	/* Free the nodes */
332fcf3ce44SJohn Forte 	for (j = 0; j < MAX_VPORTS; j++) {
333fcf3ce44SJohn Forte 		vport = &VPORT(j);
334fcf3ce44SJohn Forte 		if (vport->node_count) {
335fcf3ce44SJohn Forte 			emlxs_node_destroy_all(vport);
336fcf3ce44SJohn Forte 		}
337fcf3ce44SJohn Forte 	}
338fcf3ce44SJohn Forte 
339*82527734SSukumar Swaminathan 	/* Make sure the mailbox queue is empty */
340*82527734SSukumar Swaminathan 	emlxs_mb_flush(hba);
341*82527734SSukumar Swaminathan 
342fcf3ce44SJohn Forte 	/* Free memory associated with all buffers on get buffer pool */
343*82527734SSukumar Swaminathan 	if (hba->fc_table) {
344fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
345*82527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (emlxs_buf_t *);
346*82527734SSukumar Swaminathan 		buf_info->virt = hba->fc_table;
347fcf3ce44SJohn Forte 		emlxs_mem_free(hba, buf_info);
348*82527734SSukumar Swaminathan 		hba->fc_table = NULL;
349fcf3ce44SJohn Forte 	}
350*82527734SSukumar Swaminathan 
351fcf3ce44SJohn Forte #ifdef EMLXS_SPARC
352*82527734SSukumar Swaminathan 	if (hba->sli.sli3.fcp_bpl_table) {
353fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
354*82527734SSukumar Swaminathan 		buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
355*82527734SSukumar Swaminathan 		buf_info->virt = hba->sli.sli3.fcp_bpl_table;
356fcf3ce44SJohn Forte 		emlxs_mem_free(hba, buf_info);
357*82527734SSukumar Swaminathan 		hba->sli.sli3.fcp_bpl_table = NULL;
358fcf3ce44SJohn Forte 	}
359291a2b48SSukumar Swaminathan 
360*82527734SSukumar Swaminathan 	if (hba->sli.sli3.fcp_bpl_seg.fc_memsize) {
361*82527734SSukumar Swaminathan 		emlxs_mem_pool_free(hba, &hba->sli.sli3.fcp_bpl_seg);
362*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli3.fcp_bpl_seg, sizeof (MEMSEG));
363fcf3ce44SJohn Forte 	}
364fcf3ce44SJohn Forte #endif /* EMLXS_SPARC */
365fcf3ce44SJohn Forte 
366fcf3ce44SJohn Forte 	/* Free the memory segments */
367fcf3ce44SJohn Forte 	for (j = 0; j < FC_MAX_SEG; j++) {
368*82527734SSukumar Swaminathan 		emlxs_mem_pool_free(hba, &hba->memseg[j]);
369fcf3ce44SJohn Forte 	}
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 	return (0);
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte } /* emlxs_mem_free_buffer() */
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte 
376*82527734SSukumar Swaminathan extern MEMSEG *
377*82527734SSukumar Swaminathan emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg)
378fcf3ce44SJohn Forte {
379fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
380fcf3ce44SJohn Forte 	uint8_t *bp = NULL;
381*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
382*82527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
383*82527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
384*82527734SSukumar Swaminathan 	uint32_t i;
385*82527734SSukumar Swaminathan 
386*82527734SSukumar Swaminathan 	buf_info = &local_buf_info;
387*82527734SSukumar Swaminathan 
388*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
389*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
390*82527734SSukumar Swaminathan 
391*82527734SSukumar Swaminathan 	/* Calculate total memory size */
392*82527734SSukumar Swaminathan 	seg->fc_total_memsize = (seg->fc_memsize * seg->fc_numblks);
393*82527734SSukumar Swaminathan 
394*82527734SSukumar Swaminathan 	if (seg->fc_total_memsize == 0) {
395*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
396*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMGET_LOCK);
397*82527734SSukumar Swaminathan 		return (NULL);
398*82527734SSukumar Swaminathan 	}
399*82527734SSukumar Swaminathan 
400*82527734SSukumar Swaminathan 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
401*82527734SSukumar Swaminathan 		goto vmem_pool;
402*82527734SSukumar Swaminathan 	}
403*82527734SSukumar Swaminathan 
404*82527734SSukumar Swaminathan /* dma_pool */
405*82527734SSukumar Swaminathan 
406*82527734SSukumar Swaminathan 	for (i = 0; i < seg->fc_numblks; i++) {
407*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
408*82527734SSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
409*82527734SSukumar Swaminathan 		buf_info->align = sizeof (void *);
410*82527734SSukumar Swaminathan 
411*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
412*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
413*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
414*82527734SSukumar Swaminathan 			    "%s desc[%d]. size=%d", seg->fc_label, i,
415*82527734SSukumar Swaminathan 			    buf_info->size);
416*82527734SSukumar Swaminathan 
417*82527734SSukumar Swaminathan 			goto failed;
418*82527734SSukumar Swaminathan 		}
419*82527734SSukumar Swaminathan 
420*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)buf_info->virt;
421*82527734SSukumar Swaminathan 		bzero(mp, sizeof (MATCHMAP));
422*82527734SSukumar Swaminathan 
423*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
424*82527734SSukumar Swaminathan 		buf_info->size  = seg->fc_memsize;
425*82527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
426*82527734SSukumar Swaminathan 		buf_info->align = seg->fc_memalign;
427*82527734SSukumar Swaminathan 
428*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
429*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
430*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
431*82527734SSukumar Swaminathan 			    "%s buffer[%d]. size=%d", seg->fc_label, i,
432*82527734SSukumar Swaminathan 			    buf_info->size);
433*82527734SSukumar Swaminathan 
434*82527734SSukumar Swaminathan 			/* Free the mp object */
435*82527734SSukumar Swaminathan 			bzero(buf_info, sizeof (MBUF_INFO));
436*82527734SSukumar Swaminathan 			buf_info->size = sizeof (MATCHMAP);
437*82527734SSukumar Swaminathan 			buf_info->virt = (uint32_t *)mp;
438*82527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
439*82527734SSukumar Swaminathan 
440*82527734SSukumar Swaminathan 			goto failed;
441*82527734SSukumar Swaminathan 		}
442*82527734SSukumar Swaminathan 		bp = (uint8_t *)buf_info->virt;
443*82527734SSukumar Swaminathan 		bzero(bp, seg->fc_memsize);
444*82527734SSukumar Swaminathan 
445*82527734SSukumar Swaminathan 		mp->virt = buf_info->virt;
446*82527734SSukumar Swaminathan 		mp->phys = buf_info->phys;
447*82527734SSukumar Swaminathan 		mp->size = buf_info->size;
448*82527734SSukumar Swaminathan 		mp->dma_handle = buf_info->dma_handle;
449*82527734SSukumar Swaminathan 		mp->data_handle = buf_info->data_handle;
450*82527734SSukumar Swaminathan 		mp->tag = seg->fc_memtag;
451*82527734SSukumar Swaminathan 		mp->segment = seg;
452*82527734SSukumar Swaminathan 		mp->flag |= MAP_POOL_ALLOCATED;
453*82527734SSukumar Swaminathan 
454*82527734SSukumar Swaminathan 		/* Add the buffer desc to the tail of the pool freelist */
455*82527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
456*82527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)mp;
457*82527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
458*82527734SSukumar Swaminathan 		} else {
459*82527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)mp;
460*82527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
461*82527734SSukumar Swaminathan 		}
462*82527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)mp;
463*82527734SSukumar Swaminathan 	}
464*82527734SSukumar Swaminathan 
465*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
466*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
467*82527734SSukumar Swaminathan 	return (seg);
468*82527734SSukumar Swaminathan 
469*82527734SSukumar Swaminathan vmem_pool:
470*82527734SSukumar Swaminathan 
471*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
472*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
473*82527734SSukumar Swaminathan 
474*82527734SSukumar Swaminathan 	seg->fc_memstart_virt = kmem_zalloc(seg->fc_total_memsize, KM_SLEEP);
475*82527734SSukumar Swaminathan 
476*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
477*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
478*82527734SSukumar Swaminathan 
479*82527734SSukumar Swaminathan 	if (seg->fc_memstart_virt == NULL) {
480*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
481*82527734SSukumar Swaminathan 		    "%s base. size=%d", seg->fc_label,
482*82527734SSukumar Swaminathan 		    seg->fc_total_memsize);
483*82527734SSukumar Swaminathan 
484*82527734SSukumar Swaminathan 		goto failed;
485*82527734SSukumar Swaminathan 	}
486*82527734SSukumar Swaminathan 
487*82527734SSukumar Swaminathan 	bp = (uint8_t *)seg->fc_memstart_virt;
488*82527734SSukumar Swaminathan 	for (i = 0; i < seg->fc_numblks; i++) {
489*82527734SSukumar Swaminathan 
490*82527734SSukumar Swaminathan 		/* Add the buffer to the tail of the pool freelist */
491*82527734SSukumar Swaminathan 		if (seg->fc_memget_end == NULL) {
492*82527734SSukumar Swaminathan 			seg->fc_memget_ptr = (uint8_t *)bp;
493*82527734SSukumar Swaminathan 			seg->fc_memget_cnt = 1;
494*82527734SSukumar Swaminathan 		} else {
495*82527734SSukumar Swaminathan 			*((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)bp;
496*82527734SSukumar Swaminathan 			seg->fc_memget_cnt++;
497*82527734SSukumar Swaminathan 		}
498*82527734SSukumar Swaminathan 		seg->fc_memget_end = (uint8_t *)bp;
499*82527734SSukumar Swaminathan 
500*82527734SSukumar Swaminathan 		bp += seg->fc_memsize;
501*82527734SSukumar Swaminathan 	}
502*82527734SSukumar Swaminathan 
503*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
504*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
505*82527734SSukumar Swaminathan 	return (seg);
506*82527734SSukumar Swaminathan 
507*82527734SSukumar Swaminathan failed:
508*82527734SSukumar Swaminathan 
509*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
510*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
511*82527734SSukumar Swaminathan 	emlxs_mem_pool_free(hba, seg);
512*82527734SSukumar Swaminathan 	return (NULL);
513*82527734SSukumar Swaminathan 
514*82527734SSukumar Swaminathan } /* emlxs_mem_pool_alloc() */
515*82527734SSukumar Swaminathan 
516*82527734SSukumar Swaminathan 
517*82527734SSukumar Swaminathan extern void
518*82527734SSukumar Swaminathan emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg)
519*82527734SSukumar Swaminathan {
520*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
521*82527734SSukumar Swaminathan 	uint8_t *bp = NULL;
522*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
523*82527734SSukumar Swaminathan 	MBUF_INFO *buf_info;
524*82527734SSukumar Swaminathan 	MBUF_INFO local_buf_info;
525*82527734SSukumar Swaminathan 	MEMSEG segment;
526*82527734SSukumar Swaminathan 	uint32_t free;
527*82527734SSukumar Swaminathan 
528*82527734SSukumar Swaminathan 	/* Save a local copy of the segment and */
529*82527734SSukumar Swaminathan 	/* destroy the original outside of locks */
530*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
531*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
532*82527734SSukumar Swaminathan 
533*82527734SSukumar Swaminathan 	free = seg->fc_memget_cnt + seg->fc_memput_cnt;
534*82527734SSukumar Swaminathan 	if (free < seg->fc_numblks) {
535*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
536*82527734SSukumar Swaminathan 		    "emlxs_mem_pool_free: %s not full. (%d < %d)",
537*82527734SSukumar Swaminathan 		    seg->fc_label, free, seg->fc_numblks);
538*82527734SSukumar Swaminathan 	}
539*82527734SSukumar Swaminathan 
540*82527734SSukumar Swaminathan 	bcopy(seg, &segment, sizeof (MEMSEG));
541*82527734SSukumar Swaminathan 	bzero((char *)seg, sizeof (MEMSEG));
542*82527734SSukumar Swaminathan 	seg = &segment;
543*82527734SSukumar Swaminathan 
544*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
545*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
546*82527734SSukumar Swaminathan 
547*82527734SSukumar Swaminathan 	/* Now free the memory  */
548*82527734SSukumar Swaminathan 
549*82527734SSukumar Swaminathan 	if (!(seg->fc_memflag & FC_MBUF_DMA)) {
550*82527734SSukumar Swaminathan 		if (seg->fc_memstart_virt) {
551*82527734SSukumar Swaminathan 			kmem_free(seg->fc_memstart_virt, seg->fc_total_memsize);
552*82527734SSukumar Swaminathan 		}
553*82527734SSukumar Swaminathan 
554*82527734SSukumar Swaminathan 		return;
555*82527734SSukumar Swaminathan 	}
556*82527734SSukumar Swaminathan 
557*82527734SSukumar Swaminathan 	buf_info = &local_buf_info;
558*82527734SSukumar Swaminathan 
559*82527734SSukumar Swaminathan 	/* Free memory associated with all buffers on get buffer pool */
560*82527734SSukumar Swaminathan 	while ((bp = seg->fc_memget_ptr) != NULL) {
561*82527734SSukumar Swaminathan 		seg->fc_memget_ptr = *((uint8_t **)bp);
562*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
563*82527734SSukumar Swaminathan 
564*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
565*82527734SSukumar Swaminathan 		buf_info->size = mp->size;
566*82527734SSukumar Swaminathan 		buf_info->virt = mp->virt;
567*82527734SSukumar Swaminathan 		buf_info->phys = mp->phys;
568*82527734SSukumar Swaminathan 		buf_info->dma_handle = mp->dma_handle;
569*82527734SSukumar Swaminathan 		buf_info->data_handle = mp->data_handle;
570*82527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
571*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
572*82527734SSukumar Swaminathan 
573*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
574*82527734SSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
575*82527734SSukumar Swaminathan 		buf_info->virt = (uint32_t *)mp;
576*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
577*82527734SSukumar Swaminathan 	}
578*82527734SSukumar Swaminathan 
579*82527734SSukumar Swaminathan 	/* Free memory associated with all buffers on put buffer pool */
580*82527734SSukumar Swaminathan 	while ((bp = seg->fc_memput_ptr) != NULL) {
581*82527734SSukumar Swaminathan 		seg->fc_memput_ptr = *((uint8_t **)bp);
582*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
583*82527734SSukumar Swaminathan 
584*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
585*82527734SSukumar Swaminathan 		buf_info->size = mp->size;
586*82527734SSukumar Swaminathan 		buf_info->virt = mp->virt;
587*82527734SSukumar Swaminathan 		buf_info->phys = mp->phys;
588*82527734SSukumar Swaminathan 		buf_info->dma_handle = mp->dma_handle;
589*82527734SSukumar Swaminathan 		buf_info->data_handle = mp->data_handle;
590*82527734SSukumar Swaminathan 		buf_info->flags = seg->fc_memflag;
591*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
592*82527734SSukumar Swaminathan 
593*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
594*82527734SSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
595*82527734SSukumar Swaminathan 		buf_info->virt = (uint32_t *)mp;
596*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
597*82527734SSukumar Swaminathan 	}
598*82527734SSukumar Swaminathan 
599*82527734SSukumar Swaminathan 	return;
600*82527734SSukumar Swaminathan 
601*82527734SSukumar Swaminathan } /* emlxs_mem_pool_free() */
602*82527734SSukumar Swaminathan 
603*82527734SSukumar Swaminathan 
604*82527734SSukumar Swaminathan extern uint8_t *
605*82527734SSukumar Swaminathan emlxs_mem_pool_get(emlxs_hba_t *hba, MEMSEG *seg, uint32_t priority)
606*82527734SSukumar Swaminathan {
607*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
608*82527734SSukumar Swaminathan 	uint8_t *bp = NULL;
609*82527734SSukumar Swaminathan 	MATCHMAP *mp;
610*82527734SSukumar Swaminathan 	uint32_t free;
611*82527734SSukumar Swaminathan 
612*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMGET_LOCK);
613*82527734SSukumar Swaminathan 
614*82527734SSukumar Swaminathan 	/* Check if memory segment destroyed! */
615*82527734SSukumar Swaminathan 	if (seg->fc_total_memsize == 0) {
616*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMGET_LOCK);
617*82527734SSukumar Swaminathan 		return (NULL);
618*82527734SSukumar Swaminathan 	}
619*82527734SSukumar Swaminathan 
620*82527734SSukumar Swaminathan 	/* Check priority and reserved status */
621*82527734SSukumar Swaminathan 	if ((priority == 0) && seg->fc_reserved) {
622*82527734SSukumar Swaminathan 		free = seg->fc_memget_cnt + seg->fc_memput_cnt;
623*82527734SSukumar Swaminathan 		if (free <= seg->fc_reserved) {
624*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
625*82527734SSukumar Swaminathan 			    "%s low. (%d <= %d)", seg->fc_label,
626*82527734SSukumar Swaminathan 			    free, seg->fc_reserved);
627*82527734SSukumar Swaminathan 
628*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMGET_LOCK);
629*82527734SSukumar Swaminathan 			return (NULL);
630*82527734SSukumar Swaminathan 		}
631*82527734SSukumar Swaminathan 	}
632*82527734SSukumar Swaminathan 
633*82527734SSukumar Swaminathan top:
634*82527734SSukumar Swaminathan 
635*82527734SSukumar Swaminathan 	if (seg->fc_memget_ptr) {
636*82527734SSukumar Swaminathan 
637*82527734SSukumar Swaminathan 		bp = seg->fc_memget_ptr;
638*82527734SSukumar Swaminathan 
639*82527734SSukumar Swaminathan 		/* Remove buffer from freelist */
640*82527734SSukumar Swaminathan 		if (seg->fc_memget_end == bp) {
641*82527734SSukumar Swaminathan 			seg->fc_memget_ptr = NULL;
642*82527734SSukumar Swaminathan 			seg->fc_memget_end = NULL;
643*82527734SSukumar Swaminathan 			seg->fc_memget_cnt = 0;
644*82527734SSukumar Swaminathan 
645*82527734SSukumar Swaminathan 		} else {
646*82527734SSukumar Swaminathan 			seg->fc_memget_ptr = *((uint8_t **)bp);
647*82527734SSukumar Swaminathan 			seg->fc_memget_cnt--;
648*82527734SSukumar Swaminathan 		}
649*82527734SSukumar Swaminathan 
650*82527734SSukumar Swaminathan 		if (!(seg->fc_memflag & FC_MBUF_DMA)) {
651*82527734SSukumar Swaminathan 			bzero(bp, seg->fc_memsize);
652*82527734SSukumar Swaminathan 		} else {
653*82527734SSukumar Swaminathan 			mp = (MATCHMAP *)bp;
654*82527734SSukumar Swaminathan 			mp->fc_mptr = NULL;
655*82527734SSukumar Swaminathan 			mp->flag |= MAP_POOL_ALLOCATED;
656*82527734SSukumar Swaminathan 		}
657*82527734SSukumar Swaminathan 
658*82527734SSukumar Swaminathan 	} else {
659*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MEMPUT_LOCK);
660*82527734SSukumar Swaminathan 		if (seg->fc_memput_ptr) {
661*82527734SSukumar Swaminathan 			/*
662*82527734SSukumar Swaminathan 			 * Move list from memput to memget
663*82527734SSukumar Swaminathan 			 */
664*82527734SSukumar Swaminathan 			seg->fc_memget_ptr = seg->fc_memput_ptr;
665*82527734SSukumar Swaminathan 			seg->fc_memget_end = seg->fc_memput_end;
666*82527734SSukumar Swaminathan 			seg->fc_memget_cnt = seg->fc_memput_cnt;
667*82527734SSukumar Swaminathan 			seg->fc_memput_ptr = NULL;
668*82527734SSukumar Swaminathan 			seg->fc_memput_end = NULL;
669*82527734SSukumar Swaminathan 			seg->fc_memput_cnt = 0;
670*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMPUT_LOCK);
671*82527734SSukumar Swaminathan 
672*82527734SSukumar Swaminathan 			goto top;
673*82527734SSukumar Swaminathan 		}
674*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
675*82527734SSukumar Swaminathan 
676*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
677*82527734SSukumar Swaminathan 		    "%s empty.", seg->fc_label);
678*82527734SSukumar Swaminathan 	}
679*82527734SSukumar Swaminathan 
680*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMGET_LOCK);
681*82527734SSukumar Swaminathan 
682*82527734SSukumar Swaminathan 	return (bp);
683*82527734SSukumar Swaminathan 
684*82527734SSukumar Swaminathan } /* emlxs_mem_pool_get() */
685*82527734SSukumar Swaminathan 
686*82527734SSukumar Swaminathan 
687*82527734SSukumar Swaminathan extern MEMSEG *
688*82527734SSukumar Swaminathan emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp)
689*82527734SSukumar Swaminathan {
690*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
691*82527734SSukumar Swaminathan 	MATCHMAP *mp;
692*82527734SSukumar Swaminathan 	uint8_t *base;
693*82527734SSukumar Swaminathan 	uint8_t *end;
694*82527734SSukumar Swaminathan 
695*82527734SSukumar Swaminathan 	/* Free the pool object */
696*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_MEMPUT_LOCK);
697*82527734SSukumar Swaminathan 
698*82527734SSukumar Swaminathan 	/* Check if memory segment destroyed! */
699*82527734SSukumar Swaminathan 	if (seg->fc_total_memsize == 0) {
700*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
701*82527734SSukumar Swaminathan 		return (NULL);
702*82527734SSukumar Swaminathan 	}
703*82527734SSukumar Swaminathan 
704*82527734SSukumar Swaminathan 	/* Check if buffer was just freed */
705*82527734SSukumar Swaminathan 	if (seg->fc_memput_ptr == bp) {
706*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
707*82527734SSukumar Swaminathan 		    "%s: Freeing free object: bp=%p", seg->fc_label, bp);
708*82527734SSukumar Swaminathan 
709*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MEMPUT_LOCK);
710*82527734SSukumar Swaminathan 		return (NULL);
711*82527734SSukumar Swaminathan 	}
712*82527734SSukumar Swaminathan 
713*82527734SSukumar Swaminathan 	/* Validate the buffer belongs to this pool */
714*82527734SSukumar Swaminathan 	if (seg->fc_memflag & FC_MBUF_DMA) {
715*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
716*82527734SSukumar Swaminathan 
717*82527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED) ||
718*82527734SSukumar Swaminathan 		    (mp->segment != seg)) {
719*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
720*82527734SSukumar Swaminathan 			    "emlxs_mem_pool_put: %s invalid: mp=%p " \
721*82527734SSukumar Swaminathan 			    "tag=0x%x flag=%x", seg->fc_label,
722*82527734SSukumar Swaminathan 			    mp, mp->tag, mp->flag);
723*82527734SSukumar Swaminathan 
724*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
725*82527734SSukumar Swaminathan 
726*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMPUT_LOCK);
727*82527734SSukumar Swaminathan 
728*82527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
729*82527734SSukumar Swaminathan 			    NULL, NULL);
730*82527734SSukumar Swaminathan 
731*82527734SSukumar Swaminathan 			return (NULL);
732*82527734SSukumar Swaminathan 		}
733*82527734SSukumar Swaminathan 
734*82527734SSukumar Swaminathan 	} else { /* Vmem_pool */
735*82527734SSukumar Swaminathan 		base = seg->fc_memstart_virt;
736*82527734SSukumar Swaminathan 		end = seg->fc_memstart_virt + seg->fc_total_memsize;
737*82527734SSukumar Swaminathan 
738*82527734SSukumar Swaminathan 		if (bp < base || bp >= end) {
739*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
740*82527734SSukumar Swaminathan 			    "emlxs_mem_pool_put: %s Invalid: bp=%p base=%p " \
741*82527734SSukumar Swaminathan 			    "end=%p", seg->fc_label,
742*82527734SSukumar Swaminathan 			    bp, base, end);
743*82527734SSukumar Swaminathan 
744*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
745*82527734SSukumar Swaminathan 
746*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MEMPUT_LOCK);
747*82527734SSukumar Swaminathan 
748*82527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
749*82527734SSukumar Swaminathan 			    NULL, NULL);
750*82527734SSukumar Swaminathan 
751*82527734SSukumar Swaminathan 			return (NULL);
752*82527734SSukumar Swaminathan 		}
753*82527734SSukumar Swaminathan 	}
754*82527734SSukumar Swaminathan 
755*82527734SSukumar Swaminathan 	/* Release buffer to the end of the freelist */
756*82527734SSukumar Swaminathan 	if (seg->fc_memput_end == NULL) {
757*82527734SSukumar Swaminathan 		seg->fc_memput_ptr = bp;
758*82527734SSukumar Swaminathan 		seg->fc_memput_cnt = 1;
759*82527734SSukumar Swaminathan 	} else {
760*82527734SSukumar Swaminathan 		*((uint8_t **)(seg->fc_memput_end)) = bp;
761*82527734SSukumar Swaminathan 		seg->fc_memput_cnt++;
762*82527734SSukumar Swaminathan 	}
763*82527734SSukumar Swaminathan 	seg->fc_memput_end = bp;
764*82527734SSukumar Swaminathan 	*((uint8_t **)(bp)) = NULL;
765*82527734SSukumar Swaminathan 
766*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_MEMPUT_LOCK);
767*82527734SSukumar Swaminathan 
768*82527734SSukumar Swaminathan 	return (seg);
769*82527734SSukumar Swaminathan 
770*82527734SSukumar Swaminathan } /* emlxs_mem_pool_put() */
771*82527734SSukumar Swaminathan 
772*82527734SSukumar Swaminathan 
773*82527734SSukumar Swaminathan extern MATCHMAP *
774*82527734SSukumar Swaminathan emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size)
775*82527734SSukumar Swaminathan {
776*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
777*82527734SSukumar Swaminathan 	uint8_t *bp = NULL;
778*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
779fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
780fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
781fcf3ce44SJohn Forte 
782fcf3ce44SJohn Forte 	buf_info = &bufinfo;
783fcf3ce44SJohn Forte 
784fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
785fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
786fcf3ce44SJohn Forte 	buf_info->align = sizeof (void *);
787fcf3ce44SJohn Forte 
788fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
789fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
790fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
791fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC buffer.");
792fcf3ce44SJohn Forte 
793*82527734SSukumar Swaminathan 		return (NULL);
794fcf3ce44SJohn Forte 	}
795291a2b48SSukumar Swaminathan 
796*82527734SSukumar Swaminathan 	mp = (MATCHMAP *)buf_info->virt;
797*82527734SSukumar Swaminathan 	bzero(mp, sizeof (MATCHMAP));
798fcf3ce44SJohn Forte 
799fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
800*82527734SSukumar Swaminathan 	buf_info->size = size;
801*82527734SSukumar Swaminathan 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
802fcf3ce44SJohn Forte 	buf_info->align = 32;
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 	(void) emlxs_mem_alloc(hba, buf_info);
805fcf3ce44SJohn Forte 	if (buf_info->virt == NULL) {
806fcf3ce44SJohn Forte 
807fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
808fcf3ce44SJohn Forte 		    "MEM_BUF_ALLOC DMA buffer.");
809fcf3ce44SJohn Forte 
810*82527734SSukumar Swaminathan 		/* Free the mp object */
811728bdc9bSSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
812728bdc9bSSukumar Swaminathan 		buf_info->size = sizeof (MATCHMAP);
813*82527734SSukumar Swaminathan 		buf_info->virt = (uint32_t *)mp;
814728bdc9bSSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
815728bdc9bSSukumar Swaminathan 
816fcf3ce44SJohn Forte 		return (0);
817fcf3ce44SJohn Forte 	}
818fcf3ce44SJohn Forte 	bp = (uint8_t *)buf_info->virt;
819fcf3ce44SJohn Forte 	bzero(bp, MEM_BUF_SIZE);
820fcf3ce44SJohn Forte 
821*82527734SSukumar Swaminathan 	mp->virt = buf_info->virt;
822*82527734SSukumar Swaminathan 	mp->phys = buf_info->phys;
823*82527734SSukumar Swaminathan 	mp->size = buf_info->size;
824*82527734SSukumar Swaminathan 	mp->dma_handle = buf_info->dma_handle;
825*82527734SSukumar Swaminathan 	mp->data_handle = buf_info->data_handle;
826*82527734SSukumar Swaminathan 	mp->tag = MEM_BUF;
827*82527734SSukumar Swaminathan 	mp->flag |= MAP_BUF_ALLOCATED;
828fcf3ce44SJohn Forte 
829*82527734SSukumar Swaminathan 	return (mp);
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte } /* emlxs_mem_buf_alloc() */
832fcf3ce44SJohn Forte 
833fcf3ce44SJohn Forte 
834*82527734SSukumar Swaminathan extern MATCHMAP *
835*82527734SSukumar Swaminathan emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp)
836fcf3ce44SJohn Forte {
837fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
838fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
839fcf3ce44SJohn Forte 
840fcf3ce44SJohn Forte 	buf_info = &bufinfo;
841fcf3ce44SJohn Forte 
842*82527734SSukumar Swaminathan 	if (!(mp->flag & MAP_BUF_ALLOCATED)) {
843fcf3ce44SJohn Forte 		return (NULL);
844fcf3ce44SJohn Forte 	}
845fcf3ce44SJohn Forte 
846fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
847*82527734SSukumar Swaminathan 	buf_info->size = mp->size;
848*82527734SSukumar Swaminathan 	buf_info->virt = mp->virt;
849*82527734SSukumar Swaminathan 	buf_info->phys = mp->phys;
850*82527734SSukumar Swaminathan 	buf_info->dma_handle = mp->dma_handle;
851*82527734SSukumar Swaminathan 	buf_info->data_handle = mp->data_handle;
852fcf3ce44SJohn Forte 	buf_info->flags = FC_MBUF_DMA;
853fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
854fcf3ce44SJohn Forte 
855fcf3ce44SJohn Forte 	bzero(buf_info, sizeof (MBUF_INFO));
856fcf3ce44SJohn Forte 	buf_info->size = sizeof (MATCHMAP);
857*82527734SSukumar Swaminathan 	buf_info->virt = (uint32_t *)mp;
858fcf3ce44SJohn Forte 	emlxs_mem_free(hba, buf_info);
859fcf3ce44SJohn Forte 
860*82527734SSukumar Swaminathan 	return (mp);
861fcf3ce44SJohn Forte 
862fcf3ce44SJohn Forte } /* emlxs_mem_buf_free() */
863fcf3ce44SJohn Forte 
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte extern uint8_t *
866*82527734SSukumar Swaminathan emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id, uint32_t priority)
867fcf3ce44SJohn Forte {
868fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
869*82527734SSukumar Swaminathan 	uint8_t *bp;
870fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
871fcf3ce44SJohn Forte 	IOCBQ *iocbq;
872fcf3ce44SJohn Forte 	NODELIST *node;
873*82527734SSukumar Swaminathan 	MEMSEG *seg;
874fcf3ce44SJohn Forte 
875*82527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
876291a2b48SSukumar Swaminathan 
877*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
878*82527734SSukumar Swaminathan 		    "emlxs_mem_get: Invalid segment id = %d",
879*82527734SSukumar Swaminathan 		    seg_id);
880fcf3ce44SJohn Forte 
881fcf3ce44SJohn Forte 		return (NULL);
882fcf3ce44SJohn Forte 	}
883*82527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
884291a2b48SSukumar Swaminathan 
885*82527734SSukumar Swaminathan 	/* Alloc a buffer from the pool */
886*82527734SSukumar Swaminathan 	bp = emlxs_mem_pool_get(hba, seg, priority);
887fcf3ce44SJohn Forte 
888*82527734SSukumar Swaminathan 	if (bp) {
889*82527734SSukumar Swaminathan 		switch (seg_id) {
890fcf3ce44SJohn Forte 		case MEM_MBOX:
891fcf3ce44SJohn Forte 			mbq = (MAILBOXQ *)bp;
892fcf3ce44SJohn Forte 			mbq->flag |= MBQ_POOL_ALLOCATED;
893fcf3ce44SJohn Forte 			break;
894fcf3ce44SJohn Forte 
895fcf3ce44SJohn Forte 		case MEM_IOCB:
896fcf3ce44SJohn Forte 			iocbq = (IOCBQ *)bp;
897fcf3ce44SJohn Forte 			iocbq->flag |= IOCB_POOL_ALLOCATED;
898fcf3ce44SJohn Forte 			break;
899fcf3ce44SJohn Forte 
900fcf3ce44SJohn Forte 		case MEM_NLP:
901fcf3ce44SJohn Forte 			node = (NODELIST *)bp;
902fcf3ce44SJohn Forte 			node->flag |= NODE_POOL_ALLOCATED;
903fcf3ce44SJohn Forte 			break;
904fcf3ce44SJohn Forte 		}
905fcf3ce44SJohn Forte 	}
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 	return (bp);
908fcf3ce44SJohn Forte 
909fcf3ce44SJohn Forte } /* emlxs_mem_get() */
910fcf3ce44SJohn Forte 
911fcf3ce44SJohn Forte 
912fcf3ce44SJohn Forte extern uint8_t *
913*82527734SSukumar Swaminathan emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp)
914fcf3ce44SJohn Forte {
915fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
916fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
917*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
918fcf3ce44SJohn Forte 	NODELIST *node;
919*82527734SSukumar Swaminathan 	MEMSEG *seg;
920*82527734SSukumar Swaminathan 	MATCHMAP *mp;
921fcf3ce44SJohn Forte 
922*82527734SSukumar Swaminathan 	if (seg_id >= FC_MAX_SEG) {
923*82527734SSukumar Swaminathan 
924*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
925*82527734SSukumar Swaminathan 		    "emlxs_mem_put: Invalid segment id = %d: bp=%p",
926*82527734SSukumar Swaminathan 		    seg_id, bp);
927*82527734SSukumar Swaminathan 
928fcf3ce44SJohn Forte 		return (NULL);
929fcf3ce44SJohn Forte 	}
930*82527734SSukumar Swaminathan 	seg = &hba->memseg[seg_id];
931291a2b48SSukumar Swaminathan 
932*82527734SSukumar Swaminathan 	/* Verify buffer */
933*82527734SSukumar Swaminathan 	switch (seg_id) {
934fcf3ce44SJohn Forte 	case MEM_MBOX:
935fcf3ce44SJohn Forte 		mbq = (MAILBOXQ *)bp;
936fcf3ce44SJohn Forte 
937fcf3ce44SJohn Forte 		if (!(mbq->flag & MBQ_POOL_ALLOCATED)) {
938*82527734SSukumar Swaminathan 			return (NULL);
939fcf3ce44SJohn Forte 		}
940fcf3ce44SJohn Forte 		break;
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte 	case MEM_IOCB:
943fcf3ce44SJohn Forte 		iocbq = (IOCBQ *)bp;
944fcf3ce44SJohn Forte 
945fcf3ce44SJohn Forte 		if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) {
946*82527734SSukumar Swaminathan 			return (NULL);
947fcf3ce44SJohn Forte 		}
948291a2b48SSukumar Swaminathan 
949291a2b48SSukumar Swaminathan 		/* Any IOCBQ with a packet attached did not come */
950291a2b48SSukumar Swaminathan 		/* from our pool */
951fcf3ce44SJohn Forte 		if (iocbq->sbp) {
952*82527734SSukumar Swaminathan 			return (NULL);
953fcf3ce44SJohn Forte 		}
954fcf3ce44SJohn Forte 		break;
955fcf3ce44SJohn Forte 
956fcf3ce44SJohn Forte 	case MEM_NLP:
957fcf3ce44SJohn Forte 		node = (NODELIST *)bp;
958fcf3ce44SJohn Forte 
959fcf3ce44SJohn Forte 		if (!(node->flag & NODE_POOL_ALLOCATED)) {
960*82527734SSukumar Swaminathan 			return (NULL);
961fcf3ce44SJohn Forte 		}
962fcf3ce44SJohn Forte 		break;
963fcf3ce44SJohn Forte 
964fcf3ce44SJohn Forte 	default:
965*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)bp;
966fcf3ce44SJohn Forte 
967*82527734SSukumar Swaminathan 		if (mp->flag & MAP_BUF_ALLOCATED) {
968*82527734SSukumar Swaminathan 			return ((uint8_t *)emlxs_mem_buf_free(hba, mp));
969fcf3ce44SJohn Forte 		}
970291a2b48SSukumar Swaminathan 
971*82527734SSukumar Swaminathan 		if (mp->flag & MAP_TABLE_ALLOCATED) {
972fcf3ce44SJohn Forte 			return (bp);
973fcf3ce44SJohn Forte 		}
974291a2b48SSukumar Swaminathan 
975*82527734SSukumar Swaminathan 		if (!(mp->flag & MAP_POOL_ALLOCATED)) {
976*82527734SSukumar Swaminathan 			return (NULL);
977fcf3ce44SJohn Forte 		}
978fcf3ce44SJohn Forte 		break;
979fcf3ce44SJohn Forte 	}
980fcf3ce44SJohn Forte 
981*82527734SSukumar Swaminathan 	/* Free a buffer to the pool */
982*82527734SSukumar Swaminathan 	if (emlxs_mem_pool_put(hba, seg, bp) == NULL) {
983fcf3ce44SJohn Forte 		return (NULL);
984fcf3ce44SJohn Forte 	}
985291a2b48SSukumar Swaminathan 
986fcf3ce44SJohn Forte 	return (bp);
987fcf3ce44SJohn Forte 
988fcf3ce44SJohn Forte } /* emlxs_mem_put() */
989fcf3ce44SJohn Forte 
990fcf3ce44SJohn Forte 
991fcf3ce44SJohn Forte /*
992fcf3ce44SJohn Forte  * Look up the virtual address given a mapped address
993fcf3ce44SJohn Forte  */
994*82527734SSukumar Swaminathan /* SLI3 */
995fcf3ce44SJohn Forte extern MATCHMAP *
996fcf3ce44SJohn Forte emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp)
997fcf3ce44SJohn Forte {
998fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
999fcf3ce44SJohn Forte 	MATCHMAP *prev;
1000fcf3ce44SJohn Forte 	MATCHMAP *mp;
1001fcf3ce44SJohn Forte 
1002*82527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1003fcf3ce44SJohn Forte 		mp = (MATCHMAP *)rp->fc_mpoff;
1004fcf3ce44SJohn Forte 		prev = 0;
1005fcf3ce44SJohn Forte 
1006fcf3ce44SJohn Forte 		while (mp) {
1007fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1008fcf3ce44SJohn Forte 				if (prev == 0) {
1009fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1010fcf3ce44SJohn Forte 				} else {
1011fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1012fcf3ce44SJohn Forte 				}
1013fcf3ce44SJohn Forte 
1014fcf3ce44SJohn Forte 				if (rp->fc_mpon == (uint8_t *)mp) {
1015fcf3ce44SJohn Forte 					rp->fc_mpon = (uint8_t *)prev;
1016fcf3ce44SJohn Forte 				}
1017291a2b48SSukumar Swaminathan 
1018fcf3ce44SJohn Forte 				mp->fc_mptr = 0;
1019fcf3ce44SJohn Forte 
1020*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1021fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1022fcf3ce44SJohn Forte 
1023fcf3ce44SJohn Forte 				HBASTATS.ElsUbPosted--;
1024fcf3ce44SJohn Forte 
1025fcf3ce44SJohn Forte 				return (mp);
1026fcf3ce44SJohn Forte 			}
1027291a2b48SSukumar Swaminathan 
1028fcf3ce44SJohn Forte 			prev = mp;
1029fcf3ce44SJohn Forte 			mp = (MATCHMAP *)mp->fc_mptr;
1030fcf3ce44SJohn Forte 		}
1031fcf3ce44SJohn Forte 
1032fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1033fcf3ce44SJohn Forte 		    "ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1034fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1035fcf3ce44SJohn Forte 
1036*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1037fcf3ce44SJohn Forte 
1038fcf3ce44SJohn Forte 		mp = (MATCHMAP *)rp->fc_mpoff;
1039fcf3ce44SJohn Forte 		prev = 0;
1040fcf3ce44SJohn Forte 
1041fcf3ce44SJohn Forte 		while (mp) {
1042fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1043fcf3ce44SJohn Forte 				if (prev == 0) {
1044fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1045fcf3ce44SJohn Forte 				} else {
1046fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1047fcf3ce44SJohn Forte 				}
1048fcf3ce44SJohn Forte 
1049fcf3ce44SJohn Forte 				if (rp->fc_mpon == (uint8_t *)mp) {
1050fcf3ce44SJohn Forte 					rp->fc_mpon = (uint8_t *)prev;
1051fcf3ce44SJohn Forte 				}
1052291a2b48SSukumar Swaminathan 
1053fcf3ce44SJohn Forte 				mp->fc_mptr = 0;
1054fcf3ce44SJohn Forte 
1055*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1056fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1057fcf3ce44SJohn Forte 
1058fcf3ce44SJohn Forte 				HBASTATS.CtUbPosted--;
1059fcf3ce44SJohn Forte 
1060fcf3ce44SJohn Forte 				return (mp);
1061fcf3ce44SJohn Forte 			}
1062291a2b48SSukumar Swaminathan 
1063fcf3ce44SJohn Forte 			prev = mp;
1064fcf3ce44SJohn Forte 			mp = (MATCHMAP *)mp->fc_mptr;
1065fcf3ce44SJohn Forte 		}
1066fcf3ce44SJohn Forte 
1067fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1068fcf3ce44SJohn Forte 		    "CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1069fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1070fcf3ce44SJohn Forte 
1071*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1072fcf3ce44SJohn Forte 
1073fcf3ce44SJohn Forte 		mp = (MATCHMAP *)rp->fc_mpoff;
1074fcf3ce44SJohn Forte 		prev = 0;
1075fcf3ce44SJohn Forte 
1076fcf3ce44SJohn Forte 		while (mp) {
1077fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1078fcf3ce44SJohn Forte 				if (prev == 0) {
1079fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1080fcf3ce44SJohn Forte 				} else {
1081fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1082fcf3ce44SJohn Forte 				}
1083fcf3ce44SJohn Forte 
1084fcf3ce44SJohn Forte 				if (rp->fc_mpon == (uint8_t *)mp) {
1085fcf3ce44SJohn Forte 					rp->fc_mpon = (uint8_t *)prev;
1086fcf3ce44SJohn Forte 				}
1087291a2b48SSukumar Swaminathan 
1088fcf3ce44SJohn Forte 				mp->fc_mptr = 0;
1089fcf3ce44SJohn Forte 
1090*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1091fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1092fcf3ce44SJohn Forte 
1093fcf3ce44SJohn Forte 				HBASTATS.IpUbPosted--;
1094fcf3ce44SJohn Forte 
1095fcf3ce44SJohn Forte 				return (mp);
1096fcf3ce44SJohn Forte 			}
1097291a2b48SSukumar Swaminathan 
1098fcf3ce44SJohn Forte 			prev = mp;
1099fcf3ce44SJohn Forte 			mp = (MATCHMAP *)mp->fc_mptr;
1100fcf3ce44SJohn Forte 		}
1101fcf3ce44SJohn Forte 
1102fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1103fcf3ce44SJohn Forte 		    "IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1104fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1105fcf3ce44SJohn Forte 
1106fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
1107*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1108fcf3ce44SJohn Forte 		mp = (MATCHMAP *)rp->fc_mpoff;
1109fcf3ce44SJohn Forte 		prev = 0;
1110fcf3ce44SJohn Forte 
1111fcf3ce44SJohn Forte 		while (mp) {
1112fcf3ce44SJohn Forte 			if (mp->phys == mapbp) {
1113fcf3ce44SJohn Forte 				if (prev == 0) {
1114fcf3ce44SJohn Forte 					rp->fc_mpoff = mp->fc_mptr;
1115fcf3ce44SJohn Forte 				} else {
1116fcf3ce44SJohn Forte 					prev->fc_mptr = mp->fc_mptr;
1117fcf3ce44SJohn Forte 				}
1118fcf3ce44SJohn Forte 
1119fcf3ce44SJohn Forte 				if (rp->fc_mpon == (uint8_t *)mp) {
1120fcf3ce44SJohn Forte 					rp->fc_mpon = (uint8_t *)prev;
1121fcf3ce44SJohn Forte 				}
1122291a2b48SSukumar Swaminathan 
1123fcf3ce44SJohn Forte 				mp->fc_mptr = 0;
1124fcf3ce44SJohn Forte 
1125*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1126fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
1127fcf3ce44SJohn Forte 
1128fcf3ce44SJohn Forte 				HBASTATS.FctUbPosted--;
1129fcf3ce44SJohn Forte 
1130fcf3ce44SJohn Forte 				return (mp);
1131fcf3ce44SJohn Forte 			}
1132291a2b48SSukumar Swaminathan 
1133fcf3ce44SJohn Forte 			prev = mp;
1134fcf3ce44SJohn Forte 			mp = (MATCHMAP *)mp->fc_mptr;
1135fcf3ce44SJohn Forte 		}
1136fcf3ce44SJohn Forte 
1137fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1138fcf3ce44SJohn Forte 		    "FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1139fcf3ce44SJohn Forte 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1140fcf3ce44SJohn Forte 
1141fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */
1142fcf3ce44SJohn Forte 	}
1143fcf3ce44SJohn Forte 
1144fcf3ce44SJohn Forte 	return (0);
1145fcf3ce44SJohn Forte 
1146fcf3ce44SJohn Forte } /* emlxs_mem_get_vaddr() */
1147fcf3ce44SJohn Forte 
1148fcf3ce44SJohn Forte 
1149fcf3ce44SJohn Forte /*
1150291a2b48SSukumar Swaminathan  * Given a virtual address bp, generate the physical mapped address and
1151291a2b48SSukumar Swaminathan  * place it where addr points to. Save the address pair for lookup later.
1152fcf3ce44SJohn Forte  */
1153*82527734SSukumar Swaminathan /* SLI3 */
1154fcf3ce44SJohn Forte extern void
1155291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp,
1156291a2b48SSukumar Swaminathan     uint32_t *haddr, uint32_t *laddr)
1157fcf3ce44SJohn Forte {
1158*82527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
1159fcf3ce44SJohn Forte 		/*
1160291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1161291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1162291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1163fcf3ce44SJohn Forte 		 */
1164fcf3ce44SJohn Forte 		mp->fc_mptr = 0;
1165fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1166fcf3ce44SJohn Forte 			rp->fc_mpoff = (uint8_t *)mp;
1167fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1168fcf3ce44SJohn Forte 		} else {
1169291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1170291a2b48SSukumar Swaminathan 			    (uint8_t *)mp;
1171fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1172fcf3ce44SJohn Forte 		}
1173fcf3ce44SJohn Forte 
1174fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1175291a2b48SSukumar Swaminathan 
1176fcf3ce44SJohn Forte 			/* return mapped address */
1177*82527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1178291a2b48SSukumar Swaminathan 			/* return mapped address */
1179*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1180fcf3ce44SJohn Forte 		} else {
1181fcf3ce44SJohn Forte 			/* return mapped address */
1182*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1183fcf3ce44SJohn Forte 		}
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 		HBASTATS.ElsUbPosted++;
1186fcf3ce44SJohn Forte 
1187*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ct) {
1188fcf3ce44SJohn Forte 		/*
1189291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1190291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1191291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1192fcf3ce44SJohn Forte 		 */
1193fcf3ce44SJohn Forte 		mp->fc_mptr = 0;
1194fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1195fcf3ce44SJohn Forte 			rp->fc_mpoff = (uint8_t *)mp;
1196fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1197fcf3ce44SJohn Forte 		} else {
1198291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1199291a2b48SSukumar Swaminathan 			    (uint8_t *)mp;
1200fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1201fcf3ce44SJohn Forte 		}
1202fcf3ce44SJohn Forte 
1203fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1204fcf3ce44SJohn Forte 			/* return mapped address */
1205*82527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1206291a2b48SSukumar Swaminathan 			/* return mapped address */
1207*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1208fcf3ce44SJohn Forte 		} else {
1209fcf3ce44SJohn Forte 			/* return mapped address */
1210*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1211fcf3ce44SJohn Forte 		}
1212fcf3ce44SJohn Forte 
1213fcf3ce44SJohn Forte 		HBASTATS.CtUbPosted++;
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 
1216*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->channel_ip) {
1217fcf3ce44SJohn Forte 		/*
1218291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1219291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1220291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1221fcf3ce44SJohn Forte 		 */
1222fcf3ce44SJohn Forte 		mp->fc_mptr = 0;
1223fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1224fcf3ce44SJohn Forte 			rp->fc_mpoff = (uint8_t *)mp;
1225fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1226fcf3ce44SJohn Forte 		} else {
1227291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1228291a2b48SSukumar Swaminathan 			    (uint8_t *)mp;
1229fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1230fcf3ce44SJohn Forte 		}
1231fcf3ce44SJohn Forte 
1232fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1233fcf3ce44SJohn Forte 			/* return mapped address */
1234*82527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1235*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1236fcf3ce44SJohn Forte 		} else {
1237*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1238fcf3ce44SJohn Forte 		}
1239fcf3ce44SJohn Forte 
1240fcf3ce44SJohn Forte 		HBASTATS.IpUbPosted++;
1241fcf3ce44SJohn Forte 
1242fcf3ce44SJohn Forte 
1243fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
1244*82527734SSukumar Swaminathan 	} else if (rp->ringno == hba->CHANNEL_FCT) {
1245fcf3ce44SJohn Forte 		/*
1246291a2b48SSukumar Swaminathan 		 * Update slot fc_mpon points to then bump it
1247291a2b48SSukumar Swaminathan 		 * fc_mpoff is pointer head of the list.
1248291a2b48SSukumar Swaminathan 		 * fc_mpon is pointer tail of the list.
1249fcf3ce44SJohn Forte 		 */
1250fcf3ce44SJohn Forte 		mp->fc_mptr = 0;
1251fcf3ce44SJohn Forte 		if (rp->fc_mpoff == 0) {
1252fcf3ce44SJohn Forte 			rp->fc_mpoff = (uint8_t *)mp;
1253fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1254fcf3ce44SJohn Forte 		} else {
1255291a2b48SSukumar Swaminathan 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1256291a2b48SSukumar Swaminathan 			    (uint8_t *)mp;
1257fcf3ce44SJohn Forte 			rp->fc_mpon = (uint8_t *)mp;
1258fcf3ce44SJohn Forte 		}
1259fcf3ce44SJohn Forte 
1260fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1261fcf3ce44SJohn Forte 			/* return mapped address */
1262*82527734SSukumar Swaminathan 			*haddr = PADDR_HI(mp->phys);
1263291a2b48SSukumar Swaminathan 			/* return mapped address */
1264*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1265fcf3ce44SJohn Forte 		} else {
1266fcf3ce44SJohn Forte 			/* return mapped address */
1267*82527734SSukumar Swaminathan 			*laddr = PADDR_LO(mp->phys);
1268fcf3ce44SJohn Forte 		}
1269fcf3ce44SJohn Forte 
1270fcf3ce44SJohn Forte 		HBASTATS.FctUbPosted++;
1271*82527734SSukumar Swaminathan 
1272fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */
1273fcf3ce44SJohn Forte 	}
1274fcf3ce44SJohn Forte } /* emlxs_mem_map_vaddr() */
1275fcf3ce44SJohn Forte 
1276fcf3ce44SJohn Forte 
1277*82527734SSukumar Swaminathan /* SLI3 */
1278291a2b48SSukumar Swaminathan uint32_t
1279fcf3ce44SJohn Forte emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id)
1280fcf3ce44SJohn Forte {
1281fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1282fcf3ce44SJohn Forte 	HBQ_INIT_t *hbq;
1283fcf3ce44SJohn Forte 	MBUF_INFO *buf_info;
1284fcf3ce44SJohn Forte 	MBUF_INFO bufinfo;
1285fcf3ce44SJohn Forte 
1286*82527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
1287fcf3ce44SJohn Forte 
1288fcf3ce44SJohn Forte 	if (hbq->HBQ_host_buf.virt == 0) {
1289fcf3ce44SJohn Forte 		buf_info = &bufinfo;
1290fcf3ce44SJohn Forte 
1291fcf3ce44SJohn Forte 		/* Get the system's page size in a DDI-compliant way. */
1292fcf3ce44SJohn Forte 		bzero(buf_info, sizeof (MBUF_INFO));
1293fcf3ce44SJohn Forte 		buf_info->size = hbq->HBQ_numEntries * sizeof (HBQE_t);
1294fcf3ce44SJohn Forte 		buf_info->flags = FC_MBUF_DMA;
1295fcf3ce44SJohn Forte 		buf_info->align = 4096;
1296fcf3ce44SJohn Forte 
1297fcf3ce44SJohn Forte 		(void) emlxs_mem_alloc(hba, buf_info);
1298fcf3ce44SJohn Forte 
1299fcf3ce44SJohn Forte 		if (buf_info->virt == NULL) {
1300fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
1301fcf3ce44SJohn Forte 			    "Unable to alloc HBQ.");
1302fcf3ce44SJohn Forte 			return (ENOMEM);
1303fcf3ce44SJohn Forte 		}
1304291a2b48SSukumar Swaminathan 
1305fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.virt = (void *)buf_info->virt;
1306fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.phys = buf_info->phys;
1307fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.data_handle = buf_info->data_handle;
1308fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle;
1309fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.size = buf_info->size;
1310fcf3ce44SJohn Forte 		hbq->HBQ_host_buf.tag = hbq_id;
1311fcf3ce44SJohn Forte 
1312fcf3ce44SJohn Forte 		bzero((char *)hbq->HBQ_host_buf.virt, buf_info->size);
1313fcf3ce44SJohn Forte 	}
1314291a2b48SSukumar Swaminathan 
1315fcf3ce44SJohn Forte 	return (0);
1316fcf3ce44SJohn Forte 
1317fcf3ce44SJohn Forte } /* emlxs_hbq_alloc() */
1318