1296177Sjhibbits/*- 2296177Sjhibbits * Copyright (c) 2011-2012 Semihalf. 3296177Sjhibbits * All rights reserved. 4296177Sjhibbits * 5296177Sjhibbits * Redistribution and use in source and binary forms, with or without 6296177Sjhibbits * modification, are permitted provided that the following conditions 7296177Sjhibbits * are met: 8296177Sjhibbits * 1. Redistributions of source code must retain the above copyright 9296177Sjhibbits * notice, this list of conditions and the following disclaimer. 10296177Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright 11296177Sjhibbits * notice, this list of conditions and the following disclaimer in the 12296177Sjhibbits * documentation and/or other materials provided with the distribution. 13296177Sjhibbits * 14296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15296177Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16296177Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17296177Sjhibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18296177Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19296177Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20296177Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21296177Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22296177Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296177Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296177Sjhibbits * SUCH DAMAGE. 25296177Sjhibbits */ 26296177Sjhibbits 27296177Sjhibbits#include <sys/cdefs.h> 28296177Sjhibbits__FBSDID("$FreeBSD$"); 29296177Sjhibbits 30296177Sjhibbits#include <sys/param.h> 31296177Sjhibbits#include <sys/systm.h> 32296177Sjhibbits#include <sys/kernel.h> 33296177Sjhibbits#include <sys/bus.h> 34296177Sjhibbits#include <sys/lock.h> 35296177Sjhibbits#include <sys/module.h> 36296177Sjhibbits#include <sys/mutex.h> 37296177Sjhibbits#include <sys/proc.h> 38296177Sjhibbits#include <sys/pcpu.h> 39296177Sjhibbits#include <sys/rman.h> 40296177Sjhibbits#include <sys/sched.h> 41296177Sjhibbits 42296177Sjhibbits#include <machine/tlb.h> 43296177Sjhibbits 44296177Sjhibbits#include "bman.h" 45296177Sjhibbits 46296177Sjhibbitsdevclass_t bman_devclass; 47296177Sjhibbits 48296177Sjhibbitsstatic struct bman_softc *bman_sc; 49296177Sjhibbits 50296177Sjhibbitsextern t_Handle bman_portal_setup(struct bman_softc *bsc); 51296177Sjhibbits 52296177Sjhibbitsstatic void 53296177Sjhibbitsbman_exception(t_Handle h_App, e_BmExceptions exception) 54296177Sjhibbits{ 55296177Sjhibbits struct bman_softc *sc; 56296177Sjhibbits const char *message; 57296177Sjhibbits 58296177Sjhibbits sc = h_App; 59296177Sjhibbits 60296177Sjhibbits switch (exception) { 61296177Sjhibbits case e_BM_EX_INVALID_COMMAND: 62296177Sjhibbits message = "Invalid Command Verb"; 63296177Sjhibbits break; 64296177Sjhibbits case e_BM_EX_FBPR_THRESHOLD: 65296177Sjhibbits message = "FBPR pool exhaused. Consider increasing " 66296177Sjhibbits "BMAN_MAX_BUFFERS"; 67296177Sjhibbits break; 68296177Sjhibbits case e_BM_EX_SINGLE_ECC: 69296177Sjhibbits message = "Single bit ECC error"; 70296177Sjhibbits break; 71296177Sjhibbits case e_BM_EX_MULTI_ECC: 72296177Sjhibbits message = "Multi bit ECC error"; 73296177Sjhibbits break; 74296177Sjhibbits default: 75296177Sjhibbits message = "Unknown error"; 76296177Sjhibbits } 77296177Sjhibbits 78296177Sjhibbits device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message); 79296177Sjhibbits} 80296177Sjhibbits 81296177Sjhibbitsint 82296177Sjhibbitsbman_attach(device_t dev) 83296177Sjhibbits{ 84296177Sjhibbits struct bman_softc *sc; 85296177Sjhibbits t_BmRevisionInfo rev; 86296177Sjhibbits t_Error error; 87296177Sjhibbits t_BmParam bp; 88296177Sjhibbits 89296177Sjhibbits sc = device_get_softc(dev); 90296177Sjhibbits sc->sc_dev = dev; 91296177Sjhibbits bman_sc = sc; 92296177Sjhibbits 93296177Sjhibbits /* Check if MallocSmart allocator is ready */ 94296177Sjhibbits if (XX_MallocSmartInit() != E_OK) 95296177Sjhibbits return (ENXIO); 96296177Sjhibbits 97296177Sjhibbits /* Allocate resources */ 98296177Sjhibbits sc->sc_rrid = 0; 99296177Sjhibbits sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, 100296177Sjhibbits &sc->sc_rrid, 0, ~0, BMAN_CCSR_SIZE, RF_ACTIVE); 101296177Sjhibbits if (sc->sc_rres == NULL) 102296177Sjhibbits return (ENXIO); 103296177Sjhibbits 104296177Sjhibbits sc->sc_irid = 0; 105296177Sjhibbits sc->sc_ires = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, 106296177Sjhibbits &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); 107296177Sjhibbits if (sc->sc_ires == NULL) 108296177Sjhibbits goto err; 109296177Sjhibbits 110296177Sjhibbits /* Initialize BMAN */ 111296177Sjhibbits memset(&bp, 0, sizeof(bp)); 112296177Sjhibbits bp.guestId = NCSW_MASTER_ID; 113296177Sjhibbits bp.baseAddress = rman_get_bushandle(sc->sc_rres); 114296177Sjhibbits bp.totalNumOfBuffers = BMAN_MAX_BUFFERS; 115296177Sjhibbits bp.f_Exception = bman_exception; 116296177Sjhibbits bp.h_App = sc; 117296177Sjhibbits bp.errIrq = (int)sc->sc_ires; 118296177Sjhibbits bp.partBpidBase = 0; 119296177Sjhibbits bp.partNumOfPools = BM_MAX_NUM_OF_POOLS; 120296177Sjhibbits printf("base address: %llx\n", (uint64_t)bp.baseAddress); 121296177Sjhibbits 122296177Sjhibbits sc->sc_bh = BM_Config(&bp); 123296177Sjhibbits if (sc->sc_bh == NULL) 124296177Sjhibbits goto err; 125296177Sjhibbits 126296177Sjhibbits /* Warn if there is less than 5% free FPBR's in pool */ 127296177Sjhibbits error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20); 128296177Sjhibbits if (error != E_OK) 129296177Sjhibbits goto err; 130296177Sjhibbits 131296177Sjhibbits error = BM_Init(sc->sc_bh); 132296177Sjhibbits if (error != E_OK) 133296177Sjhibbits goto err; 134296177Sjhibbits 135296177Sjhibbits error = BM_GetRevision(sc->sc_bh, &rev); 136296177Sjhibbits if (error != E_OK) 137296177Sjhibbits goto err; 138296177Sjhibbits 139296177Sjhibbits device_printf(dev, "Hardware version: %d.%d.\n", 140296177Sjhibbits rev.majorRev, rev.minorRev); 141296177Sjhibbits 142296177Sjhibbits return (0); 143296177Sjhibbits 144296177Sjhibbitserr: 145296177Sjhibbits bman_detach(dev); 146296177Sjhibbits return (ENXIO); 147296177Sjhibbits} 148296177Sjhibbits 149296177Sjhibbitsint 150296177Sjhibbitsbman_detach(device_t dev) 151296177Sjhibbits{ 152296177Sjhibbits struct bman_softc *sc; 153296177Sjhibbits 154296177Sjhibbits sc = device_get_softc(dev); 155296177Sjhibbits 156296177Sjhibbits if (sc->sc_bh != NULL) 157296177Sjhibbits BM_Free(sc->sc_bh); 158296177Sjhibbits 159296177Sjhibbits if (sc->sc_ires != NULL) 160296177Sjhibbits bus_release_resource(dev, SYS_RES_IRQ, 161296177Sjhibbits sc->sc_irid, sc->sc_ires); 162296177Sjhibbits 163296177Sjhibbits if (sc->sc_rres != NULL) 164296177Sjhibbits bus_release_resource(dev, SYS_RES_MEMORY, 165296177Sjhibbits sc->sc_rrid, sc->sc_rres); 166296177Sjhibbits 167296177Sjhibbits return (0); 168296177Sjhibbits} 169296177Sjhibbits 170296177Sjhibbitsint 171296177Sjhibbitsbman_suspend(device_t dev) 172296177Sjhibbits{ 173296177Sjhibbits 174296177Sjhibbits return (0); 175296177Sjhibbits} 176296177Sjhibbits 177296177Sjhibbitsint 178296177Sjhibbitsbman_resume(device_t dev) 179296177Sjhibbits{ 180296177Sjhibbits 181296177Sjhibbits return (0); 182296177Sjhibbits} 183296177Sjhibbits 184296177Sjhibbitsint 185296177Sjhibbitsbman_shutdown(device_t dev) 186296177Sjhibbits{ 187296177Sjhibbits 188296177Sjhibbits return (0); 189296177Sjhibbits} 190296177Sjhibbits 191296177Sjhibbits/* 192296177Sjhibbits * BMAN API 193296177Sjhibbits */ 194296177Sjhibbits 195296177Sjhibbitst_Handle 196296177Sjhibbitsbman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers, 197296177Sjhibbits uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf, 198296177Sjhibbits t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit, 199296177Sjhibbits uint32_t dep_hw_entry, uint32_t dep_hw_exit, 200296177Sjhibbits t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool, 201296177Sjhibbits t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys) 202296177Sjhibbits{ 203296177Sjhibbits uint32_t thresholds[MAX_DEPLETION_THRESHOLDS]; 204296177Sjhibbits struct bman_softc *sc; 205296177Sjhibbits t_Handle pool, portal; 206296177Sjhibbits t_BmPoolParam bpp; 207296177Sjhibbits int error; 208296177Sjhibbits 209296177Sjhibbits sc = bman_sc; 210296177Sjhibbits pool = NULL; 211296177Sjhibbits 212296177Sjhibbits sched_pin(); 213296177Sjhibbits 214296177Sjhibbits portal = bman_portal_setup(sc); 215296177Sjhibbits if (portal == NULL) 216296177Sjhibbits goto err; 217296177Sjhibbits 218296177Sjhibbits memset(&bpp, 0, sizeof(bpp)); 219296177Sjhibbits bpp.h_Bm = sc->sc_bh; 220296177Sjhibbits bpp.h_BmPortal = portal; 221296177Sjhibbits bpp.h_App = h_BufferPool; 222296177Sjhibbits bpp.numOfBuffers = allocBuffers; 223296177Sjhibbits 224296177Sjhibbits bpp.bufferPoolInfo.h_BufferPool = h_BufferPool; 225296177Sjhibbits bpp.bufferPoolInfo.f_GetBuf = f_GetBuf; 226296177Sjhibbits bpp.bufferPoolInfo.f_PutBuf = f_PutBuf; 227296177Sjhibbits bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt; 228296177Sjhibbits bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys; 229296177Sjhibbits bpp.bufferPoolInfo.bufferSize = bufferSize; 230296177Sjhibbits 231296177Sjhibbits pool = BM_POOL_Config(&bpp); 232296177Sjhibbits if (pool == NULL) 233296177Sjhibbits goto err; 234296177Sjhibbits 235296177Sjhibbits /* 236296177Sjhibbits * Buffer context must be disabled on FreeBSD 237296177Sjhibbits * as it could cause memory corruption. 238296177Sjhibbits */ 239296177Sjhibbits BM_POOL_ConfigBuffContextMode(pool, 0); 240296177Sjhibbits 241296177Sjhibbits if (minBuffers != 0 || maxBuffers != 0) { 242296177Sjhibbits error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers); 243296177Sjhibbits if (error != E_OK) 244296177Sjhibbits goto err; 245296177Sjhibbits } 246296177Sjhibbits 247296177Sjhibbits if (f_Depletion != NULL) { 248296177Sjhibbits thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry; 249296177Sjhibbits thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit; 250296177Sjhibbits thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry; 251296177Sjhibbits thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit; 252296177Sjhibbits error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds); 253296177Sjhibbits if (error != E_OK) 254296177Sjhibbits goto err; 255296177Sjhibbits } 256296177Sjhibbits 257296177Sjhibbits error = BM_POOL_Init(pool); 258296177Sjhibbits if (error != E_OK) 259296177Sjhibbits goto err; 260296177Sjhibbits 261296177Sjhibbits *bpid = BM_POOL_GetId(pool); 262296177Sjhibbits sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid); 263296177Sjhibbits 264296177Sjhibbits sched_unpin(); 265296177Sjhibbits 266296177Sjhibbits return (pool); 267296177Sjhibbits 268296177Sjhibbitserr: 269296177Sjhibbits if (pool != NULL) 270296177Sjhibbits BM_POOL_Free(pool); 271296177Sjhibbits 272296177Sjhibbits sched_unpin(); 273296177Sjhibbits 274296177Sjhibbits return (NULL); 275296177Sjhibbits} 276296177Sjhibbits 277296177Sjhibbitsint 278296177Sjhibbitsbman_pool_destroy(t_Handle pool) 279296177Sjhibbits{ 280296177Sjhibbits struct bman_softc *sc; 281296177Sjhibbits 282296177Sjhibbits sc = bman_sc; 283296177Sjhibbits thread_lock(curthread); 284296177Sjhibbits sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]); 285296177Sjhibbits thread_unlock(curthread); 286296177Sjhibbits 287296177Sjhibbits BM_POOL_Free(pool); 288296177Sjhibbits 289296177Sjhibbits thread_lock(curthread); 290296177Sjhibbits sched_unbind(curthread); 291296177Sjhibbits thread_unlock(curthread); 292296177Sjhibbits 293296177Sjhibbits return (0); 294296177Sjhibbits} 295296177Sjhibbits 296296177Sjhibbitsint 297296177Sjhibbitsbman_pool_fill(t_Handle pool, uint16_t nbufs) 298296177Sjhibbits{ 299296177Sjhibbits struct bman_softc *sc; 300296177Sjhibbits t_Handle portal; 301296177Sjhibbits int error; 302296177Sjhibbits 303296177Sjhibbits sc = bman_sc; 304296177Sjhibbits sched_pin(); 305296177Sjhibbits 306296177Sjhibbits portal = bman_portal_setup(sc); 307296177Sjhibbits if (portal == NULL) { 308296177Sjhibbits sched_unpin(); 309296177Sjhibbits return (EIO); 310296177Sjhibbits } 311296177Sjhibbits 312296177Sjhibbits error = BM_POOL_FillBufs(pool, portal, nbufs); 313296177Sjhibbits 314296177Sjhibbits sched_unpin(); 315296177Sjhibbits 316296177Sjhibbits return ((error == E_OK) ? 0 : EIO); 317296177Sjhibbits} 318296177Sjhibbits 319296177Sjhibbitsvoid * 320296177Sjhibbitsbman_get_buffer(t_Handle pool) 321296177Sjhibbits{ 322296177Sjhibbits struct bman_softc *sc; 323296177Sjhibbits t_Handle portal; 324296177Sjhibbits void *buffer; 325296177Sjhibbits 326296177Sjhibbits sc = bman_sc; 327296177Sjhibbits sched_pin(); 328296177Sjhibbits 329296177Sjhibbits portal = bman_portal_setup(sc); 330296177Sjhibbits if (portal == NULL) { 331296177Sjhibbits sched_unpin(); 332296177Sjhibbits return (NULL); 333296177Sjhibbits } 334296177Sjhibbits 335296177Sjhibbits buffer = BM_POOL_GetBuf(pool, portal); 336296177Sjhibbits 337296177Sjhibbits sched_unpin(); 338296177Sjhibbits 339296177Sjhibbits return (buffer); 340296177Sjhibbits} 341296177Sjhibbits 342296177Sjhibbitsint 343296177Sjhibbitsbman_put_buffer(t_Handle pool, void *buffer) 344296177Sjhibbits{ 345296177Sjhibbits struct bman_softc *sc; 346296177Sjhibbits t_Handle portal; 347296177Sjhibbits int error; 348296177Sjhibbits 349296177Sjhibbits sc = bman_sc; 350296177Sjhibbits sched_pin(); 351296177Sjhibbits 352296177Sjhibbits portal = bman_portal_setup(sc); 353296177Sjhibbits if (portal == NULL) { 354296177Sjhibbits sched_unpin(); 355296177Sjhibbits return (EIO); 356296177Sjhibbits } 357296177Sjhibbits 358296177Sjhibbits error = BM_POOL_PutBuf(pool, portal, buffer); 359296177Sjhibbits 360296177Sjhibbits sched_unpin(); 361296177Sjhibbits 362296177Sjhibbits return ((error == E_OK) ? 0 : EIO); 363296177Sjhibbits} 364296177Sjhibbits 365296177Sjhibbitsuint32_t 366296177Sjhibbitsbman_count(t_Handle pool) 367296177Sjhibbits{ 368296177Sjhibbits 369296177Sjhibbits return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT)); 370296177Sjhibbits} 371