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