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