2 * Copyright (c) 2011 Semihalf.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
32 #include <sys/interrupt.h>
34 #include <sys/mutex.h>
36 #include <sys/queue.h>
38 #include <sys/sched.h>
42 #include <vm/vm_param.h>
43 #include <vm/vm_page.h>
45 #include <machine/cpufunc.h>
46 #include <machine/intr_machdep.h>
47 #include <machine/pmap.h>
48 #include <machine/stdarg.h>
50 #include <dev/dpaa/bman.h>
51 #include <dev/dpaa/qman.h>
52 #include <dev/dpaa/portals.h>
54 #include "error_ext.h"
61 /* Define the number of dTSEC ports active in system */
62 #define MALLOCSMART_DTSEC_IN_USE 4
65 * Calculate malloc's pool size for dTSEC's buffers.
66 * We reserve 1MB pool for each dTSEC port.
68 #define MALLOCSMART_POOL_SIZE \
69 (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024)
71 #define MALLOCSMART_SLICE_SIZE (PAGE_SIZE / 2) /* 2kB */
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)
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");
84 /* MallocSmart data structures */
85 static void *XX_MallocSmartPool;
86 static int XX_MallocSmartMap[MALLOCSMART_SLICES];
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);
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)
101 driver_intr_t *handler;
108 static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS];
109 /* Portal type identifiers */
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];
125 static struct XX_PortalInfo XX_PInfo;
127 /* The lower 9 bits, through emprical testing, tend to be 0. */
128 #define XX_MALLOC_TRACK_SHIFT 9
130 typedef struct XX_MallocTrackStruct {
131 LIST_ENTRY(XX_MallocTrackStruct) entries;
134 } XX_MallocTrackStruct;
136 LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker;
137 u_long XX_MallocHashMask;
138 static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa);
144 panic("NetCommSW: Exit called with status %i", status);
148 XX_Print(char *str, ...)
158 XX_Malloc(uint32_t size)
160 void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT));
166 XX_MallocSmartMapCheck(unsigned int start, unsigned int slices)
170 mtx_assert(&XX_MallocSmartLock, MA_OWNED);
171 for (i = start; i < start + slices; i++)
172 if (XX_MallocSmartMap[i])
178 XX_MallocSmartMapSet(unsigned int start, unsigned int slices)
182 mtx_assert(&XX_MallocSmartLock, MA_OWNED);
184 for (i = start; i < start + slices; i++)
185 XX_MallocSmartMap[i] = ((i == start) ? slices : -1);
189 XX_MallocSmartMapClear(unsigned int start, unsigned int slices)
193 mtx_assert(&XX_MallocSmartLock, MA_OWNED);
195 for (i = start; i < start + slices; i++)
196 XX_MallocSmartMap[i] = 0;
200 XX_MallocSmartInit(void)
205 mtx_lock(&XX_MallocSmartLock);
207 if (XX_MallocSmartPool)
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) {
219 mtx_unlock(&XX_MallocSmartLock);
224 XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
231 /* Convert alignment and size to number of slices */
232 alignment = MALLOCSMART_SIZE_TO_SLICE(alignment);
233 size = MALLOCSMART_SIZE_TO_SLICE(size);
236 mtx_lock(&XX_MallocSmartLock);
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);
248 /* Unlock resources */
249 mtx_unlock(&XX_MallocSmartLock);
251 return ((void *)addr);
255 XX_FreeSmart(void *p)
257 unsigned int start, slices;
259 /* Calculate first slice of region */
260 start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) -
261 (vm_offset_t)XX_MallocSmartPool);
264 mtx_lock(&XX_MallocSmartLock);
266 KASSERT(XX_MallocSmartMap[start] > 0,
267 ("XX_FreeSmart: Double or mid-block free!\n"));
269 XX_UntrackAddress(p);
271 slices = XX_MallocSmartMap[start];
272 XX_MallocSmartMapClear(start, slices);
274 /* Unlock resources */
275 mtx_unlock(&XX_MallocSmartLock);
283 XX_UntrackAddress(p);
284 free(p, M_NETCOMMSW);
288 XX_DisableAllIntr(void)
291 return (intr_disable());
295 XX_RestoreAllIntr(uint32_t flags)
302 XX_Call(uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags )
305 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
310 XX_IsPortalIntr(int irq)
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]) {
319 if (XX_PInfo.portal_intr[type][cpu + 1] == 0) {
329 XX_FmanFixIntr(int irq)
332 XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX;
336 XX_FmanNeedsIntrFix(int irq)
339 if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX)
346 XX_Dispatch(void *arg)
348 struct XX_IntrInfo *info;
352 /* Bind this thread to proper CPU when SMP has been already started. */
353 if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started &&
355 thread_lock(curthread);
356 sched_bind(curthread, info->cpu);
357 thread_unlock(curthread);
359 info->flags |= XX_INTR_FLAG_BOUND;
362 if (info->handler == NULL) {
363 printf("%s(): IRQ handler is NULL!\n", __func__);
367 info->handler(info->arg);
371 XX_PreallocAndBindIntr(int irq, unsigned int cpu)
377 r = (struct resource *)irq;
378 inum = rman_get_start(r);
380 error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]);
384 XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED;
385 XX_IntrInfo[inum].cpu = cpu;
391 XX_DeallocIntr(int irq)
396 r = (struct resource *)irq;
397 inum = rman_get_start(r);
399 if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0)
400 return (E_INVALID_STATE);
402 XX_IntrInfo[inum].flags = 0;
403 return (XX_FreeIntr(irq));
407 XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle)
414 r = (struct resource *)irq;
415 dev = rman_get_device(r);
416 irq = rman_get_start(r);
418 /* Handle preallocated interrupts */
419 if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
420 if (XX_IntrInfo[irq].handler != NULL)
423 XX_IntrInfo[irq].handler = f_Isr;
424 XX_IntrInfo[irq].arg = handle;
429 flags = INTR_TYPE_NET | INTR_MPSAFE;
431 /* BMAN/QMAN Portal interrupts must be exlusive */
432 if (XX_IsPortalIntr(irq))
435 err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle,
436 &XX_IntrInfo[irq].cookie);
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.
448 if (XX_FmanNeedsIntrFix(irq))
449 err = powerpc_bind_intr(irq, 0);
461 r = (struct resource *)irq;
462 dev = rman_get_device(r);
463 irq = rman_get_start(r);
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);
470 XX_IntrInfo[irq].handler = NULL;
471 XX_IntrInfo[irq].arg = NULL;
476 return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
480 XX_EnableIntr(int irq)
484 r = (struct resource *)irq;
485 irq = rman_get_start(r);
487 powerpc_intr_unmask(irq);
493 XX_DisableIntr(int irq)
497 r = (struct resource *)irq;
498 irq = rman_get_start(r);
500 powerpc_intr_mask(irq);
506 XX_InitTasklet (void (*routine)(void *), void *data)
509 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
515 XX_FreeTasklet (t_TaskletHandle h_Tasklet)
518 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
522 XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
525 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
530 XX_FlushScheduledTasks(void)
533 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
537 XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
540 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
545 XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
548 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
552 XX_GetTaskletData(t_TaskletHandle h_Tasklet)
555 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
560 XX_InitSpinlock(void)
564 m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT | M_ZERO);
568 mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK);
574 XX_FreeSpinlock(t_Handle h_Spinlock)
581 free(m, M_NETCOMMSW);
585 XX_LockSpinlock(t_Handle h_Spinlock)
594 XX_UnlockSpinlock(t_Handle h_Spinlock)
603 XX_LockIntrSpinlock(t_Handle h_Spinlock)
606 XX_LockSpinlock(h_Spinlock);
611 XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
614 XX_UnlockSpinlock(h_Spinlock);
621 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
630 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
635 XX_FreeTimer(t_Handle h_Timer)
638 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
642 XX_StartTimer(t_Handle h_Timer,
645 void (*f_TimerExpired)(t_Handle),
649 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
653 XX_GetExpirationTime(t_Handle h_Timer)
656 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
661 XX_StopTimer(t_Handle h_Timer)
664 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
668 XX_ModTimer(t_Handle h_Timer, uint32_t msecs)
671 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
675 XX_TimerIsActive(t_Handle h_Timer)
678 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
683 XX_Sleep(uint32_t msecs)
686 XX_UDelay(1000 * msecs);
691 XX_UDelay(uint32_t usecs)
697 XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
698 t_IpcMsgHandler *f_MsgHandler, t_Handle h_Module, uint32_t replyLength)
702 * This function returns fake E_OK status and does nothing
703 * as NetCommSW IPC is not used by FreeBSD drivers.
709 XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
712 * This function returns fake E_OK status and does nothing
713 * as NetCommSW IPC is not used by FreeBSD drivers.
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)
725 /* Should not be called */
726 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
731 XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
732 char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
735 /* Should not be called */
736 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
741 XX_IpcFreeSession(t_Handle h_Session)
744 /* Should not be called */
745 printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
749 extern void db_trace_self(void);
751 XX_VirtToPhys(void *addr)
756 cpu = PCPU_GET(cpuid);
758 /* Handle NULL address */
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]);
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]);
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]);
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]);
788 paddr = pmap_kextract((vm_offset_t)addr);
791 "Unable to translate virtual address 0x%08X!\n", addr);
793 XX_TrackAddress(addr);
799 XX_PhysToVirt(physAddress_t addr)
801 XX_MallocTrackStruct *ts;
804 cpu = PCPU_GET(cpuid);
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])));
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])));
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])));
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])));
832 mtx_lock(&XX_MallocTrackLock);
833 ts = XX_FindTracker(addr);
834 mtx_unlock(&XX_MallocTrackLock);
840 "Unable to translate physical address 0x%08llX!\n", addr);
846 XX_PortalSetInfo(device_t dev)
849 struct dpaa_portals_softc *sc;
852 dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK |
855 len = strlen("bman-portals");
857 strncpy(dev_name, device_get_name(dev), len);
859 if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name,
860 "qman-portals", len))
863 if (strncmp(dev_name, "bman-portals", len) == 0)
868 sc = device_get_softc(dev);
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;
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]);
881 free(dev_name, M_TEMP);
884 static XX_MallocTrackStruct *
885 XX_FindTracker(physAddress_t pa)
887 struct XX_MallocTrackerList *l;
888 XX_MallocTrackStruct *tp;
890 l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
892 LIST_FOREACH(tp, l, entries) {
903 if (XX_MallocTracker == NULL) {
904 XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT,
910 XX_TrackAddress(void *addr)
913 struct XX_MallocTrackerList *l;
914 XX_MallocTrackStruct *ts;
916 pa = pmap_kextract((vm_offset_t)addr);
918 ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT);
922 l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
924 mtx_lock(&XX_MallocTrackLock);
925 if (XX_FindTracker(pa) != NULL)
926 free(ts, M_NETCOMMSW_MT);
928 LIST_INSERT_HEAD(l, ts, entries);
929 mtx_unlock(&XX_MallocTrackLock);
933 XX_UntrackAddress(void *addr)
936 XX_MallocTrackStruct *ts;
938 pa = pmap_kextract((vm_offset_t)addr);
940 KASSERT(XX_MallocTracker != NULL,
941 ("Untracking an address before it's even initialized!\n"));
943 mtx_lock(&XX_MallocTrackLock);
944 ts = XX_FindTracker(pa);
946 LIST_REMOVE(ts, entries);
947 mtx_unlock(&XX_MallocTrackLock);
948 free(ts, M_NETCOMMSW_MT);