1 /*- 2 * Copyright (c) 2011 Semihalf. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/kernel.h> 30 #include <sys/malloc.h> 31 #include <sys/bus.h> 32 #include <sys/interrupt.h> 33 #include <sys/lock.h> 34 #include <sys/mutex.h> 35 #include <sys/proc.h> 36 #include <sys/queue.h> 37 #include <sys/rman.h> 38 #include <sys/sched.h> 39 #include <sys/smp.h> 40 41 #include <vm/vm.h> 42 #include <vm/vm_param.h> 43 #include <vm/vm_page.h> 44 45 #include <machine/cpufunc.h> 46 #include <machine/intr_machdep.h> 47 #include <machine/pmap.h> 48 #include <machine/stdarg.h> 49 50 #include <dev/dpaa/bman.h> 51 #include <dev/dpaa/qman.h> 52 #include <dev/dpaa/portals.h> 53 54 #include "error_ext.h" 55 #include "std_ext.h" 56 #include "list_ext.h" 57 #include "mm_ext.h" 58 59 /* Configuration */ 60 61 /* Define the number of dTSEC ports active in system */ 62 #define MALLOCSMART_DTSEC_IN_USE 4 63 64 /* 65 * Calculate malloc's pool size for dTSEC's buffers. 66 * We reserve 1MB pool for each dTSEC port. 67 */ 68 #define MALLOCSMART_POOL_SIZE \ 69 (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024) 70 71 #define MALLOCSMART_SLICE_SIZE (PAGE_SIZE / 2) /* 2kB */ 72 73 /* Defines */ 74 #define MALLOCSMART_SIZE_TO_SLICE(x) \ 75 (((x) + MALLOCSMART_SLICE_SIZE - 1) / MALLOCSMART_SLICE_SIZE) 76 #define MALLOCSMART_SLICES \ 77 MALLOCSMART_SIZE_TO_SLICE(MALLOCSMART_POOL_SIZE) 78 79 /* Malloc Pool for NetCommSW */ 80 MALLOC_DEFINE(M_NETCOMMSW, "NetCommSW", "NetCommSW software stack"); 81 MALLOC_DEFINE(M_NETCOMMSW_MT, "NetCommSWTrack", 82 "NetCommSW software allocation tracker"); 83 84 /* MallocSmart data structures */ 85 static void *XX_MallocSmartPool; 86 static int XX_MallocSmartMap[MALLOCSMART_SLICES]; 87 88 static struct mtx XX_MallocSmartLock; 89 static struct mtx XX_MallocTrackLock; 90 MTX_SYSINIT(XX_MallocSmartLockInit, &XX_MallocSmartLock, 91 "NetCommSW MallocSmart Lock", MTX_DEF); 92 MTX_SYSINIT(XX_MallocTrackLockInit, &XX_MallocTrackLock, 93 "NetCommSW MallocTrack Lock", MTX_DEF); 94 95 /* Interrupt info */ 96 #define XX_INTR_FLAG_PREALLOCATED (1 << 0) 97 #define XX_INTR_FLAG_BOUND (1 << 1) 98 #define XX_INTR_FLAG_FMAN_FIX (1 << 2) 99 100 struct XX_IntrInfo { 101 driver_intr_t *handler; 102 void *arg; 103 int cpu; 104 int flags; 105 void *cookie; 106 }; 107 108 static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS]; 109 /* Portal type identifiers */ 110 enum XX_PortalIdent{ 111 BM_PORTAL = 0, 112 QM_PORTAL, 113 }; 114 /* Structure to store portals' properties */ 115 struct XX_PortalInfo { 116 vm_paddr_t portal_ce_pa[2][MAXCPU]; 117 vm_paddr_t portal_ci_pa[2][MAXCPU]; 118 uint32_t portal_ce_size[2][MAXCPU]; 119 uint32_t portal_ci_size[2][MAXCPU]; 120 vm_offset_t portal_ce_va[2]; 121 vm_offset_t portal_ci_va[2]; 122 uint32_t portal_intr[2][MAXCPU]; 123 }; 124 125 static struct XX_PortalInfo XX_PInfo; 126 127 /* The lower 9 bits, through emprical testing, tend to be 0. */ 128 #define XX_MALLOC_TRACK_SHIFT 9 129 130 typedef struct XX_MallocTrackStruct { 131 LIST_ENTRY(XX_MallocTrackStruct) entries; 132 physAddress_t pa; 133 void *va; 134 } XX_MallocTrackStruct; 135 136 LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker; 137 u_long XX_MallocHashMask; 138 static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa); 139 140 void 141 XX_Exit(int status) 142 { 143 144 panic("NetCommSW: Exit called with status %i", status); 145 } 146 147 void 148 XX_Print(char *str, ...) 149 { 150 va_list ap; 151 152 va_start(ap, str); 153 vprintf(str, ap); 154 va_end(ap); 155 } 156 157 void * 158 XX_Malloc(uint32_t size) 159 { 160 void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT)); 161 162 return (p); 163 } 164 165 static int 166 XX_MallocSmartMapCheck(unsigned int start, unsigned int slices) 167 { 168 unsigned int i; 169 170 mtx_assert(&XX_MallocSmartLock, MA_OWNED); 171 for (i = start; i < start + slices; i++) 172 if (XX_MallocSmartMap[i]) 173 return (FALSE); 174 return (TRUE); 175 } 176 177 static void 178 XX_MallocSmartMapSet(unsigned int start, unsigned int slices) 179 { 180 unsigned int i; 181 182 mtx_assert(&XX_MallocSmartLock, MA_OWNED); 183 184 for (i = start; i < start + slices; i++) 185 XX_MallocSmartMap[i] = ((i == start) ? slices : -1); 186 } 187 188 static void 189 XX_MallocSmartMapClear(unsigned int start, unsigned int slices) 190 { 191 unsigned int i; 192 193 mtx_assert(&XX_MallocSmartLock, MA_OWNED); 194 195 for (i = start; i < start + slices; i++) 196 XX_MallocSmartMap[i] = 0; 197 } 198 199 int 200 XX_MallocSmartInit(void) 201 { 202 int error; 203 204 error = E_OK; 205 mtx_lock(&XX_MallocSmartLock); 206 207 if (XX_MallocSmartPool) 208 goto out; 209 210 /* Allocate MallocSmart pool */ 211 XX_MallocSmartPool = contigmalloc(MALLOCSMART_POOL_SIZE, M_NETCOMMSW, 212 M_NOWAIT, 0, 0xFFFFFFFFFull, MALLOCSMART_POOL_SIZE, 0); 213 if (!XX_MallocSmartPool) { 214 error = E_NO_MEMORY; 215 goto out; 216 } 217 218 out: 219 mtx_unlock(&XX_MallocSmartLock); 220 return (error); 221 } 222 223 void * 224 XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) 225 { 226 unsigned int i; 227 vm_offset_t addr; 228 229 addr = 0; 230 231 /* Convert alignment and size to number of slices */ 232 alignment = MALLOCSMART_SIZE_TO_SLICE(alignment); 233 size = MALLOCSMART_SIZE_TO_SLICE(size); 234 235 /* Lock resources */ 236 mtx_lock(&XX_MallocSmartLock); 237 238 /* Allocate region */ 239 for (i = 0; i + size <= MALLOCSMART_SLICES; i += alignment) { 240 if (XX_MallocSmartMapCheck(i, size)) { 241 XX_MallocSmartMapSet(i, size); 242 addr = (vm_offset_t)XX_MallocSmartPool + 243 (i * MALLOCSMART_SLICE_SIZE); 244 break; 245 } 246 } 247 248 /* Unlock resources */ 249 mtx_unlock(&XX_MallocSmartLock); 250 251 return ((void *)addr); 252 } 253 254 void 255 XX_FreeSmart(void *p) 256 { 257 unsigned int start, slices; 258 259 /* Calculate first slice of region */ 260 start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) - 261 (vm_offset_t)XX_MallocSmartPool); 262 263 /* Lock resources */ 264 mtx_lock(&XX_MallocSmartLock); 265 266 KASSERT(XX_MallocSmartMap[start] > 0, 267 ("XX_FreeSmart: Double or mid-block free!\n")); 268 269 XX_UntrackAddress(p); 270 /* Free region */ 271 slices = XX_MallocSmartMap[start]; 272 XX_MallocSmartMapClear(start, slices); 273 274 /* Unlock resources */ 275 mtx_unlock(&XX_MallocSmartLock); 276 } 277 278 void 279 XX_Free(void *p) 280 { 281 282 if (p != NULL) 283 XX_UntrackAddress(p); 284 free(p, M_NETCOMMSW); 285 } 286 287 uint32_t 288 XX_DisableAllIntr(void) 289 { 290 291 return (intr_disable()); 292 } 293 294 void 295 XX_RestoreAllIntr(uint32_t flags) 296 { 297 298 intr_restore(flags); 299 } 300 301 t_Error 302 XX_Call(uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags ) 303 { 304 /* Not referenced */ 305 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 306 return (E_OK); 307 } 308 309 static bool 310 XX_IsPortalIntr(int irq) 311 { 312 int cpu, type; 313 /* Check interrupt numbers of all available portals */ 314 for (cpu = 0, type = 0; XX_PInfo.portal_intr[type][cpu] != 0; cpu++) { 315 if (irq == XX_PInfo.portal_intr[type][cpu]) { 316 /* Found it! */ 317 return (1); 318 } 319 if (XX_PInfo.portal_intr[type][cpu + 1] == 0) { 320 type++; 321 cpu = 0; 322 } 323 } 324 325 return (0); 326 } 327 328 void 329 XX_FmanFixIntr(int irq) 330 { 331 332 XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX; 333 } 334 335 static bool 336 XX_FmanNeedsIntrFix(int irq) 337 { 338 339 if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX) 340 return (1); 341 342 return (0); 343 } 344 345 static void 346 XX_Dispatch(void *arg) 347 { 348 struct XX_IntrInfo *info; 349 350 info = arg; 351 352 /* Bind this thread to proper CPU when SMP has been already started. */ 353 if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started && 354 info->cpu >= 0) { 355 thread_lock(curthread); 356 sched_bind(curthread, info->cpu); 357 thread_unlock(curthread); 358 359 info->flags |= XX_INTR_FLAG_BOUND; 360 } 361 362 if (info->handler == NULL) { 363 printf("%s(): IRQ handler is NULL!\n", __func__); 364 return; 365 } 366 367 info->handler(info->arg); 368 } 369 370 t_Error 371 XX_PreallocAndBindIntr(int irq, unsigned int cpu) 372 { 373 struct resource *r; 374 unsigned int inum; 375 t_Error error; 376 377 r = (struct resource *)irq; 378 inum = rman_get_start(r); 379 380 error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]); 381 if (error != 0) 382 return (error); 383 384 XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED; 385 XX_IntrInfo[inum].cpu = cpu; 386 387 return (E_OK); 388 } 389 390 t_Error 391 XX_DeallocIntr(int irq) 392 { 393 struct resource *r; 394 unsigned int inum; 395 396 r = (struct resource *)irq; 397 inum = rman_get_start(r); 398 399 if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0) 400 return (E_INVALID_STATE); 401 402 XX_IntrInfo[inum].flags = 0; 403 return (XX_FreeIntr(irq)); 404 } 405 406 t_Error 407 XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) 408 { 409 struct device *dev; 410 struct resource *r; 411 unsigned int flags; 412 int err; 413 414 r = (struct resource *)irq; 415 dev = rman_get_device(r); 416 irq = rman_get_start(r); 417 418 /* Handle preallocated interrupts */ 419 if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) { 420 if (XX_IntrInfo[irq].handler != NULL) 421 return (E_BUSY); 422 423 XX_IntrInfo[irq].handler = f_Isr; 424 XX_IntrInfo[irq].arg = handle; 425 426 return (E_OK); 427 } 428 429 flags = INTR_TYPE_NET | INTR_MPSAFE; 430 431 /* BMAN/QMAN Portal interrupts must be exlusive */ 432 if (XX_IsPortalIntr(irq)) 433 flags |= INTR_EXCL; 434 435 err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle, 436 &XX_IntrInfo[irq].cookie); 437 if (err) 438 goto finish; 439 440 /* 441 * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each 442 * interrupt to all CPUs. Race between an interrupt assertion and 443 * masking may occur and interrupt handler may be called multiple times 444 * per one interrupt. FMan doesn't support such a situation. Workaround 445 * is to bind FMan interrupt to one CPU0 only. 446 */ 447 #ifdef SMP 448 if (XX_FmanNeedsIntrFix(irq)) 449 err = powerpc_bind_intr(irq, 0); 450 #endif 451 finish: 452 return (err); 453 } 454 455 t_Error 456 XX_FreeIntr(int irq) 457 { 458 struct device *dev; 459 struct resource *r; 460 461 r = (struct resource *)irq; 462 dev = rman_get_device(r); 463 irq = rman_get_start(r); 464 465 /* Handle preallocated interrupts */ 466 if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) { 467 if (XX_IntrInfo[irq].handler == NULL) 468 return (E_INVALID_STATE); 469 470 XX_IntrInfo[irq].handler = NULL; 471 XX_IntrInfo[irq].arg = NULL; 472 473 return (E_OK); 474 } 475 476 return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie)); 477 } 478 479 t_Error 480 XX_EnableIntr(int irq) 481 { 482 struct resource *r; 483 484 r = (struct resource *)irq; 485 irq = rman_get_start(r); 486 487 powerpc_intr_unmask(irq); 488 489 return (E_OK); 490 } 491 492 t_Error 493 XX_DisableIntr(int irq) 494 { 495 struct resource *r; 496 497 r = (struct resource *)irq; 498 irq = rman_get_start(r); 499 500 powerpc_intr_mask(irq); 501 502 return (E_OK); 503 } 504 505 t_TaskletHandle 506 XX_InitTasklet (void (*routine)(void *), void *data) 507 { 508 /* Not referenced */ 509 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 510 return (NULL); 511 } 512 513 514 void 515 XX_FreeTasklet (t_TaskletHandle h_Tasklet) 516 { 517 /* Not referenced */ 518 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 519 } 520 521 int 522 XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate) 523 { 524 /* Not referenced */ 525 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 526 return (0); 527 } 528 529 void 530 XX_FlushScheduledTasks(void) 531 { 532 /* Not referenced */ 533 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 534 } 535 536 int 537 XX_TaskletIsQueued(t_TaskletHandle h_Tasklet) 538 { 539 /* Not referenced */ 540 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 541 return (0); 542 } 543 544 void 545 XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data) 546 { 547 /* Not referenced */ 548 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 549 } 550 551 t_Handle 552 XX_GetTaskletData(t_TaskletHandle h_Tasklet) 553 { 554 /* Not referenced */ 555 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 556 return (NULL); 557 } 558 559 t_Handle 560 XX_InitSpinlock(void) 561 { 562 struct mtx *m; 563 564 m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT | M_ZERO); 565 if (!m) 566 return (0); 567 568 mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK); 569 570 return (m); 571 } 572 573 void 574 XX_FreeSpinlock(t_Handle h_Spinlock) 575 { 576 struct mtx *m; 577 578 m = h_Spinlock; 579 580 mtx_destroy(m); 581 free(m, M_NETCOMMSW); 582 } 583 584 void 585 XX_LockSpinlock(t_Handle h_Spinlock) 586 { 587 struct mtx *m; 588 589 m = h_Spinlock; 590 mtx_lock(m); 591 } 592 593 void 594 XX_UnlockSpinlock(t_Handle h_Spinlock) 595 { 596 struct mtx *m; 597 598 m = h_Spinlock; 599 mtx_unlock(m); 600 } 601 602 uint32_t 603 XX_LockIntrSpinlock(t_Handle h_Spinlock) 604 { 605 606 XX_LockSpinlock(h_Spinlock); 607 return (0); 608 } 609 610 void 611 XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags) 612 { 613 614 XX_UnlockSpinlock(h_Spinlock); 615 } 616 617 uint32_t 618 XX_CurrentTime(void) 619 { 620 /* Not referenced */ 621 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 622 return (0); 623 } 624 625 626 t_Handle 627 XX_CreateTimer(void) 628 { 629 /* Not referenced */ 630 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 631 return (NULL); 632 } 633 634 void 635 XX_FreeTimer(t_Handle h_Timer) 636 { 637 /* Not referenced */ 638 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 639 } 640 641 void 642 XX_StartTimer(t_Handle h_Timer, 643 uint32_t msecs, 644 bool periodic, 645 void (*f_TimerExpired)(t_Handle), 646 t_Handle h_Arg) 647 { 648 /* Not referenced */ 649 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 650 } 651 652 uint32_t 653 XX_GetExpirationTime(t_Handle h_Timer) 654 { 655 /* Not referenced */ 656 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 657 return (0); 658 } 659 660 void 661 XX_StopTimer(t_Handle h_Timer) 662 { 663 /* Not referenced */ 664 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 665 } 666 667 void 668 XX_ModTimer(t_Handle h_Timer, uint32_t msecs) 669 { 670 /* Not referenced */ 671 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 672 } 673 674 int 675 XX_TimerIsActive(t_Handle h_Timer) 676 { 677 /* Not referenced */ 678 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 679 return (0); 680 } 681 682 uint32_t 683 XX_Sleep(uint32_t msecs) 684 { 685 686 XX_UDelay(1000 * msecs); 687 return (0); 688 } 689 690 void 691 XX_UDelay(uint32_t usecs) 692 { 693 DELAY(usecs); 694 } 695 696 t_Error 697 XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], 698 t_IpcMsgHandler *f_MsgHandler, t_Handle h_Module, uint32_t replyLength) 699 { 700 701 /* 702 * This function returns fake E_OK status and does nothing 703 * as NetCommSW IPC is not used by FreeBSD drivers. 704 */ 705 return (E_OK); 706 } 707 708 t_Error 709 XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]) 710 { 711 /* 712 * This function returns fake E_OK status and does nothing 713 * as NetCommSW IPC is not used by FreeBSD drivers. 714 */ 715 return (E_OK); 716 } 717 718 719 t_Error 720 XX_IpcSendMessage(t_Handle h_Session, 721 uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, 722 uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg) 723 { 724 725 /* Should not be called */ 726 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 727 return (E_OK); 728 } 729 730 t_Handle 731 XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], 732 char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]) 733 { 734 735 /* Should not be called */ 736 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 737 return (E_OK); 738 } 739 740 t_Error 741 XX_IpcFreeSession(t_Handle h_Session) 742 { 743 744 /* Should not be called */ 745 printf("NetCommSW: Unimplemented function %s() called!\n", __func__); 746 return (E_OK); 747 } 748 749 extern void db_trace_self(void); 750 physAddress_t 751 XX_VirtToPhys(void *addr) 752 { 753 vm_paddr_t paddr; 754 int cpu; 755 756 cpu = PCPU_GET(cpuid); 757 758 /* Handle NULL address */ 759 if (addr == NULL) 760 return (-1); 761 762 /* Handle BMAN mappings */ 763 if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) && 764 ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] + 765 XX_PInfo.portal_ce_size[BM_PORTAL][cpu])) 766 return (XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] + 767 (vm_offset_t)addr - XX_PInfo.portal_ce_va[BM_PORTAL]); 768 769 if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[BM_PORTAL]) && 770 ((vm_offset_t)addr < XX_PInfo.portal_ci_va[BM_PORTAL] + 771 XX_PInfo.portal_ci_size[BM_PORTAL][cpu])) 772 return (XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] + 773 (vm_offset_t)addr - XX_PInfo.portal_ci_va[BM_PORTAL]); 774 775 /* Handle QMAN mappings */ 776 if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[QM_PORTAL]) && 777 ((vm_offset_t)addr < XX_PInfo.portal_ce_va[QM_PORTAL] + 778 XX_PInfo.portal_ce_size[QM_PORTAL][cpu])) 779 return (XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] + 780 (vm_offset_t)addr - XX_PInfo.portal_ce_va[QM_PORTAL]); 781 782 if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[QM_PORTAL]) && 783 ((vm_offset_t)addr < XX_PInfo.portal_ci_va[QM_PORTAL] + 784 XX_PInfo.portal_ci_size[QM_PORTAL][cpu])) 785 return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] + 786 (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]); 787 788 paddr = pmap_kextract((vm_offset_t)addr); 789 if (!paddr) 790 printf("NetCommSW: " 791 "Unable to translate virtual address 0x%08X!\n", addr); 792 else 793 XX_TrackAddress(addr); 794 795 return (paddr); 796 } 797 798 void * 799 XX_PhysToVirt(physAddress_t addr) 800 { 801 XX_MallocTrackStruct *ts; 802 int cpu; 803 804 cpu = PCPU_GET(cpuid); 805 806 /* Handle BMAN mappings */ 807 if ((addr >= XX_PInfo.portal_ce_pa[BM_PORTAL][cpu]) && 808 (addr < XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] + 809 XX_PInfo.portal_ce_size[BM_PORTAL][cpu])) 810 return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] + 811 (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]))); 812 813 if ((addr >= XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]) && 814 (addr < XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] + 815 XX_PInfo.portal_ci_size[BM_PORTAL][cpu])) 816 return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] + 817 (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]))); 818 819 /* Handle QMAN mappings */ 820 if ((addr >= XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]) && 821 (addr < XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] + 822 XX_PInfo.portal_ce_size[QM_PORTAL][cpu])) 823 return ((void *)(XX_PInfo.portal_ce_va[QM_PORTAL] + 824 (vm_offset_t)(addr - XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]))); 825 826 if ((addr >= XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]) && 827 (addr < XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] + 828 XX_PInfo.portal_ci_size[QM_PORTAL][cpu])) 829 return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] + 830 (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]))); 831 832 mtx_lock(&XX_MallocTrackLock); 833 ts = XX_FindTracker(addr); 834 mtx_unlock(&XX_MallocTrackLock); 835 836 if (ts != NULL) 837 return ts->va; 838 839 printf("NetCommSW: " 840 "Unable to translate physical address 0x%08llX!\n", addr); 841 842 return (NULL); 843 } 844 845 void 846 XX_PortalSetInfo(device_t dev) 847 { 848 char *dev_name; 849 struct dpaa_portals_softc *sc; 850 int i, type, len; 851 852 dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK | 853 M_ZERO); 854 855 len = strlen("bman-portals"); 856 857 strncpy(dev_name, device_get_name(dev), len); 858 859 if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name, 860 "qman-portals", len)) 861 goto end; 862 863 if (strncmp(dev_name, "bman-portals", len) == 0) 864 type = BM_PORTAL; 865 else 866 type = QM_PORTAL; 867 868 sc = device_get_softc(dev); 869 870 for (i = 0; sc->sc_dp[i].dp_ce_pa != 0; i++) { 871 XX_PInfo.portal_ce_pa[type][i] = sc->sc_dp[i].dp_ce_pa; 872 XX_PInfo.portal_ci_pa[type][i] = sc->sc_dp[i].dp_ci_pa; 873 XX_PInfo.portal_ce_size[type][i] = sc->sc_dp[i].dp_ce_size; 874 XX_PInfo.portal_ci_size[type][i] = sc->sc_dp[i].dp_ci_size; 875 XX_PInfo.portal_intr[type][i] = sc->sc_dp[i].dp_intr_num; 876 } 877 878 XX_PInfo.portal_ce_va[type] = rman_get_bushandle(sc->sc_rres[0]); 879 XX_PInfo.portal_ci_va[type] = rman_get_bushandle(sc->sc_rres[1]); 880 end: 881 free(dev_name, M_TEMP); 882 } 883 884 static XX_MallocTrackStruct * 885 XX_FindTracker(physAddress_t pa) 886 { 887 struct XX_MallocTrackerList *l; 888 XX_MallocTrackStruct *tp; 889 890 l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; 891 892 LIST_FOREACH(tp, l, entries) { 893 if (tp->pa == pa) 894 return tp; 895 } 896 897 return NULL; 898 } 899 900 void 901 XX_TrackInit(void) 902 { 903 if (XX_MallocTracker == NULL) { 904 XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT, 905 &XX_MallocHashMask); 906 } 907 } 908 909 void 910 XX_TrackAddress(void *addr) 911 { 912 physAddress_t pa; 913 struct XX_MallocTrackerList *l; 914 XX_MallocTrackStruct *ts; 915 916 pa = pmap_kextract((vm_offset_t)addr); 917 918 ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT); 919 ts->va = addr; 920 ts->pa = pa; 921 922 l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; 923 924 mtx_lock(&XX_MallocTrackLock); 925 if (XX_FindTracker(pa) != NULL) 926 free(ts, M_NETCOMMSW_MT); 927 else 928 LIST_INSERT_HEAD(l, ts, entries); 929 mtx_unlock(&XX_MallocTrackLock); 930 } 931 932 void 933 XX_UntrackAddress(void *addr) 934 { 935 physAddress_t pa; 936 XX_MallocTrackStruct *ts; 937 938 pa = pmap_kextract((vm_offset_t)addr); 939 940 KASSERT(XX_MallocTracker != NULL, 941 ("Untracking an address before it's even initialized!\n")); 942 943 mtx_lock(&XX_MallocTrackLock); 944 ts = XX_FindTracker(pa); 945 if (ts != NULL) 946 LIST_REMOVE(ts, entries); 947 mtx_unlock(&XX_MallocTrackLock); 948 free(ts, M_NETCOMMSW_MT); 949 } 950