1296177Sjhibbits/*- 2296177Sjhibbits * Copyright (c) 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/module.h> 34296177Sjhibbits#include <sys/bus.h> 35296177Sjhibbits#include <sys/rman.h> 36296177Sjhibbits#include <sys/malloc.h> 37296177Sjhibbits#include <sys/mbuf.h> 38296177Sjhibbits#include <sys/socket.h> 39296177Sjhibbits#include <sys/sysctl.h> 40296177Sjhibbits#include <sys/sockio.h> 41296177Sjhibbits 42296177Sjhibbits#include <net/ethernet.h> 43296177Sjhibbits#include <net/if.h> 44296177Sjhibbits#include <net/if_dl.h> 45296177Sjhibbits#include <net/if_media.h> 46296177Sjhibbits#include <net/if_types.h> 47296177Sjhibbits#include <net/if_arp.h> 48296177Sjhibbits 49296177Sjhibbits#include <dev/mii/mii.h> 50296177Sjhibbits#include <dev/mii/miivar.h> 51296177Sjhibbits 52296177Sjhibbits#include "miibus_if.h" 53296177Sjhibbits 54296177Sjhibbits#include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h> 55296177Sjhibbits#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h> 56296177Sjhibbits#include <contrib/ncsw/inc/xx_ext.h> 57296177Sjhibbits 58296177Sjhibbits#include "fman.h" 59296177Sjhibbits#include "bman.h" 60296177Sjhibbits#include "qman.h" 61296177Sjhibbits#include "if_dtsec.h" 62296177Sjhibbits#include "if_dtsec_rm.h" 63296177Sjhibbits 64296177Sjhibbits 65296177Sjhibbits/** 66296177Sjhibbits * @group dTSEC RM private defines. 67296177Sjhibbits * @{ 68296177Sjhibbits */ 69296177Sjhibbits#define DTSEC_BPOOLS_USED (1) 70296177Sjhibbits#define DTSEC_MAX_TX_QUEUE_LEN 256 71296177Sjhibbits 72296177Sjhibbitsstruct dtsec_rm_frame_info { 73296177Sjhibbits struct mbuf *fi_mbuf; 74296177Sjhibbits t_DpaaSGTE fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY]; 75296177Sjhibbits}; 76296177Sjhibbits 77296177Sjhibbitsenum dtsec_rm_pool_params { 78296177Sjhibbits DTSEC_RM_POOL_RX_LOW_MARK = 16, 79296177Sjhibbits DTSEC_RM_POOL_RX_HIGH_MARK = 64, 80296177Sjhibbits DTSEC_RM_POOL_RX_MAX_SIZE = 256, 81296177Sjhibbits 82296177Sjhibbits DTSEC_RM_POOL_FI_LOW_MARK = 16, 83296177Sjhibbits DTSEC_RM_POOL_FI_HIGH_MARK = 64, 84296177Sjhibbits DTSEC_RM_POOL_FI_MAX_SIZE = 256, 85296177Sjhibbits}; 86296177Sjhibbits 87296177Sjhibbitsenum dtsec_rm_fqr_params { 88296177Sjhibbits DTSEC_RM_FQR_RX_CHANNEL = e_QM_FQ_CHANNEL_POOL1, 89296177Sjhibbits DTSEC_RM_FQR_RX_WQ = 1, 90296177Sjhibbits DTSEC_RM_FQR_TX_CONF_CHANNEL = e_QM_FQ_CHANNEL_SWPORTAL0, 91296177Sjhibbits DTSEC_RM_FQR_TX_WQ = 1, 92296177Sjhibbits DTSEC_RM_FQR_TX_CONF_WQ = 1 93296177Sjhibbits}; 94296177Sjhibbits/** @} */ 95296177Sjhibbits 96296177Sjhibbits 97296177Sjhibbits/** 98296177Sjhibbits * @group dTSEC Frame Info routines. 99296177Sjhibbits * @{ 100296177Sjhibbits */ 101296177Sjhibbitsvoid 102296177Sjhibbitsdtsec_rm_fi_pool_free(struct dtsec_softc *sc) 103296177Sjhibbits{ 104296177Sjhibbits 105296177Sjhibbits if (sc->sc_fi_zone != NULL) 106296177Sjhibbits uma_zdestroy(sc->sc_fi_zone); 107296177Sjhibbits} 108296177Sjhibbits 109296177Sjhibbitsint 110296177Sjhibbitsdtsec_rm_fi_pool_init(struct dtsec_softc *sc) 111296177Sjhibbits{ 112296177Sjhibbits 113296177Sjhibbits snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info", 114296177Sjhibbits device_get_nameunit(sc->sc_dev)); 115296177Sjhibbits 116296177Sjhibbits sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname, 117296177Sjhibbits sizeof(struct dtsec_rm_frame_info), NULL, NULL, NULL, NULL, 118296177Sjhibbits sizeof(void *), 0); 119296177Sjhibbits if (sc->sc_fi_zone == NULL) 120296177Sjhibbits return (EIO); 121296177Sjhibbits 122296177Sjhibbits return (0); 123296177Sjhibbits} 124296177Sjhibbits 125296177Sjhibbitsstatic struct dtsec_rm_frame_info * 126296177Sjhibbitsdtsec_rm_fi_alloc(struct dtsec_softc *sc) 127296177Sjhibbits{ 128296177Sjhibbits struct dtsec_rm_frame_info *fi; 129296177Sjhibbits 130296177Sjhibbits fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT); 131296177Sjhibbits 132296177Sjhibbits return (fi); 133296177Sjhibbits} 134296177Sjhibbits 135296177Sjhibbitsstatic void 136296177Sjhibbitsdtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi) 137296177Sjhibbits{ 138296177Sjhibbits 139296177Sjhibbits XX_UntrackAddress(fi); 140296177Sjhibbits uma_zfree(sc->sc_fi_zone, fi); 141296177Sjhibbits} 142296177Sjhibbits/** @} */ 143296177Sjhibbits 144296177Sjhibbits 145296177Sjhibbits/** 146296177Sjhibbits * @group dTSEC FMan PORT routines. 147296177Sjhibbits * @{ 148296177Sjhibbits */ 149296177Sjhibbitsint 150296177Sjhibbitsdtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit) 151296177Sjhibbits{ 152296177Sjhibbits t_FmPortParams params; 153296177Sjhibbits t_FmPortRxParams *rx_params; 154296177Sjhibbits t_FmPortExtPools *pool_params; 155296177Sjhibbits t_Error error; 156296177Sjhibbits 157296177Sjhibbits memset(¶ms, 0, sizeof(params)); 158296177Sjhibbits 159296177Sjhibbits params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id; 160296177Sjhibbits params.h_Fm = sc->sc_fmh; 161296177Sjhibbits params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type); 162296177Sjhibbits params.portId = sc->sc_eth_id; 163296177Sjhibbits params.independentModeEnable = FALSE; 164296177Sjhibbits params.liodnBase = FM_PORT_LIODN_BASE; 165296177Sjhibbits params.f_Exception = dtsec_fm_port_rx_exception_callback; 166296177Sjhibbits params.h_App = sc; 167296177Sjhibbits 168296177Sjhibbits rx_params = ¶ms.specificParams.rxParams; 169296177Sjhibbits rx_params->errFqid = sc->sc_rx_fqid; 170296177Sjhibbits rx_params->dfltFqid = sc->sc_rx_fqid; 171296177Sjhibbits rx_params->liodnOffset = 0; 172296177Sjhibbits 173296177Sjhibbits pool_params = &rx_params->extBufPools; 174296177Sjhibbits pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED; 175296177Sjhibbits pool_params->extBufPool->id = sc->sc_rx_bpid; 176296177Sjhibbits pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE; 177296177Sjhibbits 178296177Sjhibbits sc->sc_rxph = FM_PORT_Config(¶ms); 179296177Sjhibbits if (sc->sc_rxph == NULL) { 180296177Sjhibbits device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n"); 181296177Sjhibbits return (ENXIO); 182296177Sjhibbits } 183296177Sjhibbits 184296177Sjhibbits error = FM_PORT_Init(sc->sc_rxph); 185296177Sjhibbits if (error != E_OK) { 186296177Sjhibbits device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n"); 187296177Sjhibbits FM_PORT_Free(sc->sc_rxph); 188296177Sjhibbits return (ENXIO); 189296177Sjhibbits } 190296177Sjhibbits 191296177Sjhibbits if (bootverbose) 192296177Sjhibbits device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n", 193296177Sjhibbits sc->sc_port_rx_hw_id); 194296177Sjhibbits 195296177Sjhibbits return (0); 196296177Sjhibbits} 197296177Sjhibbits 198296177Sjhibbitsint 199296177Sjhibbitsdtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit) 200296177Sjhibbits{ 201296177Sjhibbits t_FmPortParams params; 202296177Sjhibbits t_FmPortNonRxParams *tx_params; 203296177Sjhibbits t_Error error; 204296177Sjhibbits 205296177Sjhibbits memset(¶ms, 0, sizeof(params)); 206296177Sjhibbits 207296177Sjhibbits params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id; 208296177Sjhibbits params.h_Fm = sc->sc_fmh; 209296177Sjhibbits params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type); 210296177Sjhibbits params.portId = sc->sc_eth_id; 211296177Sjhibbits params.independentModeEnable = FALSE; 212296177Sjhibbits params.liodnBase = FM_PORT_LIODN_BASE; 213296177Sjhibbits params.f_Exception = dtsec_fm_port_tx_exception_callback; 214296177Sjhibbits params.h_App = sc; 215296177Sjhibbits 216296177Sjhibbits tx_params = ¶ms.specificParams.nonRxParams; 217296177Sjhibbits tx_params->errFqid = sc->sc_tx_conf_fqid; 218296177Sjhibbits tx_params->dfltFqid = sc->sc_tx_conf_fqid; 219296177Sjhibbits tx_params->qmChannel = sc->sc_port_tx_qman_chan; 220296177Sjhibbits#ifdef FM_OP_PARTITION_ERRATA_FMANx8 221296177Sjhibbits tx_params->opLiodnOffset = 0; 222296177Sjhibbits#endif 223296177Sjhibbits 224296177Sjhibbits sc->sc_txph = FM_PORT_Config(¶ms); 225296177Sjhibbits if (sc->sc_txph == NULL) { 226296177Sjhibbits device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n"); 227296177Sjhibbits return (ENXIO); 228296177Sjhibbits } 229296177Sjhibbits 230296177Sjhibbits error = FM_PORT_Init(sc->sc_txph); 231296177Sjhibbits if (error != E_OK) { 232296177Sjhibbits device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n"); 233296177Sjhibbits FM_PORT_Free(sc->sc_txph); 234296177Sjhibbits return (ENXIO); 235296177Sjhibbits } 236296177Sjhibbits 237296177Sjhibbits if (bootverbose) 238296177Sjhibbits device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n", 239296177Sjhibbits sc->sc_port_tx_hw_id); 240296177Sjhibbits 241296177Sjhibbits return (0); 242296177Sjhibbits} 243296177Sjhibbits/** @} */ 244296177Sjhibbits 245296177Sjhibbits 246296177Sjhibbits/** 247296177Sjhibbits * @group dTSEC buffer pools routines. 248296177Sjhibbits * @{ 249296177Sjhibbits */ 250296177Sjhibbitsstatic t_Error 251296177Sjhibbitsdtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer, 252296177Sjhibbits t_Handle context) 253296177Sjhibbits{ 254296177Sjhibbits struct dtsec_softc *sc; 255296177Sjhibbits 256296177Sjhibbits sc = h_BufferPool; 257296177Sjhibbits uma_zfree(sc->sc_rx_zone, buffer); 258296177Sjhibbits 259296177Sjhibbits return (E_OK); 260296177Sjhibbits} 261296177Sjhibbits 262296177Sjhibbitsstatic uint8_t * 263296177Sjhibbitsdtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context) 264296177Sjhibbits{ 265296177Sjhibbits struct dtsec_softc *sc; 266296177Sjhibbits uint8_t *buffer; 267296177Sjhibbits 268296177Sjhibbits sc = h_BufferPool; 269296177Sjhibbits buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT); 270296177Sjhibbits 271296177Sjhibbits return (buffer); 272296177Sjhibbits} 273296177Sjhibbits 274296177Sjhibbitsstatic void 275296177Sjhibbitsdtsec_rm_pool_rx_depleted(t_Handle h_App, bool in) 276296177Sjhibbits{ 277296177Sjhibbits struct dtsec_softc *sc; 278296177Sjhibbits unsigned int count; 279296177Sjhibbits 280296177Sjhibbits sc = h_App; 281296177Sjhibbits 282296177Sjhibbits if (!in) 283296177Sjhibbits return; 284296177Sjhibbits 285296177Sjhibbits while (1) { 286296177Sjhibbits count = bman_count(sc->sc_rx_pool); 287296177Sjhibbits if (count > DTSEC_RM_POOL_RX_HIGH_MARK) 288296177Sjhibbits return; 289296177Sjhibbits 290296177Sjhibbits bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK); 291296177Sjhibbits } 292296177Sjhibbits} 293296177Sjhibbits 294296177Sjhibbitsvoid 295296177Sjhibbitsdtsec_rm_pool_rx_free(struct dtsec_softc *sc) 296296177Sjhibbits{ 297296177Sjhibbits 298296177Sjhibbits if (sc->sc_rx_pool != NULL) 299296177Sjhibbits bman_pool_destroy(sc->sc_rx_pool); 300296177Sjhibbits 301296177Sjhibbits if (sc->sc_rx_zone != NULL) 302296177Sjhibbits uma_zdestroy(sc->sc_rx_zone); 303296177Sjhibbits} 304296177Sjhibbits 305296177Sjhibbitsint 306296177Sjhibbitsdtsec_rm_pool_rx_init(struct dtsec_softc *sc) 307296177Sjhibbits{ 308296177Sjhibbits 309296177Sjhibbits /* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */ 310296177Sjhibbits CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE); 311296177Sjhibbits 312296177Sjhibbits snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers", 313296177Sjhibbits device_get_nameunit(sc->sc_dev)); 314296177Sjhibbits 315296177Sjhibbits sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL, 316296177Sjhibbits NULL, NULL, NULL, FM_PORT_BUFFER_SIZE, 0); 317296177Sjhibbits if (sc->sc_rx_zone == NULL) 318296177Sjhibbits return (EIO); 319296177Sjhibbits 320296177Sjhibbits sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE, 321296177Sjhibbits 0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer, 322296177Sjhibbits dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK, 323296177Sjhibbits DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL, 324296177Sjhibbits NULL); 325296177Sjhibbits if (sc->sc_rx_pool == NULL) { 326296177Sjhibbits dtsec_rm_pool_rx_free(sc); 327296177Sjhibbits return (EIO); 328296177Sjhibbits } 329296177Sjhibbits 330296177Sjhibbits return (0); 331296177Sjhibbits} 332296177Sjhibbits/** @} */ 333296177Sjhibbits 334296177Sjhibbits 335296177Sjhibbits/** 336296177Sjhibbits * @group dTSEC Frame Queue Range routines. 337296177Sjhibbits * @{ 338296177Sjhibbits */ 339296177Sjhibbitsstatic void 340296177Sjhibbitsdtsec_rm_fqr_mext_free(struct mbuf *m, void *buffer, void *arg) 341296177Sjhibbits{ 342296177Sjhibbits struct dtsec_softc *sc; 343296177Sjhibbits 344296177Sjhibbits sc = arg; 345296177Sjhibbits if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE) 346296177Sjhibbits bman_put_buffer(sc->sc_rx_pool, buffer); 347296177Sjhibbits else 348296177Sjhibbits dtsec_rm_pool_rx_put_buffer(arg, buffer, NULL); 349296177Sjhibbits} 350296177Sjhibbits 351296177Sjhibbitsstatic e_RxStoreResponse 352296177Sjhibbitsdtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal, 353296177Sjhibbits uint32_t fqid_off, t_DpaaFD *frame) 354296177Sjhibbits{ 355296177Sjhibbits struct dtsec_softc *sc; 356296177Sjhibbits struct mbuf *m; 357296177Sjhibbits 358296177Sjhibbits m = NULL; 359296177Sjhibbits sc = app; 360296177Sjhibbits 361296177Sjhibbits KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF, 362296177Sjhibbits ("%s(): Got unsupported frame format 0x%02X!", __func__, 363296177Sjhibbits DPAA_FD_GET_FORMAT(frame))); 364296177Sjhibbits 365296177Sjhibbits KASSERT(DPAA_FD_GET_OFFSET(frame) == 0, 366296177Sjhibbits ("%s(): Only offset 0 is supported!", __func__)); 367296177Sjhibbits 368296177Sjhibbits if (DPAA_FD_GET_STATUS(frame) != 0) { 369296177Sjhibbits device_printf(sc->sc_dev, "RX error: 0x%08X\n", 370296177Sjhibbits DPAA_FD_GET_STATUS(frame)); 371296177Sjhibbits goto err; 372296177Sjhibbits } 373296177Sjhibbits 374296177Sjhibbits m = m_gethdr(M_NOWAIT, MT_HEADER); 375296177Sjhibbits if (m == NULL) 376296177Sjhibbits goto err; 377296177Sjhibbits 378296295Sjhibbits m_extadd(m, DPAA_FD_GET_ADDR(frame), FM_PORT_BUFFER_SIZE, 379296177Sjhibbits dtsec_rm_fqr_mext_free, DPAA_FD_GET_ADDR(frame), sc, 0, 380296177Sjhibbits EXT_NET_DRV); 381296177Sjhibbits 382296177Sjhibbits m->m_pkthdr.rcvif = sc->sc_ifnet; 383296177Sjhibbits m->m_len = DPAA_FD_GET_LENGTH(frame); 384296177Sjhibbits m_fixhdr(m); 385296177Sjhibbits 386296177Sjhibbits (*sc->sc_ifnet->if_input)(sc->sc_ifnet, m); 387296177Sjhibbits 388296177Sjhibbits return (e_RX_STORE_RESPONSE_CONTINUE); 389296177Sjhibbits 390296177Sjhibbitserr: 391296177Sjhibbits bman_put_buffer(sc->sc_rx_pool, DPAA_FD_GET_ADDR(frame)); 392296177Sjhibbits if (m != NULL) 393296177Sjhibbits m_freem(m); 394296177Sjhibbits 395296177Sjhibbits return (e_RX_STORE_RESPONSE_CONTINUE); 396296177Sjhibbits} 397296177Sjhibbits 398296177Sjhibbitsstatic e_RxStoreResponse 399296177Sjhibbitsdtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal, 400296177Sjhibbits uint32_t fqid_off, t_DpaaFD *frame) 401296177Sjhibbits{ 402296177Sjhibbits struct dtsec_rm_frame_info *fi; 403296177Sjhibbits struct dtsec_softc *sc; 404296177Sjhibbits unsigned int qlen; 405296177Sjhibbits t_DpaaSGTE *sgt0; 406296177Sjhibbits 407296177Sjhibbits sc = app; 408296177Sjhibbits 409296177Sjhibbits if (DPAA_FD_GET_STATUS(frame) != 0) 410296177Sjhibbits device_printf(sc->sc_dev, "TX error: 0x%08X\n", 411296177Sjhibbits DPAA_FD_GET_STATUS(frame)); 412296177Sjhibbits 413296177Sjhibbits /* 414296177Sjhibbits * We are storing struct dtsec_rm_frame_info in first entry 415296177Sjhibbits * of scatter-gather table. 416296177Sjhibbits */ 417296177Sjhibbits sgt0 = DPAA_FD_GET_ADDR(frame); 418296177Sjhibbits fi = DPAA_SGTE_GET_ADDR(sgt0); 419296177Sjhibbits 420296177Sjhibbits /* Free transmitted frame */ 421296177Sjhibbits m_freem(fi->fi_mbuf); 422296177Sjhibbits dtsec_rm_fi_free(sc, fi); 423296177Sjhibbits 424296177Sjhibbits qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0, 425296177Sjhibbits e_QM_FQR_COUNTERS_FRAME); 426296177Sjhibbits 427296177Sjhibbits if (qlen == 0) { 428296177Sjhibbits DTSEC_LOCK(sc); 429296177Sjhibbits 430296177Sjhibbits if (sc->sc_tx_fqr_full) { 431296177Sjhibbits sc->sc_tx_fqr_full = 0; 432296177Sjhibbits dtsec_rm_if_start_locked(sc); 433296177Sjhibbits } 434296177Sjhibbits 435296177Sjhibbits DTSEC_UNLOCK(sc); 436296177Sjhibbits } 437296177Sjhibbits 438296177Sjhibbits return (e_RX_STORE_RESPONSE_CONTINUE); 439296177Sjhibbits} 440296177Sjhibbits 441296177Sjhibbitsvoid 442296177Sjhibbitsdtsec_rm_fqr_rx_free(struct dtsec_softc *sc) 443296177Sjhibbits{ 444296177Sjhibbits 445296177Sjhibbits if (sc->sc_rx_fqr) 446296177Sjhibbits qman_fqr_free(sc->sc_rx_fqr); 447296177Sjhibbits} 448296177Sjhibbits 449296177Sjhibbitsint 450296177Sjhibbitsdtsec_rm_fqr_rx_init(struct dtsec_softc *sc) 451296177Sjhibbits{ 452296177Sjhibbits t_Error error; 453296177Sjhibbits t_Handle fqr; 454296177Sjhibbits 455296177Sjhibbits /* Default Frame Queue */ 456296177Sjhibbits fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ, 457296177Sjhibbits FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0, 0); 458296177Sjhibbits if (fqr == NULL) { 459296177Sjhibbits device_printf(sc->sc_dev, "could not create default RX queue" 460296177Sjhibbits "\n"); 461296177Sjhibbits return (EIO); 462296177Sjhibbits } 463296177Sjhibbits 464296177Sjhibbits sc->sc_rx_fqr = fqr; 465296177Sjhibbits sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr); 466296177Sjhibbits 467296177Sjhibbits error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc); 468296177Sjhibbits if (error != E_OK) { 469296177Sjhibbits device_printf(sc->sc_dev, "could not register RX callback\n"); 470296177Sjhibbits dtsec_rm_fqr_rx_free(sc); 471296177Sjhibbits return (EIO); 472296177Sjhibbits } 473296177Sjhibbits 474296177Sjhibbits return (0); 475296177Sjhibbits} 476296177Sjhibbits 477296177Sjhibbitsvoid 478296177Sjhibbitsdtsec_rm_fqr_tx_free(struct dtsec_softc *sc) 479296177Sjhibbits{ 480296177Sjhibbits 481296177Sjhibbits if (sc->sc_tx_fqr) 482296177Sjhibbits qman_fqr_free(sc->sc_tx_fqr); 483296177Sjhibbits 484296177Sjhibbits if (sc->sc_tx_conf_fqr) 485296177Sjhibbits qman_fqr_free(sc->sc_tx_conf_fqr); 486296177Sjhibbits} 487296177Sjhibbits 488296177Sjhibbitsint 489296177Sjhibbitsdtsec_rm_fqr_tx_init(struct dtsec_softc *sc) 490296177Sjhibbits{ 491296177Sjhibbits t_Error error; 492296177Sjhibbits t_Handle fqr; 493296177Sjhibbits 494296177Sjhibbits /* TX Frame Queue */ 495296177Sjhibbits fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan, 496296177Sjhibbits DTSEC_RM_FQR_TX_WQ, FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0, 0); 497296177Sjhibbits if (fqr == NULL) { 498296177Sjhibbits device_printf(sc->sc_dev, "could not create default TX queue" 499296177Sjhibbits "\n"); 500296177Sjhibbits return (EIO); 501296177Sjhibbits } 502296177Sjhibbits 503296177Sjhibbits sc->sc_tx_fqr = fqr; 504296177Sjhibbits 505296177Sjhibbits /* TX Confirmation Frame Queue */ 506296177Sjhibbits fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL, 507296177Sjhibbits DTSEC_RM_FQR_TX_CONF_WQ, FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0, 508296177Sjhibbits 0); 509296177Sjhibbits if (fqr == NULL) { 510296177Sjhibbits device_printf(sc->sc_dev, "could not create TX confirmation " 511296177Sjhibbits "queue\n"); 512296177Sjhibbits dtsec_rm_fqr_tx_free(sc); 513296177Sjhibbits return (EIO); 514296177Sjhibbits } 515296177Sjhibbits 516296177Sjhibbits sc->sc_tx_conf_fqr = fqr; 517296177Sjhibbits sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr); 518296177Sjhibbits 519296177Sjhibbits error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc); 520296177Sjhibbits if (error != E_OK) { 521296177Sjhibbits device_printf(sc->sc_dev, "could not register TX confirmation " 522296177Sjhibbits "callback\n"); 523296177Sjhibbits dtsec_rm_fqr_tx_free(sc); 524296177Sjhibbits return (EIO); 525296177Sjhibbits } 526296177Sjhibbits 527296177Sjhibbits return (0); 528296177Sjhibbits} 529296177Sjhibbits/** @} */ 530296177Sjhibbits 531296177Sjhibbits 532296177Sjhibbits/** 533296177Sjhibbits * @group dTSEC IFnet routines. 534296177Sjhibbits * @{ 535296177Sjhibbits */ 536296177Sjhibbitsvoid 537296177Sjhibbitsdtsec_rm_if_start_locked(struct dtsec_softc *sc) 538296177Sjhibbits{ 539296177Sjhibbits vm_size_t dsize, psize, ssize; 540296177Sjhibbits struct dtsec_rm_frame_info *fi; 541296177Sjhibbits unsigned int qlen, i; 542296177Sjhibbits struct mbuf *m0, *m; 543296177Sjhibbits vm_offset_t vaddr; 544296177Sjhibbits vm_paddr_t paddr; 545296177Sjhibbits t_DpaaFD fd; 546296177Sjhibbits 547296177Sjhibbits DTSEC_LOCK_ASSERT(sc); 548296177Sjhibbits /* TODO: IFF_DRV_OACTIVE */ 549296177Sjhibbits 550296177Sjhibbits if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0) 551296177Sjhibbits return; 552296177Sjhibbits 553296177Sjhibbits if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING) 554296177Sjhibbits return; 555296177Sjhibbits 556296177Sjhibbits while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) { 557296177Sjhibbits /* Check length of the TX queue */ 558296177Sjhibbits qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0, 559296177Sjhibbits e_QM_FQR_COUNTERS_FRAME); 560296177Sjhibbits 561296177Sjhibbits if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) { 562296177Sjhibbits sc->sc_tx_fqr_full = 1; 563296177Sjhibbits return; 564296177Sjhibbits } 565296177Sjhibbits 566296177Sjhibbits fi = dtsec_rm_fi_alloc(sc); 567296177Sjhibbits if (fi == NULL) 568296177Sjhibbits return; 569296177Sjhibbits 570296177Sjhibbits IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m0); 571296177Sjhibbits if (m0 == NULL) { 572296177Sjhibbits dtsec_rm_fi_free(sc, fi); 573296177Sjhibbits return; 574296177Sjhibbits } 575296177Sjhibbits 576296177Sjhibbits i = 0; 577296177Sjhibbits m = m0; 578296177Sjhibbits psize = 0; 579296177Sjhibbits dsize = 0; 580296177Sjhibbits fi->fi_mbuf = m0; 581296177Sjhibbits while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 582296177Sjhibbits if (m->m_len == 0) 583296177Sjhibbits continue; 584296177Sjhibbits 585296177Sjhibbits /* 586296177Sjhibbits * First entry in scatter-gather table is used to keep 587296177Sjhibbits * pointer to frame info structure. 588296177Sjhibbits */ 589296177Sjhibbits DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi); 590296177Sjhibbits DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0); 591296177Sjhibbits 592296177Sjhibbits DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0); 593296177Sjhibbits DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0); 594296177Sjhibbits DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0); 595296177Sjhibbits DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0); 596296177Sjhibbits i++; 597296177Sjhibbits 598296177Sjhibbits dsize = m->m_len; 599296177Sjhibbits vaddr = (vm_offset_t)m->m_data; 600296177Sjhibbits while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 601296177Sjhibbits paddr = XX_VirtToPhys((void *)vaddr); 602296177Sjhibbits ssize = PAGE_SIZE - (paddr & PAGE_MASK); 603296177Sjhibbits if (m->m_len < ssize) 604296177Sjhibbits ssize = m->m_len; 605296177Sjhibbits 606296177Sjhibbits DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], 607296177Sjhibbits (void *)vaddr); 608296177Sjhibbits DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize); 609296177Sjhibbits 610296177Sjhibbits DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0); 611296177Sjhibbits DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0); 612296177Sjhibbits DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0); 613296177Sjhibbits DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0); 614296177Sjhibbits 615296177Sjhibbits dsize -= ssize; 616296177Sjhibbits vaddr += ssize; 617296177Sjhibbits psize += ssize; 618296177Sjhibbits i++; 619296177Sjhibbits } 620296177Sjhibbits 621296177Sjhibbits if (dsize > 0) 622296177Sjhibbits break; 623296177Sjhibbits 624296177Sjhibbits m = m->m_next; 625296177Sjhibbits } 626296177Sjhibbits 627296177Sjhibbits /* Check if SG table was constructed properly */ 628296177Sjhibbits if (m != NULL || dsize != 0) { 629296177Sjhibbits dtsec_rm_fi_free(sc, fi); 630296177Sjhibbits m_freem(m0); 631296177Sjhibbits continue; 632296177Sjhibbits } 633296177Sjhibbits 634296177Sjhibbits DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1); 635296177Sjhibbits 636296177Sjhibbits DPAA_FD_SET_ADDR(&fd, fi->fi_sgt); 637296177Sjhibbits DPAA_FD_SET_LENGTH(&fd, psize); 638296177Sjhibbits DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF); 639296177Sjhibbits 640296177Sjhibbits DPAA_FD_SET_DD(&fd, 0); 641296177Sjhibbits DPAA_FD_SET_PID(&fd, 0); 642296177Sjhibbits DPAA_FD_SET_BPID(&fd, 0); 643296177Sjhibbits DPAA_FD_SET_OFFSET(&fd, 0); 644296177Sjhibbits DPAA_FD_SET_STATUS(&fd, 0); 645296177Sjhibbits 646296177Sjhibbits DTSEC_UNLOCK(sc); 647296177Sjhibbits if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) { 648296177Sjhibbits dtsec_rm_fi_free(sc, fi); 649296177Sjhibbits m_freem(m0); 650296177Sjhibbits } 651296177Sjhibbits DTSEC_LOCK(sc); 652296177Sjhibbits } 653296177Sjhibbits} 654296177Sjhibbits/** @} */ 655