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