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
9 * http://www.opensource.org/licenses/cddl1.txt.
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 (c) 2004-2011 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <emlxs.h>
28
29 /* #define EMLXS_POOL_DEBUG */
30
31 EMLXS_MSG_DEF(EMLXS_MEM_C);
32
33
34 static uint32_t emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg,
35 uint32_t count);
36 static void emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count);
37
38
39 extern int32_t
emlxs_mem_alloc_buffer(emlxs_hba_t * hba)40 emlxs_mem_alloc_buffer(emlxs_hba_t *hba)
41 {
42 emlxs_port_t *port = &PPORT;
43 emlxs_config_t *cfg;
44 MBUF_INFO *buf_info;
45 MEMSEG *seg;
46 MBUF_INFO bufinfo;
47 int32_t i;
48 MATCHMAP *mp;
49 MATCHMAP **bpl_table;
50
51 buf_info = &bufinfo;
52 cfg = &CFG;
53
54 bzero(hba->memseg, sizeof (hba->memseg));
55
56 /* Allocate the fc_table */
57 bzero(buf_info, sizeof (MBUF_INFO));
58 buf_info->size = (hba->max_iotag * sizeof (emlxs_buf_t *));
59
60 (void) emlxs_mem_alloc(hba, buf_info);
61 if (buf_info->virt == NULL) {
62
63 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
64 "fc_table buffer.");
65
66 goto failed;
67 }
68 hba->fc_table = buf_info->virt;
69 bzero(hba->fc_table, buf_info->size);
70
71 /* Prepare the memory pools */
72 for (i = 0; i < FC_MAX_SEG; i++) {
73 seg = &hba->memseg[i];
74
75 switch (i) {
76 case MEM_NLP:
77 (void) strlcpy(seg->fc_label, "Node Pool",
78 sizeof (seg->fc_label));
79 seg->fc_memtag = MEM_NLP;
80 seg->fc_memsize = sizeof (NODELIST);
81 seg->fc_hi_water = hba->max_nodes + 2;
82 seg->fc_lo_water = 2;
83 seg->fc_step = 1;
84 break;
85
86 case MEM_IOCB:
87 (void) strlcpy(seg->fc_label, "IOCB Pool",
88 sizeof (seg->fc_label));
89 seg->fc_memtag = MEM_IOCB;
90 seg->fc_memsize = sizeof (IOCBQ);
91 seg->fc_hi_water = cfg[CFG_NUM_IOCBS].current;
92 seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
93 seg->fc_step = cfg[CFG_NUM_IOCBS].low;
94 break;
95
96 case MEM_MBOX:
97 (void) strlcpy(seg->fc_label, "MBOX Pool",
98 sizeof (seg->fc_label));
99 seg->fc_memtag = MEM_MBOX;
100 seg->fc_memsize = sizeof (MAILBOXQ);
101 seg->fc_hi_water = hba->max_nodes + 32;
102 seg->fc_lo_water = 32;
103 seg->fc_step = 1;
104 break;
105
106 case MEM_BPL:
107 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
108 continue;
109 }
110 (void) strlcpy(seg->fc_label, "BPL Pool",
111 sizeof (seg->fc_label));
112 seg->fc_memtag = MEM_BPL;
113 seg->fc_memsize = hba->sli.sli3.mem_bpl_size;
114 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG;
115 seg->fc_memalign = 32;
116 seg->fc_hi_water = hba->max_iotag;
117 seg->fc_lo_water = cfg[CFG_NUM_IOCBS].low;
118 seg->fc_step = cfg[CFG_NUM_IOCBS].low;
119 break;
120
121 case MEM_BUF:
122 /* These are the unsolicited ELS buffers. */
123 (void) strlcpy(seg->fc_label, "BUF Pool",
124 sizeof (seg->fc_label));
125 seg->fc_memtag = MEM_BUF;
126 seg->fc_memsize = MEM_BUF_SIZE;
127 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG;
128 seg->fc_memalign = 32;
129 seg->fc_hi_water = MEM_ELSBUF_COUNT + MEM_BUF_COUNT;
130 seg->fc_lo_water = MEM_ELSBUF_COUNT;
131 seg->fc_step = 1;
132 break;
133
134 case MEM_IPBUF:
135 /* These are the unsolicited IP buffers. */
136 if (cfg[CFG_NETWORK_ON].current == 0) {
137 continue;
138 }
139
140 (void) strlcpy(seg->fc_label, "IPBUF Pool",
141 sizeof (seg->fc_label));
142 seg->fc_memtag = MEM_IPBUF;
143 seg->fc_memsize = MEM_IPBUF_SIZE;
144 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG;
145 seg->fc_memalign = 32;
146 seg->fc_hi_water = MEM_IPBUF_COUNT;
147 seg->fc_lo_water = 0;
148 seg->fc_step = 4;
149 break;
150
151 case MEM_CTBUF:
152 /* These are the unsolicited CT buffers. */
153 (void) strlcpy(seg->fc_label, "CTBUF Pool",
154 sizeof (seg->fc_label));
155 seg->fc_memtag = MEM_CTBUF;
156 seg->fc_memsize = MEM_CTBUF_SIZE;
157 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG;
158 seg->fc_memalign = 32;
159 seg->fc_hi_water = MEM_CTBUF_COUNT;
160 seg->fc_lo_water = MEM_CTBUF_COUNT;
161 seg->fc_step = 1;
162 break;
163
164 #ifdef SFCT_SUPPORT
165 case MEM_FCTBUF:
166 /* These are the unsolicited FCT buffers. */
167 if (!(port->flag & EMLXS_TGT_ENABLED)) {
168 continue;
169 }
170
171 (void) strlcpy(seg->fc_label, "FCTBUF Pool",
172 sizeof (seg->fc_label));
173 seg->fc_memtag = MEM_FCTBUF;
174 seg->fc_memsize = MEM_FCTBUF_SIZE;
175 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG;
176 seg->fc_memalign = 32;
177 seg->fc_hi_water = MEM_FCTBUF_COUNT;
178 seg->fc_lo_water = 0;
179 seg->fc_step = 8;
180 break;
181 #endif /* SFCT_SUPPORT */
182
183 default:
184 continue;
185 }
186
187 if (seg->fc_memsize == 0) {
188 continue;
189 }
190
191 (void) emlxs_mem_pool_create(hba, seg);
192
193 if (seg->fc_numblks < seg->fc_lo_water) {
194 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
195 "%s: count=%d size=%d flags=%x lo=%d hi=%d",
196 seg->fc_label, seg->fc_numblks,
197 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
198 seg->fc_hi_water);
199
200 goto failed;
201 }
202 }
203
204 hba->sli.sli3.bpl_table = NULL;
205 seg = &hba->memseg[MEM_BPL];
206
207 /* If SLI3 and MEM_BPL pool is static */
208 if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK) &&
209 !(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
210 /*
211 * Allocate and Initialize bpl_table
212 * This is for increased performance.
213 */
214 bzero(buf_info, sizeof (MBUF_INFO));
215 buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
216
217 (void) emlxs_mem_alloc(hba, buf_info);
218 if (buf_info->virt == NULL) {
219
220 EMLXS_MSGF(EMLXS_CONTEXT,
221 &emlxs_mem_alloc_failed_msg,
222 "BPL table buffer.");
223
224 goto failed;
225 }
226 hba->sli.sli3.bpl_table = buf_info->virt;
227
228 bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
229 for (i = 0; i < hba->max_iotag; i++) {
230 mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL);
231 mp->flag |= MAP_TABLE_ALLOCATED;
232 bpl_table[i] = mp;
233 }
234 }
235
236 return (1);
237
238 failed:
239
240 (void) emlxs_mem_free_buffer(hba);
241 return (0);
242
243 } /* emlxs_mem_alloc_buffer() */
244
245
246 /*
247 * emlxs_mem_free_buffer
248 *
249 * This routine will free iocb/data buffer space
250 * and TGTM resource.
251 */
252 extern int
emlxs_mem_free_buffer(emlxs_hba_t * hba)253 emlxs_mem_free_buffer(emlxs_hba_t *hba)
254 {
255 emlxs_port_t *port = &PPORT;
256 emlxs_port_t *vport;
257 int32_t j;
258 MATCHMAP *mp;
259 CHANNEL *cp;
260 RING *rp;
261 MBUF_INFO *buf_info;
262 MBUF_INFO bufinfo;
263 MATCHMAP **bpl_table;
264
265 buf_info = &bufinfo;
266
267 for (j = 0; j < hba->chan_count; j++) {
268 cp = &hba->chan[j];
269
270 /* Flush the ring */
271 (void) emlxs_tx_channel_flush(hba, cp, 0);
272 }
273
274 if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
275 /* free the mapped address match area for each ring */
276 for (j = 0; j < MAX_RINGS; j++) {
277 rp = &hba->sli.sli3.ring[j];
278
279 while (rp->fc_mpoff) {
280 uint64_t addr;
281
282 addr = 0;
283 mp = (MATCHMAP *)(rp->fc_mpoff);
284
285 if ((j == hba->channel_els) ||
286 (j == hba->channel_ct) ||
287 #ifdef SFCT_SUPPORT
288 (j == hba->CHANNEL_FCT) ||
289 #endif /* SFCT_SUPPORT */
290 (j == hba->channel_ip)) {
291 addr = mp->phys;
292 }
293
294 if ((mp = emlxs_mem_get_vaddr(hba, rp, addr))) {
295 if (j == hba->channel_els) {
296 emlxs_mem_put(hba,
297 MEM_ELSBUF, (void *)mp);
298 } else if (j == hba->channel_ct) {
299 emlxs_mem_put(hba,
300 MEM_CTBUF, (void *)mp);
301 } else if (j == hba->channel_ip) {
302 emlxs_mem_put(hba,
303 MEM_IPBUF, (void *)mp);
304 }
305 #ifdef SFCT_SUPPORT
306 else if (j == hba->CHANNEL_FCT) {
307 emlxs_mem_put(hba,
308 MEM_FCTBUF, (void *)mp);
309 }
310 #endif /* SFCT_SUPPORT */
311
312 }
313 }
314 }
315 }
316
317 if (hba->flag & FC_HBQ_ENABLED) {
318 emlxs_hbq_free_all(hba, EMLXS_ELS_HBQ_ID);
319 emlxs_hbq_free_all(hba, EMLXS_IP_HBQ_ID);
320 emlxs_hbq_free_all(hba, EMLXS_CT_HBQ_ID);
321
322 if (port->flag & EMLXS_TGT_ENABLED) {
323 emlxs_hbq_free_all(hba, EMLXS_FCT_HBQ_ID);
324 }
325 }
326
327 /* Free the nodes */
328 for (j = 0; j < MAX_VPORTS; j++) {
329 vport = &VPORT(j);
330 if (vport->node_count) {
331 emlxs_node_destroy_all(vport);
332 }
333 }
334
335 /* Make sure the mailbox queue is empty */
336 emlxs_mb_flush(hba);
337
338 if (hba->fc_table) {
339 bzero(buf_info, sizeof (MBUF_INFO));
340 buf_info->size = hba->max_iotag * sizeof (emlxs_buf_t *);
341 buf_info->virt = hba->fc_table;
342 emlxs_mem_free(hba, buf_info);
343 hba->fc_table = NULL;
344 }
345
346 if (hba->sli.sli3.bpl_table) {
347 /* Return MEM_BPLs to their pool */
348 bpl_table = (MATCHMAP**)hba->sli.sli3.bpl_table;
349 for (j = 0; j < hba->max_iotag; j++) {
350 mp = bpl_table[j];
351 mp->flag &= ~MAP_TABLE_ALLOCATED;
352 emlxs_mem_put(hba, MEM_BPL, (void*)mp);
353 }
354
355 bzero(buf_info, sizeof (MBUF_INFO));
356 buf_info->size = hba->max_iotag * sizeof (MATCHMAP *);
357 buf_info->virt = hba->sli.sli3.bpl_table;
358 emlxs_mem_free(hba, buf_info);
359 hba->sli.sli3.bpl_table = NULL;
360 }
361
362 /* Free the memory segments */
363 for (j = 0; j < FC_MAX_SEG; j++) {
364 emlxs_mem_pool_destroy(hba, &hba->memseg[j]);
365 }
366
367 return (0);
368
369 } /* emlxs_mem_free_buffer() */
370
371
372 /* Must hold EMLXS_MEMGET_LOCK when calling */
373 static uint32_t
emlxs_mem_pool_alloc(emlxs_hba_t * hba,MEMSEG * seg,uint32_t count)374 emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
375 {
376 emlxs_port_t *port = &PPORT;
377 uint8_t *bp = NULL;
378 MATCHMAP *mp = NULL;
379 MBUF_INFO *buf_info;
380 MBUF_INFO local_buf_info;
381 uint32_t i;
382 uint32_t fc_numblks;
383
384 if (seg->fc_memsize == 0) {
385 return (0);
386 }
387
388 if (seg->fc_numblks >= seg->fc_hi_water) {
389 return (0);
390 }
391
392 if (count == 0) {
393 return (0);
394 }
395
396 if (count > (seg->fc_hi_water - seg->fc_numblks)) {
397 count = (seg->fc_hi_water - seg->fc_numblks);
398 }
399
400 buf_info = &local_buf_info;
401 fc_numblks = seg->fc_numblks;
402
403 /* Check for initial allocation */
404 if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
406 "%s alloc:%d n=%d s=%d f=%x l=%d,%d,%d "
407 "f=%d:%d",
408 seg->fc_label, count, seg->fc_numblks,
409 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
410 seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
411 seg->fc_low);
412 }
413
414 if (!(seg->fc_memflag & FC_MBUF_DMA)) {
415 goto vmem_pool;
416 }
417
418 /* dma_pool */
419
420 for (i = 0; i < count; i++) {
421 bzero(buf_info, sizeof (MBUF_INFO));
422 buf_info->size = sizeof (MATCHMAP);
423 buf_info->align = sizeof (void *);
424
425 (void) emlxs_mem_alloc(hba, buf_info);
426 if (buf_info->virt == NULL) {
427 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
428 "%s: count=%d size=%d",
429 seg->fc_label, seg->fc_numblks, seg->fc_memsize);
430
431 goto done;
432 }
433
434 mp = (MATCHMAP *)buf_info->virt;
435 bzero(mp, sizeof (MATCHMAP));
436
437 bzero(buf_info, sizeof (MBUF_INFO));
438 buf_info->size = seg->fc_memsize;
439 buf_info->flags = seg->fc_memflag;
440 buf_info->align = seg->fc_memalign;
441
442 (void) emlxs_mem_alloc(hba, buf_info);
443 if (buf_info->virt == NULL) {
444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
445 "%s: count=%d size=%d",
446 seg->fc_label, seg->fc_numblks, seg->fc_memsize);
447
448 /* Free the mp object */
449 bzero(buf_info, sizeof (MBUF_INFO));
450 buf_info->size = sizeof (MATCHMAP);
451 buf_info->virt = (void *)mp;
452 emlxs_mem_free(hba, buf_info);
453
454 goto done;
455 }
456 bp = (uint8_t *)buf_info->virt;
457 bzero(bp, seg->fc_memsize);
458
459 mp->virt = buf_info->virt;
460 mp->phys = buf_info->phys;
461 mp->size = buf_info->size;
462 mp->dma_handle = buf_info->dma_handle;
463 mp->data_handle = buf_info->data_handle;
464 mp->tag = seg->fc_memtag;
465 mp->segment = seg;
466 mp->flag |= MAP_POOL_ALLOCATED;
467
468 #ifdef SFCT_SUPPORT
469 if (mp->tag >= MEM_FCTSEG) {
470 if (emlxs_fct_stmf_alloc(hba, mp)) {
471 /* Free the DMA memory itself */
472 emlxs_mem_free(hba, buf_info);
473
474 /* Free the mp object */
475 bzero(buf_info, sizeof (MBUF_INFO));
476 buf_info->size = sizeof (MATCHMAP);
477 buf_info->virt = (void *)mp;
478 emlxs_mem_free(hba, buf_info);
479
480 goto done;
481 }
482 }
483 #endif /* SFCT_SUPPORT */
484
485 /* Add the buffer desc to the tail of the pool freelist */
486 if (seg->fc_memget_end == NULL) {
487 seg->fc_memget_ptr = (uint8_t *)mp;
488 seg->fc_memget_cnt = 1;
489 } else {
490 *((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)mp;
491 seg->fc_memget_cnt++;
492 }
493 seg->fc_memget_end = (uint8_t *)mp;
494
495 seg->fc_numblks++;
496 seg->fc_total_memsize += (seg->fc_memsize + sizeof (MATCHMAP));
497 }
498
499 goto done;
500
501 vmem_pool:
502
503 for (i = 0; i < count; i++) {
504 bzero(buf_info, sizeof (MBUF_INFO));
505 buf_info->size = seg->fc_memsize;
506
507 (void) emlxs_mem_alloc(hba, buf_info);
508 if (buf_info->virt == NULL) {
509 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
510 "%s: count=%d size=%d",
511 seg->fc_label, seg->fc_numblks, seg->fc_memsize);
512
513 goto done;
514 }
515 bp = (uint8_t *)buf_info->virt;
516
517 /* Add the buffer to the tail of the pool freelist */
518 if (seg->fc_memget_end == NULL) {
519 seg->fc_memget_ptr = (uint8_t *)bp;
520 seg->fc_memget_cnt = 1;
521 } else {
522 *((uint8_t **)(seg->fc_memget_end)) = (uint8_t *)bp;
523 seg->fc_memget_cnt++;
524 }
525 seg->fc_memget_end = (uint8_t *)bp;
526
527 seg->fc_numblks++;
528 seg->fc_total_memsize += seg->fc_memsize;
529 }
530
531 done:
532
533 return ((seg->fc_numblks - fc_numblks));
534
535 } /* emlxs_mem_pool_alloc() */
536
537
538 /* Must hold EMLXS_MEMGET_LOCK & EMLXS_MEMPUT_LOCK when calling */
539 static void
emlxs_mem_pool_free(emlxs_hba_t * hba,MEMSEG * seg,uint32_t count)540 emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg, uint32_t count)
541 {
542 emlxs_port_t *port = &PPORT;
543 uint8_t *bp = NULL;
544 MATCHMAP *mp = NULL;
545 MBUF_INFO *buf_info;
546 MBUF_INFO local_buf_info;
547
548 if ((seg->fc_memsize == 0) ||
549 (seg->fc_numblks == 0) ||
550 (count == 0)) {
551 return;
552 }
553
554 /* Check max count */
555 if (count > seg->fc_numblks) {
556 count = seg->fc_numblks;
557 }
558
559 /* Move memput list to memget list */
560 if (seg->fc_memput_ptr) {
561 if (seg->fc_memget_end == NULL) {
562 seg->fc_memget_ptr = seg->fc_memput_ptr;
563 } else {
564 *((uint8_t **)(seg->fc_memget_end)) =\
565 seg->fc_memput_ptr;
566 }
567 seg->fc_memget_end = seg->fc_memput_end;
568 seg->fc_memget_cnt += seg->fc_memput_cnt;
569
570 seg->fc_memput_ptr = NULL;
571 seg->fc_memput_end = NULL;
572 seg->fc_memput_cnt = 0;
573 }
574
575 buf_info = &local_buf_info;
576
577 /* Check for final deallocation */
578 if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
579 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
580 "%s free:%d n=%d s=%d f=%x l=%d,%d,%d "
581 "f=%d:%d",
582 seg->fc_label, count, seg->fc_numblks,
583 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
584 seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
585 seg->fc_low);
586 }
587
588 if (!(seg->fc_memflag & FC_MBUF_DMA)) {
589 goto vmem_pool;
590 }
591
592 dma_pool:
593
594 /* Free memory associated with all buffers on get buffer pool */
595 while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
596 /* Remove buffer from list */
597 if (seg->fc_memget_end == bp) {
598 seg->fc_memget_ptr = NULL;
599 seg->fc_memget_end = NULL;
600 seg->fc_memget_cnt = 0;
601
602 } else {
603 seg->fc_memget_ptr = *((uint8_t **)bp);
604 seg->fc_memget_cnt--;
605 }
606 mp = (MATCHMAP *)bp;
607
608 #ifdef SFCT_SUPPORT
609 if (mp->tag >= MEM_FCTSEG) {
610 emlxs_fct_stmf_free(hba, mp);
611 }
612 #endif /* SFCT_SUPPORT */
613
614 /* Free the DMA memory itself */
615 bzero(buf_info, sizeof (MBUF_INFO));
616 buf_info->size = mp->size;
617 buf_info->virt = mp->virt;
618 buf_info->phys = mp->phys;
619 buf_info->dma_handle = mp->dma_handle;
620 buf_info->data_handle = mp->data_handle;
621 buf_info->flags = seg->fc_memflag;
622 emlxs_mem_free(hba, buf_info);
623
624 /* Free the handle */
625 bzero(buf_info, sizeof (MBUF_INFO));
626 buf_info->size = sizeof (MATCHMAP);
627 buf_info->virt = (void *)mp;
628 emlxs_mem_free(hba, buf_info);
629
630 seg->fc_numblks--;
631 seg->fc_total_memsize -= (seg->fc_memsize + sizeof (MATCHMAP));
632
633 count--;
634 }
635
636 return;
637
638 vmem_pool:
639
640 /* Free memory associated with all buffers on get buffer pool */
641 while (count && ((bp = seg->fc_memget_ptr) != NULL)) {
642 /* Remove buffer from list */
643 if (seg->fc_memget_end == bp) {
644 seg->fc_memget_ptr = NULL;
645 seg->fc_memget_end = NULL;
646 seg->fc_memget_cnt = 0;
647
648 } else {
649 seg->fc_memget_ptr = *((uint8_t **)bp);
650 seg->fc_memget_cnt--;
651 }
652
653 /* Free the Virtual memory itself */
654 bzero(buf_info, sizeof (MBUF_INFO));
655 buf_info->size = seg->fc_memsize;
656 buf_info->virt = bp;
657 emlxs_mem_free(hba, buf_info);
658
659 seg->fc_numblks--;
660 seg->fc_total_memsize -= seg->fc_memsize;
661
662 count--;
663 }
664
665 return;
666
667 } /* emlxs_mem_pool_free() */
668
669
670 extern uint32_t
emlxs_mem_pool_create(emlxs_hba_t * hba,MEMSEG * seg)671 emlxs_mem_pool_create(emlxs_hba_t *hba, MEMSEG *seg)
672 {
673 emlxs_config_t *cfg = &CFG;
674
675 mutex_enter(&EMLXS_MEMGET_LOCK);
676 mutex_enter(&EMLXS_MEMPUT_LOCK);
677
678 if (seg->fc_memsize == 0) {
679 mutex_exit(&EMLXS_MEMPUT_LOCK);
680 mutex_exit(&EMLXS_MEMGET_LOCK);
681
682 return (0);
683 }
684
685 /* Sanity check hi > lo */
686 if (seg->fc_lo_water > seg->fc_hi_water) {
687 seg->fc_hi_water = seg->fc_lo_water;
688 }
689
690 /* If dynamic pools are disabled, then force pool to max level */
691 if (cfg[CFG_MEM_DYNAMIC].current == 0) {
692 seg->fc_lo_water = seg->fc_hi_water;
693 }
694
695 /* If pool is dynamic, then fc_step must be >0 */
696 /* Otherwise, fc_step must be 0 */
697 if (seg->fc_lo_water != seg->fc_hi_water) {
698 seg->fc_memflag |= FC_MEMSEG_DYNAMIC;
699
700 if (seg->fc_step == 0) {
701 seg->fc_step = 1;
702 }
703 } else {
704 seg->fc_step = 0;
705 }
706
707 seg->fc_numblks = 0;
708 seg->fc_total_memsize = 0;
709 seg->fc_low = 0;
710
711 (void) emlxs_mem_pool_alloc(hba, seg, seg->fc_lo_water);
712
713 seg->fc_memflag |= (FC_MEMSEG_PUT_ENABLED|FC_MEMSEG_GET_ENABLED);
714
715 mutex_exit(&EMLXS_MEMPUT_LOCK);
716 mutex_exit(&EMLXS_MEMGET_LOCK);
717
718 return (seg->fc_numblks);
719
720 } /* emlxs_mem_pool_create() */
721
722
723 extern void
emlxs_mem_pool_destroy(emlxs_hba_t * hba,MEMSEG * seg)724 emlxs_mem_pool_destroy(emlxs_hba_t *hba, MEMSEG *seg)
725 {
726 emlxs_port_t *port = &PPORT;
727
728 mutex_enter(&EMLXS_MEMGET_LOCK);
729 mutex_enter(&EMLXS_MEMPUT_LOCK);
730
731 if (seg->fc_memsize == 0) {
732 mutex_exit(&EMLXS_MEMPUT_LOCK);
733 mutex_exit(&EMLXS_MEMGET_LOCK);
734 return;
735 }
736
737 /* Leave FC_MEMSEG_PUT_ENABLED set for now */
738 seg->fc_memflag &= ~FC_MEMSEG_GET_ENABLED;
739
740 /* Try to free all objects */
741 emlxs_mem_pool_free(hba, seg, seg->fc_numblks);
742
743 if (seg->fc_numblks) {
744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
745 "mem_pool_destroy: %s leak detected: "
746 "%d objects still allocated.",
747 seg->fc_label, seg->fc_numblks);
748 } else {
749 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
750 "mem_pool_destroy: %s destroyed.",
751 seg->fc_label);
752
753 /* Clear all */
754 bzero(seg, sizeof (MEMSEG));
755 }
756
757 mutex_exit(&EMLXS_MEMPUT_LOCK);
758 mutex_exit(&EMLXS_MEMGET_LOCK);
759
760 return;
761
762 } /* emlxs_mem_pool_destroy() */
763
764
765 extern void
emlxs_mem_pool_clean(emlxs_hba_t * hba,MEMSEG * seg)766 emlxs_mem_pool_clean(emlxs_hba_t *hba, MEMSEG *seg)
767 {
768 emlxs_port_t *port = &PPORT;
769 uint32_t clean_count;
770 uint32_t free_count;
771 uint32_t free_pad;
772
773 mutex_enter(&EMLXS_MEMGET_LOCK);
774 mutex_enter(&EMLXS_MEMPUT_LOCK);
775
776 if (!(seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
777 mutex_exit(&EMLXS_MEMPUT_LOCK);
778 mutex_exit(&EMLXS_MEMGET_LOCK);
779 return;
780 }
781
782 if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
783 goto done;
784 }
785
786 #ifdef EMLXS_POOL_DEBUG
787 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
788 "%s clean: n=%d s=%d f=%x l=%d,%d,%d "
789 "f=%d:%d",
790 seg->fc_label, seg->fc_numblks,
791 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
792 seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
793 seg->fc_low);
794 #endif /* EMLXS_POOL_DEBUG */
795
796 /* Calculatge current free count */
797 free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
798
799 /* Reset fc_low value to current free count */
800 clean_count = seg->fc_low;
801 seg->fc_low = free_count;
802
803 /* Return if pool is already at lo water mark */
804 if (seg->fc_numblks <= seg->fc_lo_water) {
805 goto done;
806 }
807
808 /* Return if there is nothing to clean */
809 if ((free_count == 0) ||
810 (clean_count <= 1)) {
811 goto done;
812 }
813
814 /* Calculate a 3 percent free pad count (1 being minimum) */
815 if (seg->fc_numblks > 66) {
816 free_pad = ((seg->fc_numblks * 3)/100);
817 } else {
818 free_pad = 1;
819 }
820
821 /* Return if fc_low is below pool free pad */
822 if (clean_count <= free_pad) {
823 goto done;
824 }
825
826 clean_count -= free_pad;
827
828 /* clean_count can't exceed minimum pool levels */
829 if (clean_count > (seg->fc_numblks - seg->fc_lo_water)) {
830 clean_count = (seg->fc_numblks - seg->fc_lo_water);
831 }
832
833 emlxs_mem_pool_free(hba, seg, clean_count);
834
835 done:
836 if (seg->fc_last != seg->fc_numblks) {
837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_detail_msg,
838 "%s update: n=%d->%d s=%d f=%x l=%d,%d,%d "
839 "f=%d:%d",
840 seg->fc_label, seg->fc_last, seg->fc_numblks,
841 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
842 seg->fc_hi_water, seg->fc_step, seg->fc_memget_cnt,
843 seg->fc_low);
844
845 seg->fc_last = seg->fc_numblks;
846 }
847
848 mutex_exit(&EMLXS_MEMPUT_LOCK);
849 mutex_exit(&EMLXS_MEMGET_LOCK);
850 return;
851
852 } /* emlxs_mem_pool_clean() */
853
854
855 extern void *
emlxs_mem_pool_get(emlxs_hba_t * hba,MEMSEG * seg)856 emlxs_mem_pool_get(emlxs_hba_t *hba, MEMSEG *seg)
857 {
858 emlxs_port_t *port = &PPORT;
859 void *bp = NULL;
860 MATCHMAP *mp;
861 uint32_t free_count;
862
863 mutex_enter(&EMLXS_MEMGET_LOCK);
864
865 /* Check if memory pool is GET enabled */
866 if (!(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
867 mutex_exit(&EMLXS_MEMGET_LOCK);
868 return (NULL);
869 }
870
871 /* If no entries on memget list, then check memput list */
872 if (!seg->fc_memget_ptr) {
873 mutex_enter(&EMLXS_MEMPUT_LOCK);
874 if (seg->fc_memput_ptr) {
875 /*
876 * Move list from memput to memget
877 */
878 seg->fc_memget_ptr = seg->fc_memput_ptr;
879 seg->fc_memget_end = seg->fc_memput_end;
880 seg->fc_memget_cnt = seg->fc_memput_cnt;
881 seg->fc_memput_ptr = NULL;
882 seg->fc_memput_end = NULL;
883 seg->fc_memput_cnt = 0;
884 }
885 mutex_exit(&EMLXS_MEMPUT_LOCK);
886 }
887
888 /* If no entries on memget list, then pool is empty */
889 /* Try to allocate more if pool is dynamic */
890 if (!seg->fc_memget_ptr &&
891 (seg->fc_memflag & FC_MEMSEG_DYNAMIC)) {
892 (void) emlxs_mem_pool_alloc(hba, seg, seg->fc_step);
893 seg->fc_low = 0;
894 }
895
896 /* If no entries on memget list, then pool is empty */
897 if (!seg->fc_memget_ptr) {
898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
899 "%s empty.", seg->fc_label);
900
901 mutex_exit(&EMLXS_MEMGET_LOCK);
902 return (NULL);
903 }
904
905 /* Remove an entry from the get list */
906 bp = seg->fc_memget_ptr;
907
908 if (seg->fc_memget_end == bp) {
909 seg->fc_memget_ptr = NULL;
910 seg->fc_memget_end = NULL;
911 seg->fc_memget_cnt = 0;
912
913 } else {
914 seg->fc_memget_ptr = *((uint8_t **)bp);
915 seg->fc_memget_cnt--;
916 }
917
918 /* Initialize buffer */
919 if (!(seg->fc_memflag & FC_MBUF_DMA)) {
920 bzero(bp, seg->fc_memsize);
921 } else {
922 mp = (MATCHMAP *)bp;
923 mp->fc_mptr = NULL;
924 mp->flag |= MAP_POOL_ALLOCATED;
925 }
926
927 /* Set fc_low if pool is dynamic */
928 if (seg->fc_memflag & FC_MEMSEG_DYNAMIC) {
929 free_count = (seg->fc_memget_cnt + seg->fc_memput_cnt);
930 if (free_count < seg->fc_low) {
931 seg->fc_low = free_count;
932 }
933 }
934
935 mutex_exit(&EMLXS_MEMGET_LOCK);
936
937 return (bp);
938
939 } /* emlxs_mem_pool_get() */
940
941
942 extern void
emlxs_mem_pool_put(emlxs_hba_t * hba,MEMSEG * seg,void * bp)943 emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, void *bp)
944 {
945 emlxs_port_t *port = &PPORT;
946 MATCHMAP *mp;
947
948 /* Free the pool object */
949 mutex_enter(&EMLXS_MEMPUT_LOCK);
950
951 /* Check if memory pool is PUT enabled */
952 if (!(seg->fc_memflag & FC_MEMSEG_PUT_ENABLED)) {
953 mutex_exit(&EMLXS_MEMPUT_LOCK);
954 return;
955 }
956
957 /* Check if buffer was just freed */
958 if ((seg->fc_memput_end == bp) || (seg->fc_memget_end == bp)) {
959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
960 "%s: Freeing free object: bp=%p", seg->fc_label, bp);
961
962 mutex_exit(&EMLXS_MEMPUT_LOCK);
963 return;
964 }
965
966 /* Validate DMA buffer */
967 if (seg->fc_memflag & FC_MBUF_DMA) {
968 mp = (MATCHMAP *)bp;
969
970 if (!(mp->flag & MAP_POOL_ALLOCATED) ||
971 (mp->segment != seg)) {
972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
973 "mem_pool_put: %s invalid: mp=%p " \
974 "tag=0x%x flag=%x", seg->fc_label,
975 mp, mp->tag, mp->flag);
976
977 EMLXS_STATE_CHANGE(hba, FC_ERROR);
978
979 mutex_exit(&EMLXS_MEMPUT_LOCK);
980
981 emlxs_thread_spawn(hba, emlxs_shutdown_thread,
982 NULL, NULL);
983
984 return;
985 }
986 }
987
988 /* Release buffer to the end of the memput list */
989 if (seg->fc_memput_end == NULL) {
990 seg->fc_memput_ptr = bp;
991 seg->fc_memput_cnt = 1;
992 } else {
993 *((void **)(seg->fc_memput_end)) = bp;
994 seg->fc_memput_cnt++;
995 }
996 seg->fc_memput_end = bp;
997 *((void **)(bp)) = NULL;
998
999 mutex_exit(&EMLXS_MEMPUT_LOCK);
1000
1001 /* This is for late PUT's after an initial */
1002 /* emlxs_mem_pool_destroy call */
1003 if ((seg->fc_memflag & FC_MEMSEG_PUT_ENABLED) &&
1004 !(seg->fc_memflag & FC_MEMSEG_GET_ENABLED)) {
1005 emlxs_mem_pool_destroy(hba, seg);
1006 }
1007
1008 return;
1009
1010 } /* emlxs_mem_pool_put() */
1011
1012
1013 extern MATCHMAP *
emlxs_mem_buf_alloc(emlxs_hba_t * hba,uint32_t size)1014 emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size)
1015 {
1016 emlxs_port_t *port = &PPORT;
1017 uint8_t *bp = NULL;
1018 MATCHMAP *mp = NULL;
1019 MBUF_INFO *buf_info;
1020 MBUF_INFO bufinfo;
1021
1022 buf_info = &bufinfo;
1023
1024 bzero(buf_info, sizeof (MBUF_INFO));
1025 buf_info->size = sizeof (MATCHMAP);
1026 buf_info->align = sizeof (void *);
1027
1028 (void) emlxs_mem_alloc(hba, buf_info);
1029 if (buf_info->virt == NULL) {
1030 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1031 "MEM_BUF_ALLOC buffer.");
1032
1033 return (NULL);
1034 }
1035
1036 mp = (MATCHMAP *)buf_info->virt;
1037 bzero(mp, sizeof (MATCHMAP));
1038
1039 bzero(buf_info, sizeof (MBUF_INFO));
1040 buf_info->size = size;
1041 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1042 buf_info->align = 32;
1043
1044 (void) emlxs_mem_alloc(hba, buf_info);
1045 if (buf_info->virt == NULL) {
1046
1047 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1048 "MEM_BUF_ALLOC DMA buffer.");
1049
1050 /* Free the mp object */
1051 bzero(buf_info, sizeof (MBUF_INFO));
1052 buf_info->size = sizeof (MATCHMAP);
1053 buf_info->virt = (void *)mp;
1054 emlxs_mem_free(hba, buf_info);
1055
1056 return (0);
1057 }
1058 bp = (uint8_t *)buf_info->virt;
1059 bzero(bp, buf_info->size);
1060
1061 mp->virt = buf_info->virt;
1062 mp->phys = buf_info->phys;
1063 mp->size = buf_info->size;
1064 mp->dma_handle = buf_info->dma_handle;
1065 mp->data_handle = buf_info->data_handle;
1066 mp->tag = MEM_BUF;
1067 mp->flag |= MAP_BUF_ALLOCATED;
1068
1069 return (mp);
1070
1071 } /* emlxs_mem_buf_alloc() */
1072
1073
1074 extern void
emlxs_mem_buf_free(emlxs_hba_t * hba,MATCHMAP * mp)1075 emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp)
1076 {
1077 MBUF_INFO bufinfo;
1078 MBUF_INFO *buf_info;
1079
1080 buf_info = &bufinfo;
1081
1082 if (!(mp->flag & MAP_BUF_ALLOCATED)) {
1083 return;
1084 }
1085
1086 bzero(buf_info, sizeof (MBUF_INFO));
1087 buf_info->size = mp->size;
1088 buf_info->virt = mp->virt;
1089 buf_info->phys = mp->phys;
1090 buf_info->dma_handle = mp->dma_handle;
1091 buf_info->data_handle = mp->data_handle;
1092 buf_info->flags = FC_MBUF_DMA;
1093 emlxs_mem_free(hba, buf_info);
1094
1095 bzero(buf_info, sizeof (MBUF_INFO));
1096 buf_info->size = sizeof (MATCHMAP);
1097 buf_info->virt = (void *)mp;
1098 emlxs_mem_free(hba, buf_info);
1099
1100 return;
1101
1102 } /* emlxs_mem_buf_free() */
1103
1104
1105 extern void *
emlxs_mem_get(emlxs_hba_t * hba,uint32_t seg_id)1106 emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id)
1107 {
1108 emlxs_port_t *port = &PPORT;
1109 void *bp;
1110 MAILBOXQ *mbq;
1111 IOCBQ *iocbq;
1112 NODELIST *node;
1113 MEMSEG *seg;
1114
1115 if (seg_id >= FC_MAX_SEG) {
1116
1117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1118 "mem_get: Invalid segment id = %d",
1119 seg_id);
1120
1121 return (NULL);
1122 }
1123 seg = &hba->memseg[seg_id];
1124
1125 /* Alloc a buffer from the pool */
1126 bp = emlxs_mem_pool_get(hba, seg);
1127
1128 if (bp) {
1129 switch (seg_id) {
1130 case MEM_MBOX:
1131 mbq = (MAILBOXQ *)bp;
1132 mbq->flag |= MBQ_POOL_ALLOCATED;
1133 break;
1134
1135 case MEM_IOCB:
1136 iocbq = (IOCBQ *)bp;
1137 iocbq->flag |= IOCB_POOL_ALLOCATED;
1138 break;
1139
1140 case MEM_NLP:
1141 node = (NODELIST *)bp;
1142 node->flag |= NODE_POOL_ALLOCATED;
1143 break;
1144 }
1145 }
1146
1147 return (bp);
1148
1149 } /* emlxs_mem_get() */
1150
1151
1152 extern void
emlxs_mem_put(emlxs_hba_t * hba,uint32_t seg_id,void * bp)1153 emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, void *bp)
1154 {
1155 emlxs_port_t *port = &PPORT;
1156 MAILBOXQ *mbq;
1157 IOCBQ *iocbq;
1158 NODELIST *node;
1159 MEMSEG *seg;
1160 MATCHMAP *mp;
1161
1162 if (seg_id >= FC_MAX_SEG) {
1163
1164 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1165 "mem_put: Invalid segment id = %d: bp=%p",
1166 seg_id, bp);
1167
1168 return;
1169 }
1170 seg = &hba->memseg[seg_id];
1171
1172 /* Verify buffer */
1173 switch (seg_id) {
1174 case MEM_MBOX:
1175 mbq = (MAILBOXQ *)bp;
1176
1177 if (!(mbq->flag & MBQ_POOL_ALLOCATED)) {
1178 return;
1179 }
1180 break;
1181
1182 case MEM_IOCB:
1183 iocbq = (IOCBQ *)bp;
1184
1185 if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) {
1186 return;
1187 }
1188
1189 /* Any IOCBQ with a packet attached did not come */
1190 /* from our pool */
1191 if (iocbq->sbp) {
1192 return;
1193 }
1194 break;
1195
1196 case MEM_NLP:
1197 node = (NODELIST *)bp;
1198
1199 if (!(node->flag & NODE_POOL_ALLOCATED)) {
1200 return;
1201 }
1202 break;
1203
1204 default:
1205 mp = (MATCHMAP *)bp;
1206
1207 if (mp->flag & MAP_BUF_ALLOCATED) {
1208 emlxs_mem_buf_free(hba, mp);
1209 return;
1210 }
1211
1212 if (mp->flag & MAP_TABLE_ALLOCATED) {
1213 return;
1214 }
1215
1216 if (!(mp->flag & MAP_POOL_ALLOCATED)) {
1217 return;
1218 }
1219 break;
1220 }
1221
1222 /* Free a buffer to the pool */
1223 emlxs_mem_pool_put(hba, seg, bp);
1224
1225 return;
1226
1227 } /* emlxs_mem_put() */
1228
1229
1230 /*
1231 * Look up the virtual address given a mapped address
1232 */
1233 /* SLI3 */
1234 extern MATCHMAP *
emlxs_mem_get_vaddr(emlxs_hba_t * hba,RING * rp,uint64_t mapbp)1235 emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp)
1236 {
1237 emlxs_port_t *port = &PPORT;
1238 MATCHMAP *prev;
1239 MATCHMAP *mp;
1240
1241 if (rp->ringno == hba->channel_els) {
1242 mp = (MATCHMAP *)rp->fc_mpoff;
1243 prev = 0;
1244
1245 while (mp) {
1246 if (mp->phys == mapbp) {
1247 if (prev == 0) {
1248 rp->fc_mpoff = mp->fc_mptr;
1249 } else {
1250 prev->fc_mptr = mp->fc_mptr;
1251 }
1252
1253 if (rp->fc_mpon == mp) {
1254 rp->fc_mpon = (void *)prev;
1255 }
1256
1257 mp->fc_mptr = NULL;
1258
1259 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1260 DDI_DMA_SYNC_FORKERNEL);
1261
1262 HBASTATS.ElsUbPosted--;
1263
1264 return (mp);
1265 }
1266
1267 prev = mp;
1268 mp = (MATCHMAP *)mp->fc_mptr;
1269 }
1270
1271 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1272 "ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1273 mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1274
1275 } else if (rp->ringno == hba->channel_ct) {
1276
1277 mp = (MATCHMAP *)rp->fc_mpoff;
1278 prev = 0;
1279
1280 while (mp) {
1281 if (mp->phys == mapbp) {
1282 if (prev == 0) {
1283 rp->fc_mpoff = mp->fc_mptr;
1284 } else {
1285 prev->fc_mptr = mp->fc_mptr;
1286 }
1287
1288 if (rp->fc_mpon == mp) {
1289 rp->fc_mpon = (void *)prev;
1290 }
1291
1292 mp->fc_mptr = NULL;
1293
1294 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1295 DDI_DMA_SYNC_FORKERNEL);
1296
1297 HBASTATS.CtUbPosted--;
1298
1299 return (mp);
1300 }
1301
1302 prev = mp;
1303 mp = (MATCHMAP *)mp->fc_mptr;
1304 }
1305
1306 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1307 "CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1308 mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1309
1310 } else if (rp->ringno == hba->channel_ip) {
1311
1312 mp = (MATCHMAP *)rp->fc_mpoff;
1313 prev = 0;
1314
1315 while (mp) {
1316 if (mp->phys == mapbp) {
1317 if (prev == 0) {
1318 rp->fc_mpoff = mp->fc_mptr;
1319 } else {
1320 prev->fc_mptr = mp->fc_mptr;
1321 }
1322
1323 if (rp->fc_mpon == mp) {
1324 rp->fc_mpon = (void *)prev;
1325 }
1326
1327 mp->fc_mptr = NULL;
1328
1329 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1330 DDI_DMA_SYNC_FORKERNEL);
1331
1332 HBASTATS.IpUbPosted--;
1333
1334 return (mp);
1335 }
1336
1337 prev = mp;
1338 mp = (MATCHMAP *)mp->fc_mptr;
1339 }
1340
1341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1342 "IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1343 mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1344
1345 #ifdef SFCT_SUPPORT
1346 } else if (rp->ringno == hba->CHANNEL_FCT) {
1347 mp = (MATCHMAP *)rp->fc_mpoff;
1348 prev = 0;
1349
1350 while (mp) {
1351 if (mp->phys == mapbp) {
1352 if (prev == 0) {
1353 rp->fc_mpoff = mp->fc_mptr;
1354 } else {
1355 prev->fc_mptr = mp->fc_mptr;
1356 }
1357
1358 if (rp->fc_mpon == mp) {
1359 rp->fc_mpon = (void *)prev;
1360 }
1361
1362 mp->fc_mptr = NULL;
1363
1364 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
1365 DDI_DMA_SYNC_FORKERNEL);
1366
1367 HBASTATS.FctUbPosted--;
1368
1369 return (mp);
1370 }
1371
1372 prev = mp;
1373 mp = (MATCHMAP *)mp->fc_mptr;
1374 }
1375
1376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1377 "FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1378 mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1379
1380 #endif /* SFCT_SUPPORT */
1381 }
1382
1383 return (0);
1384
1385 } /* emlxs_mem_get_vaddr() */
1386
1387
1388 /*
1389 * Given a virtual address bp, generate the physical mapped address and
1390 * place it where addr points to. Save the address pair for lookup later.
1391 */
1392 /* SLI3 */
1393 extern void
emlxs_mem_map_vaddr(emlxs_hba_t * hba,RING * rp,MATCHMAP * mp,uint32_t * haddr,uint32_t * laddr)1394 emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp,
1395 uint32_t *haddr, uint32_t *laddr)
1396 {
1397 if (rp->ringno == hba->channel_els) {
1398 /*
1399 * Update slot fc_mpon points to then bump it
1400 * fc_mpoff is pointer head of the list.
1401 * fc_mpon is pointer tail of the list.
1402 */
1403 mp->fc_mptr = NULL;
1404 if (rp->fc_mpoff == 0) {
1405 rp->fc_mpoff = (void *)mp;
1406 rp->fc_mpon = (void *)mp;
1407 } else {
1408 ((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1409 (void *)mp;
1410 rp->fc_mpon = (void *)mp;
1411 }
1412
1413 if (hba->flag & FC_SLIM2_MODE) {
1414
1415 /* return mapped address */
1416 *haddr = PADDR_HI(mp->phys);
1417 /* return mapped address */
1418 *laddr = PADDR_LO(mp->phys);
1419 } else {
1420 /* return mapped address */
1421 *laddr = PADDR_LO(mp->phys);
1422 }
1423
1424 HBASTATS.ElsUbPosted++;
1425
1426 } else if (rp->ringno == hba->channel_ct) {
1427 /*
1428 * Update slot fc_mpon points to then bump it
1429 * fc_mpoff is pointer head of the list.
1430 * fc_mpon is pointer tail of the list.
1431 */
1432 mp->fc_mptr = NULL;
1433 if (rp->fc_mpoff == 0) {
1434 rp->fc_mpoff = (void *)mp;
1435 rp->fc_mpon = (void *)mp;
1436 } else {
1437 ((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1438 (void *)mp;
1439 rp->fc_mpon = (void *)mp;
1440 }
1441
1442 if (hba->flag & FC_SLIM2_MODE) {
1443 /* return mapped address */
1444 *haddr = PADDR_HI(mp->phys);
1445 /* return mapped address */
1446 *laddr = PADDR_LO(mp->phys);
1447 } else {
1448 /* return mapped address */
1449 *laddr = PADDR_LO(mp->phys);
1450 }
1451
1452 HBASTATS.CtUbPosted++;
1453
1454
1455 } else if (rp->ringno == hba->channel_ip) {
1456 /*
1457 * Update slot fc_mpon points to then bump it
1458 * fc_mpoff is pointer head of the list.
1459 * fc_mpon is pointer tail of the list.
1460 */
1461 mp->fc_mptr = NULL;
1462 if (rp->fc_mpoff == 0) {
1463 rp->fc_mpoff = (void *)mp;
1464 rp->fc_mpon = (void *)mp;
1465 } else {
1466 ((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1467 (void *)mp;
1468 rp->fc_mpon = (void *)mp;
1469 }
1470
1471 if (hba->flag & FC_SLIM2_MODE) {
1472 /* return mapped address */
1473 *haddr = PADDR_HI(mp->phys);
1474 *laddr = PADDR_LO(mp->phys);
1475 } else {
1476 *laddr = PADDR_LO(mp->phys);
1477 }
1478
1479 HBASTATS.IpUbPosted++;
1480
1481
1482 #ifdef SFCT_SUPPORT
1483 } else if (rp->ringno == hba->CHANNEL_FCT) {
1484 /*
1485 * Update slot fc_mpon points to then bump it
1486 * fc_mpoff is pointer head of the list.
1487 * fc_mpon is pointer tail of the list.
1488 */
1489 mp->fc_mptr = NULL;
1490 if (rp->fc_mpoff == 0) {
1491 rp->fc_mpoff = (void *)mp;
1492 rp->fc_mpon = (void *)mp;
1493 } else {
1494 ((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1495 (void *)mp;
1496 rp->fc_mpon = (void *)mp;
1497 }
1498
1499 if (hba->flag & FC_SLIM2_MODE) {
1500 /* return mapped address */
1501 *haddr = PADDR_HI(mp->phys);
1502 /* return mapped address */
1503 *laddr = PADDR_LO(mp->phys);
1504 } else {
1505 /* return mapped address */
1506 *laddr = PADDR_LO(mp->phys);
1507 }
1508
1509 HBASTATS.FctUbPosted++;
1510
1511 #endif /* SFCT_SUPPORT */
1512 }
1513 } /* emlxs_mem_map_vaddr() */
1514
1515
1516 /* SLI3 */
1517 uint32_t
emlxs_hbq_alloc(emlxs_hba_t * hba,uint32_t hbq_id)1518 emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id)
1519 {
1520 emlxs_port_t *port = &PPORT;
1521 HBQ_INIT_t *hbq;
1522 MBUF_INFO *buf_info;
1523 MBUF_INFO bufinfo;
1524
1525 hbq = &hba->sli.sli3.hbq_table[hbq_id];
1526
1527 if (hbq->HBQ_host_buf.virt == 0) {
1528 buf_info = &bufinfo;
1529
1530 /* Get the system's page size in a DDI-compliant way. */
1531 bzero(buf_info, sizeof (MBUF_INFO));
1532 buf_info->size = hbq->HBQ_numEntries * sizeof (HBQE_t);
1533 buf_info->flags = FC_MBUF_DMA;
1534 buf_info->align = 4096;
1535
1536 (void) emlxs_mem_alloc(hba, buf_info);
1537
1538 if (buf_info->virt == NULL) {
1539 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
1540 "Unable to alloc HBQ.");
1541 return (ENOMEM);
1542 }
1543
1544 hbq->HBQ_host_buf.virt = buf_info->virt;
1545 hbq->HBQ_host_buf.phys = buf_info->phys;
1546 hbq->HBQ_host_buf.data_handle = buf_info->data_handle;
1547 hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle;
1548 hbq->HBQ_host_buf.size = buf_info->size;
1549 hbq->HBQ_host_buf.tag = hbq_id;
1550
1551 bzero((char *)hbq->HBQ_host_buf.virt, buf_info->size);
1552 }
1553
1554 return (0);
1555
1556 } /* emlxs_hbq_alloc() */
1557