summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ncsw/user/env/xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ncsw/user/env/xx.c')
-rw-r--r--sys/contrib/ncsw/user/env/xx.c949
1 files changed, 949 insertions, 0 deletions
diff --git a/sys/contrib/ncsw/user/env/xx.c b/sys/contrib/ncsw/user/env/xx.c
new file mode 100644
index 0000000..0ca7bc1
--- /dev/null
+++ b/sys/contrib/ncsw/user/env/xx.c
@@ -0,0 +1,949 @@
+/*-
+ * Copyright (c) 2011 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/rman.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpufunc.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
+#include <machine/stdarg.h>
+
+#include <dev/dpaa/bman.h>
+#include <dev/dpaa/qman.h>
+#include <dev/dpaa/portals.h>
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "list_ext.h"
+#include "mm_ext.h"
+
+/* Configuration */
+
+/* Define the number of dTSEC ports active in system */
+#define MALLOCSMART_DTSEC_IN_USE 4
+
+/*
+ * Calculate malloc's pool size for dTSEC's buffers.
+ * We reserve 1MB pool for each dTSEC port.
+ */
+#define MALLOCSMART_POOL_SIZE \
+ (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024)
+
+#define MALLOCSMART_SLICE_SIZE (PAGE_SIZE / 2) /* 2kB */
+
+/* Defines */
+#define MALLOCSMART_SIZE_TO_SLICE(x) \
+ (((x) + MALLOCSMART_SLICE_SIZE - 1) / MALLOCSMART_SLICE_SIZE)
+#define MALLOCSMART_SLICES \
+ MALLOCSMART_SIZE_TO_SLICE(MALLOCSMART_POOL_SIZE)
+
+/* Malloc Pool for NetCommSW */
+MALLOC_DEFINE(M_NETCOMMSW, "NetCommSW", "NetCommSW software stack");
+MALLOC_DEFINE(M_NETCOMMSW_MT, "NetCommSWTrack",
+ "NetCommSW software allocation tracker");
+
+/* MallocSmart data structures */
+static void *XX_MallocSmartPool;
+static int XX_MallocSmartMap[MALLOCSMART_SLICES];
+
+static struct mtx XX_MallocSmartLock;
+static struct mtx XX_MallocTrackLock;
+MTX_SYSINIT(XX_MallocSmartLockInit, &XX_MallocSmartLock,
+ "NetCommSW MallocSmart Lock", MTX_DEF);
+MTX_SYSINIT(XX_MallocTrackLockInit, &XX_MallocTrackLock,
+ "NetCommSW MallocTrack Lock", MTX_DEF);
+
+/* Interrupt info */
+#define XX_INTR_FLAG_PREALLOCATED (1 << 0)
+#define XX_INTR_FLAG_BOUND (1 << 1)
+#define XX_INTR_FLAG_FMAN_FIX (1 << 2)
+
+struct XX_IntrInfo {
+ driver_intr_t *handler;
+ void *arg;
+ int cpu;
+ int flags;
+ void *cookie;
+};
+
+static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS];
+/* Portal type identifiers */
+enum XX_PortalIdent{
+ BM_PORTAL = 0,
+ QM_PORTAL,
+};
+/* Structure to store portals' properties */
+struct XX_PortalInfo {
+ vm_paddr_t portal_ce_pa[2][MAXCPU];
+ vm_paddr_t portal_ci_pa[2][MAXCPU];
+ uint32_t portal_ce_size[2][MAXCPU];
+ uint32_t portal_ci_size[2][MAXCPU];
+ vm_offset_t portal_ce_va[2];
+ vm_offset_t portal_ci_va[2];
+ uint32_t portal_intr[2][MAXCPU];
+};
+
+static struct XX_PortalInfo XX_PInfo;
+
+/* The lower 9 bits, through emprical testing, tend to be 0. */
+#define XX_MALLOC_TRACK_SHIFT 9
+
+typedef struct XX_MallocTrackStruct {
+ LIST_ENTRY(XX_MallocTrackStruct) entries;
+ physAddress_t pa;
+ void *va;
+} XX_MallocTrackStruct;
+
+LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker;
+u_long XX_MallocHashMask;
+static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa);
+
+void
+XX_Exit(int status)
+{
+
+ panic("NetCommSW: Exit called with status %i", status);
+}
+
+void
+XX_Print(char *str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ vprintf(str, ap);
+ va_end(ap);
+}
+
+void *
+XX_Malloc(uint32_t size)
+{
+ void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT));
+
+ return (p);
+}
+
+static int
+XX_MallocSmartMapCheck(unsigned int start, unsigned int slices)
+{
+ unsigned int i;
+
+ mtx_assert(&XX_MallocSmartLock, MA_OWNED);
+ for (i = start; i < start + slices; i++)
+ if (XX_MallocSmartMap[i])
+ return (FALSE);
+ return (TRUE);
+}
+
+static void
+XX_MallocSmartMapSet(unsigned int start, unsigned int slices)
+{
+ unsigned int i;
+
+ mtx_assert(&XX_MallocSmartLock, MA_OWNED);
+
+ for (i = start; i < start + slices; i++)
+ XX_MallocSmartMap[i] = ((i == start) ? slices : -1);
+}
+
+static void
+XX_MallocSmartMapClear(unsigned int start, unsigned int slices)
+{
+ unsigned int i;
+
+ mtx_assert(&XX_MallocSmartLock, MA_OWNED);
+
+ for (i = start; i < start + slices; i++)
+ XX_MallocSmartMap[i] = 0;
+}
+
+int
+XX_MallocSmartInit(void)
+{
+ int error;
+
+ error = E_OK;
+ mtx_lock(&XX_MallocSmartLock);
+
+ if (XX_MallocSmartPool)
+ goto out;
+
+ /* Allocate MallocSmart pool */
+ XX_MallocSmartPool = contigmalloc(MALLOCSMART_POOL_SIZE, M_NETCOMMSW,
+ M_NOWAIT, 0, 0xFFFFFFFFFull, MALLOCSMART_POOL_SIZE, 0);
+ if (!XX_MallocSmartPool) {
+ error = E_NO_MEMORY;
+ goto out;
+ }
+
+out:
+ mtx_unlock(&XX_MallocSmartLock);
+ return (error);
+}
+
+void *
+XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
+{
+ unsigned int i;
+ vm_offset_t addr;
+
+ addr = 0;
+
+ /* Convert alignment and size to number of slices */
+ alignment = MALLOCSMART_SIZE_TO_SLICE(alignment);
+ size = MALLOCSMART_SIZE_TO_SLICE(size);
+
+ /* Lock resources */
+ mtx_lock(&XX_MallocSmartLock);
+
+ /* Allocate region */
+ for (i = 0; i + size <= MALLOCSMART_SLICES; i += alignment) {
+ if (XX_MallocSmartMapCheck(i, size)) {
+ XX_MallocSmartMapSet(i, size);
+ addr = (vm_offset_t)XX_MallocSmartPool +
+ (i * MALLOCSMART_SLICE_SIZE);
+ break;
+ }
+ }
+
+ /* Unlock resources */
+ mtx_unlock(&XX_MallocSmartLock);
+
+ return ((void *)addr);
+}
+
+void
+XX_FreeSmart(void *p)
+{
+ unsigned int start, slices;
+
+ /* Calculate first slice of region */
+ start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) -
+ (vm_offset_t)XX_MallocSmartPool);
+
+ /* Lock resources */
+ mtx_lock(&XX_MallocSmartLock);
+
+ KASSERT(XX_MallocSmartMap[start] > 0,
+ ("XX_FreeSmart: Double or mid-block free!\n"));
+
+ XX_UntrackAddress(p);
+ /* Free region */
+ slices = XX_MallocSmartMap[start];
+ XX_MallocSmartMapClear(start, slices);
+
+ /* Unlock resources */
+ mtx_unlock(&XX_MallocSmartLock);
+}
+
+void
+XX_Free(void *p)
+{
+
+ if (p != NULL)
+ XX_UntrackAddress(p);
+ free(p, M_NETCOMMSW);
+}
+
+uint32_t
+XX_DisableAllIntr(void)
+{
+
+ return (intr_disable());
+}
+
+void
+XX_RestoreAllIntr(uint32_t flags)
+{
+
+ intr_restore(flags);
+}
+
+t_Error
+XX_Call(uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags )
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (E_OK);
+}
+
+static bool
+XX_IsPortalIntr(int irq)
+{
+ int cpu, type;
+ /* Check interrupt numbers of all available portals */
+ for (cpu = 0, type = 0; XX_PInfo.portal_intr[type][cpu] != 0; cpu++) {
+ if (irq == XX_PInfo.portal_intr[type][cpu]) {
+ /* Found it! */
+ return (1);
+ }
+ if (XX_PInfo.portal_intr[type][cpu + 1] == 0) {
+ type++;
+ cpu = 0;
+ }
+ }
+
+ return (0);
+}
+
+void
+XX_FmanFixIntr(int irq)
+{
+
+ XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX;
+}
+
+static bool
+XX_FmanNeedsIntrFix(int irq)
+{
+
+ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX)
+ return (1);
+
+ return (0);
+}
+
+static void
+XX_Dispatch(void *arg)
+{
+ struct XX_IntrInfo *info;
+
+ info = arg;
+
+ /* Bind this thread to proper CPU when SMP has been already started. */
+ if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started &&
+ info->cpu >= 0) {
+ thread_lock(curthread);
+ sched_bind(curthread, info->cpu);
+ thread_unlock(curthread);
+
+ info->flags |= XX_INTR_FLAG_BOUND;
+ }
+
+ if (info->handler == NULL) {
+ printf("%s(): IRQ handler is NULL!\n", __func__);
+ return;
+ }
+
+ info->handler(info->arg);
+}
+
+t_Error
+XX_PreallocAndBindIntr(int irq, unsigned int cpu)
+{
+ struct resource *r;
+ unsigned int inum;
+ t_Error error;
+
+ r = (struct resource *)irq;
+ inum = rman_get_start(r);
+
+ error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]);
+ if (error != 0)
+ return (error);
+
+ XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED;
+ XX_IntrInfo[inum].cpu = cpu;
+
+ return (E_OK);
+}
+
+t_Error
+XX_DeallocIntr(int irq)
+{
+ struct resource *r;
+ unsigned int inum;
+
+ r = (struct resource *)irq;
+ inum = rman_get_start(r);
+
+ if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0)
+ return (E_INVALID_STATE);
+
+ XX_IntrInfo[inum].flags = 0;
+ return (XX_FreeIntr(irq));
+}
+
+t_Error
+XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle)
+{
+ struct device *dev;
+ struct resource *r;
+ unsigned int flags;
+ int err;
+
+ r = (struct resource *)irq;
+ dev = rman_get_device(r);
+ irq = rman_get_start(r);
+
+ /* Handle preallocated interrupts */
+ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
+ if (XX_IntrInfo[irq].handler != NULL)
+ return (E_BUSY);
+
+ XX_IntrInfo[irq].handler = f_Isr;
+ XX_IntrInfo[irq].arg = handle;
+
+ return (E_OK);
+ }
+
+ flags = INTR_TYPE_NET | INTR_MPSAFE;
+
+ /* BMAN/QMAN Portal interrupts must be exlusive */
+ if (XX_IsPortalIntr(irq))
+ flags |= INTR_EXCL;
+
+ err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle,
+ &XX_IntrInfo[irq].cookie);
+ if (err)
+ goto finish;
+
+ /*
+ * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each
+ * interrupt to all CPUs. Race between an interrupt assertion and
+ * masking may occur and interrupt handler may be called multiple times
+ * per one interrupt. FMan doesn't support such a situation. Workaround
+ * is to bind FMan interrupt to one CPU0 only.
+ */
+#ifdef SMP
+ if (XX_FmanNeedsIntrFix(irq))
+ err = powerpc_bind_intr(irq, 0);
+#endif
+finish:
+ return (err);
+}
+
+t_Error
+XX_FreeIntr(int irq)
+{
+ struct device *dev;
+ struct resource *r;
+
+ r = (struct resource *)irq;
+ dev = rman_get_device(r);
+ irq = rman_get_start(r);
+
+ /* Handle preallocated interrupts */
+ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
+ if (XX_IntrInfo[irq].handler == NULL)
+ return (E_INVALID_STATE);
+
+ XX_IntrInfo[irq].handler = NULL;
+ XX_IntrInfo[irq].arg = NULL;
+
+ return (E_OK);
+ }
+
+ return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
+}
+
+t_Error
+XX_EnableIntr(int irq)
+{
+ struct resource *r;
+
+ r = (struct resource *)irq;
+ irq = rman_get_start(r);
+
+ powerpc_intr_unmask(irq);
+
+ return (E_OK);
+}
+
+t_Error
+XX_DisableIntr(int irq)
+{
+ struct resource *r;
+
+ r = (struct resource *)irq;
+ irq = rman_get_start(r);
+
+ powerpc_intr_mask(irq);
+
+ return (E_OK);
+}
+
+t_TaskletHandle
+XX_InitTasklet (void (*routine)(void *), void *data)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (NULL);
+}
+
+
+void
+XX_FreeTasklet (t_TaskletHandle h_Tasklet)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+int
+XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (0);
+}
+
+void
+XX_FlushScheduledTasks(void)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+int
+XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (0);
+}
+
+void
+XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+t_Handle
+XX_GetTaskletData(t_TaskletHandle h_Tasklet)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (NULL);
+}
+
+t_Handle
+XX_InitSpinlock(void)
+{
+ struct mtx *m;
+
+ m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT);
+ if (!m)
+ return (0);
+
+ mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK);
+
+ return (m);
+}
+
+void
+XX_FreeSpinlock(t_Handle h_Spinlock)
+{
+ struct mtx *m;
+
+ m = h_Spinlock;
+
+ mtx_destroy(m);
+ free(m, M_NETCOMMSW);
+}
+
+void
+XX_LockSpinlock(t_Handle h_Spinlock)
+{
+ struct mtx *m;
+
+ m = h_Spinlock;
+ mtx_lock(m);
+}
+
+void
+XX_UnlockSpinlock(t_Handle h_Spinlock)
+{
+ struct mtx *m;
+
+ m = h_Spinlock;
+ mtx_unlock(m);
+}
+
+uint32_t
+XX_LockIntrSpinlock(t_Handle h_Spinlock)
+{
+
+ XX_LockSpinlock(h_Spinlock);
+ return (0);
+}
+
+void
+XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
+{
+
+ XX_UnlockSpinlock(h_Spinlock);
+}
+
+uint32_t
+XX_CurrentTime(void)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (0);
+}
+
+
+t_Handle
+XX_CreateTimer(void)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (NULL);
+}
+
+void
+XX_FreeTimer(t_Handle h_Timer)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+void
+XX_StartTimer(t_Handle h_Timer,
+ uint32_t msecs,
+ bool periodic,
+ void (*f_TimerExpired)(t_Handle),
+ t_Handle h_Arg)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+uint32_t
+XX_GetExpirationTime(t_Handle h_Timer)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (0);
+}
+
+void
+XX_StopTimer(t_Handle h_Timer)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+void
+XX_ModTimer(t_Handle h_Timer, uint32_t msecs)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+}
+
+int
+XX_TimerIsActive(t_Handle h_Timer)
+{
+ /* Not referenced */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (0);
+}
+
+uint32_t
+XX_Sleep(uint32_t msecs)
+{
+
+ XX_UDelay(1000 * msecs);
+ return (0);
+}
+
+void
+XX_UDelay(uint32_t usecs)
+{
+ DELAY(usecs);
+}
+
+t_Error
+XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ t_IpcMsgHandler *f_MsgHandler, t_Handle h_Module, uint32_t replyLength)
+{
+
+ /*
+ * This function returns fake E_OK status and does nothing
+ * as NetCommSW IPC is not used by FreeBSD drivers.
+ */
+ return (E_OK);
+}
+
+t_Error
+XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+ /*
+ * This function returns fake E_OK status and does nothing
+ * as NetCommSW IPC is not used by FreeBSD drivers.
+ */
+ return (E_OK);
+}
+
+
+t_Error
+XX_IpcSendMessage(t_Handle h_Session,
+ uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply,
+ uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg)
+{
+
+ /* Should not be called */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (E_OK);
+}
+
+t_Handle
+XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+
+ /* Should not be called */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (E_OK);
+}
+
+t_Error
+XX_IpcFreeSession(t_Handle h_Session)
+{
+
+ /* Should not be called */
+ printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
+ return (E_OK);
+}
+
+extern void db_trace_self(void);
+physAddress_t
+XX_VirtToPhys(void *addr)
+{
+ vm_paddr_t paddr;
+ int cpu;
+
+ cpu = PCPU_GET(cpuid);
+
+ /* Handle NULL address */
+ if (addr == NULL)
+ return (-1);
+
+ /* Handle BMAN mappings */
+ if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) &&
+ ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] +
+ XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
+ return (XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
+ (vm_offset_t)addr - XX_PInfo.portal_ce_va[BM_PORTAL]);
+
+ if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[BM_PORTAL]) &&
+ ((vm_offset_t)addr < XX_PInfo.portal_ci_va[BM_PORTAL] +
+ XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
+ return (XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
+ (vm_offset_t)addr - XX_PInfo.portal_ci_va[BM_PORTAL]);
+
+ /* Handle QMAN mappings */
+ if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[QM_PORTAL]) &&
+ ((vm_offset_t)addr < XX_PInfo.portal_ce_va[QM_PORTAL] +
+ XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
+ return (XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
+ (vm_offset_t)addr - XX_PInfo.portal_ce_va[QM_PORTAL]);
+
+ if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[QM_PORTAL]) &&
+ ((vm_offset_t)addr < XX_PInfo.portal_ci_va[QM_PORTAL] +
+ XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
+ return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
+ (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]);
+
+ paddr = pmap_kextract((vm_offset_t)addr);
+ if (!paddr)
+ printf("NetCommSW: "
+ "Unable to translate virtual address 0x%08X!\n", addr);
+ else
+ XX_TrackAddress(addr);
+
+ return (paddr);
+}
+
+void *
+XX_PhysToVirt(physAddress_t addr)
+{
+ XX_MallocTrackStruct *ts;
+ int cpu;
+
+ cpu = PCPU_GET(cpuid);
+
+ /* Handle BMAN mappings */
+ if ((addr >= XX_PInfo.portal_ce_pa[BM_PORTAL][cpu]) &&
+ (addr < XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
+ XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
+ return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
+ (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
+
+ if ((addr >= XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]) &&
+ (addr < XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
+ XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
+ return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
+ (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
+
+ /* Handle QMAN mappings */
+ if ((addr >= XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]) &&
+ (addr < XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
+ XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
+ return ((void *)(XX_PInfo.portal_ce_va[QM_PORTAL] +
+ (vm_offset_t)(addr - XX_PInfo.portal_ce_pa[QM_PORTAL][cpu])));
+
+ if ((addr >= XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]) &&
+ (addr < XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
+ XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
+ return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] +
+ (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu])));
+
+ mtx_lock(&XX_MallocTrackLock);
+ ts = XX_FindTracker(addr);
+ mtx_unlock(&XX_MallocTrackLock);
+
+ if (ts != NULL)
+ return ts->va;
+
+ printf("NetCommSW: "
+ "Unable to translate physical address 0x%08llX!\n", addr);
+
+ return (NULL);
+}
+
+void
+XX_PortalSetInfo(device_t dev)
+{
+ char *dev_name;
+ struct dpaa_portals_softc *sc;
+ int i, type, len;
+
+ dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK |
+ M_ZERO);
+
+ len = strlen("bman-portals");
+
+ strncpy(dev_name, device_get_name(dev), len);
+
+ if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name,
+ "qman-portals", len))
+ goto end;
+
+ if (strncmp(dev_name, "bman-portals", len) == 0)
+ type = BM_PORTAL;
+ else
+ type = QM_PORTAL;
+
+ sc = device_get_softc(dev);
+
+ for (i = 0; sc->sc_dp[i].dp_ce_pa != 0; i++) {
+ XX_PInfo.portal_ce_pa[type][i] = sc->sc_dp[i].dp_ce_pa;
+ XX_PInfo.portal_ci_pa[type][i] = sc->sc_dp[i].dp_ci_pa;
+ XX_PInfo.portal_ce_size[type][i] = sc->sc_dp[i].dp_ce_size;
+ XX_PInfo.portal_ci_size[type][i] = sc->sc_dp[i].dp_ci_size;
+ XX_PInfo.portal_intr[type][i] = sc->sc_dp[i].dp_intr_num;
+ }
+
+ XX_PInfo.portal_ce_va[type] = rman_get_bushandle(sc->sc_rres[0]);
+ XX_PInfo.portal_ci_va[type] = rman_get_bushandle(sc->sc_rres[1]);
+end:
+ free(dev_name, M_TEMP);
+}
+
+static XX_MallocTrackStruct *
+XX_FindTracker(physAddress_t pa)
+{
+ struct XX_MallocTrackerList *l;
+ XX_MallocTrackStruct *tp;
+
+ l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
+
+ LIST_FOREACH(tp, l, entries) {
+ if (tp->pa == pa)
+ return tp;
+ }
+
+ return NULL;
+}
+
+void
+XX_TrackInit(void)
+{
+ if (XX_MallocTracker == NULL) {
+ XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT,
+ &XX_MallocHashMask);
+ }
+}
+
+void
+XX_TrackAddress(void *addr)
+{
+ physAddress_t pa;
+ struct XX_MallocTrackerList *l;
+ XX_MallocTrackStruct *ts;
+
+ pa = pmap_kextract((vm_offset_t)addr);
+
+ ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT);
+ ts->va = addr;
+ ts->pa = pa;
+
+ l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
+
+ mtx_lock(&XX_MallocTrackLock);
+ if (XX_FindTracker(pa) != NULL)
+ free(ts, M_NETCOMMSW_MT);
+ else
+ LIST_INSERT_HEAD(l, ts, entries);
+ mtx_unlock(&XX_MallocTrackLock);
+}
+
+void
+XX_UntrackAddress(void *addr)
+{
+ physAddress_t pa;
+ XX_MallocTrackStruct *ts;
+
+ pa = pmap_kextract((vm_offset_t)addr);
+
+ KASSERT(XX_MallocTracker != NULL,
+ ("Untracking an address before it's even initialized!\n"));
+
+ mtx_lock(&XX_MallocTrackLock);
+ ts = XX_FindTracker(pa);
+ if (ts != NULL)
+ LIST_REMOVE(ts, entries);
+ mtx_unlock(&XX_MallocTrackLock);
+ free(ts, M_NETCOMMSW_MT);
+}
OpenPOWER on IntegriCloud