/* * Destroy the shared data structures of a vmxnet3s device. */ static void vmxnet3s_destroy_drivershared(vmxnet3s_softc_t *dp) { VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_DSAL, 0); VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_DSAH, 0); vmxnet3s_free(&dp->qdescs); vmxnet3s_free(&dp->shareddata); }
/* * Destroy the rx queue of a vmxnet3s device. */ static void vmxnet3s_destroy_rxq(vmxnet3s_softc_t *dp) { vmxnet3s_rxq_t *rxq = &dp->rxq; ASSERT(rxq->bufring); ASSERT(rxq->cmdring.dma.buf && rxq->compring.dma.buf); vmxnet3s_rxq_fini(dp, rxq); kmem_free(rxq->bufring, rxq->cmdring.size * sizeof (vmxnet3s_bufdesc_t)); vmxnet3s_free(&rxq->cmdring.dma); vmxnet3s_free(&rxq->compring.dma); }
/* * Allocate and initialize the shared data structures * of a vmxnet3s device. */ static int vmxnet3s_prepare_drivershared(vmxnet3s_softc_t *dp) { vmxnet3s_drvshared_t *ds; size_t allocsz = sizeof (vmxnet3s_drvshared_t); if (vmxnet3s_alloc1(dp, &dp->shareddata, allocsz, B_TRUE) != DDI_SUCCESS) return (DDI_FAILURE); ds = VMXNET3_DS(dp); (void) memset(ds, 0, allocsz); allocsz = sizeof (vmxnet3s_txqdesc_t) + sizeof (vmxnet3s_rxqdesc_t); if (vmxnet3s_alloc128(dp, &dp->qdescs, allocsz, B_TRUE) != DDI_SUCCESS) { vmxnet3s_free(&dp->shareddata); return (DDI_FAILURE); } (void) memset(dp->qdescs.buf, 0, allocsz); ds->magic = VMXNET3_REV1_MAGIC; /* Take care of most of devread */ ds->devread.misc.drvinfo.version = BUILD_NUMBER_NUMERIC; if (sizeof (void *) == 4) ds->devread.misc.drvinfo.gos.gosbits = VMXNET3_GOS_BITS_32; else if (sizeof (void *) == 8) ds->devread.misc.drvinfo.gos.gosbits = VMXNET3_GOS_BITS_64; else ASSERT(B_FALSE); ds->devread.misc.drvinfo.gos.gostype = VMXNET3_GOS_TYPE_SOLARIS; ds->devread.misc.drvinfo.gos.gosver = 10; ds->devread.misc.drvinfo.vmxnet3srevspt = 1; ds->devread.misc.drvinfo.uptverspt = 1; ds->devread.misc.uptfeatures = UPT1_F_RXCSUM; ds->devread.misc.mtu = dp->cur_mtu; /* XXX ds->devread.misc.maxnumrxsg */ ds->devread.misc.numtxq = 1; ds->devread.misc.numrxq = 1; ds->devread.misc.queuedescpa = dp->qdescs.bufpa; ds->devread.misc.queuedesclen = allocsz; /* txq and rxq information is filled in other functions */ ds->devread.intrconf.automask = (dp->intrmaskmode == VMXNET3_IMM_AUTO); ds->devread.intrconf.numintrs = 1; /* XXX ds->intr.modlevels */ ds->devread.intrconf.eventintridx = 0; VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_DSAL, VMXNET3_ADDR_LO(dp->shareddata.bufpa)); VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_DSAH, VMXNET3_ADDR_HI(dp->shareddata.bufpa)); return (DDI_SUCCESS); }
/* * Initialize the tx queue of a vmxnet3s device. */ static int vmxnet3s_prepare_txq(vmxnet3s_softc_t *dp) { vmxnet3s_txqdesc_t *tqdesc = VMXNET3_TQDESC(dp); vmxnet3s_txq_t *txq = &dp->txq; ASSERT(!(txq->cmdring.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!(txq->compring.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!txq->cmdring.dma.buf && !txq->compring.dma.buf); if (vmxnet3s_alloc_cmdring(dp, &txq->cmdring) != DDI_SUCCESS) goto error; tqdesc->conf.txringbasepa = txq->cmdring.dma.bufpa; tqdesc->conf.txringsize = txq->cmdring.size; tqdesc->conf.dataringbasepa = 0; tqdesc->conf.dataringsize = 0; if (vmxnet3s_alloc_compring(dp, &txq->compring) != DDI_SUCCESS) goto error_cmdring; tqdesc->conf.compringbasepa = txq->compring.dma.bufpa; tqdesc->conf.compringsize = txq->compring.size; txq->metaring = kmem_zalloc(txq->cmdring.size * sizeof (vmxnet3s_metatx_t), KM_SLEEP); if (vmxnet3s_txcache_init(dp, txq) != DDI_SUCCESS) goto error_mpring; if (vmxnet3s_txq_init(dp, txq) != DDI_SUCCESS) goto error_txcache; return (DDI_SUCCESS); error_txcache: vmxnet3s_txcache_release(dp); error_mpring: kmem_free(txq->metaring, txq->cmdring.size * sizeof (vmxnet3s_metatx_t)); vmxnet3s_free(&txq->compring.dma); error_cmdring: vmxnet3s_free(&txq->cmdring.dma); error: return (DDI_FAILURE); }
/* * Destroy the tx queue of a vmxnet3s device. */ static void vmxnet3s_destroy_txq(vmxnet3s_softc_t *dp) { vmxnet3s_txq_t *txq = &dp->txq; ASSERT(txq->metaring); ASSERT(txq->cmdring.dma.buf && txq->compring.dma.buf); vmxnet3s_txq_fini(dp, txq); kmem_free(txq->metaring, txq->cmdring.size * sizeof (vmxnet3s_metatx_t)); vmxnet3s_free(&txq->cmdring.dma); vmxnet3s_free(&txq->compring.dma); vmxnet3s_txcache_release(dp); }
/* * Initialize the rx queue of a vmxnet3s device. */ static int vmxnet3s_prepare_rxq(vmxnet3s_softc_t *dp) { vmxnet3s_rxqdesc_t *rqdesc = VMXNET3_RQDESC(dp); vmxnet3s_rxq_t *rxq = &dp->rxq; ASSERT(!(rxq->cmdring.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!(rxq->compring.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!rxq->cmdring.dma.buf && !rxq->compring.dma.buf); if (vmxnet3s_alloc_cmdring(dp, &rxq->cmdring) != DDI_SUCCESS) goto error; rqdesc->conf.rxringbasepa[0] = rxq->cmdring.dma.bufpa; rqdesc->conf.rxringsize[0] = rxq->cmdring.size; rqdesc->conf.rxringbasepa[1] = 0; rqdesc->conf.rxringsize[1] = 0; if (vmxnet3s_alloc_compring(dp, &rxq->compring) != DDI_SUCCESS) goto error_cmdring; rqdesc->conf.compringbasepa = rxq->compring.dma.bufpa; rqdesc->conf.compringsize = rxq->compring.size; rxq->bufring = kmem_zalloc(rxq->cmdring.size * sizeof (vmxnet3s_bufdesc_t), KM_SLEEP); if (vmxnet3s_rxq_init(dp, rxq) != DDI_SUCCESS) goto error_bufring; return (DDI_SUCCESS); error_bufring: kmem_free(rxq->bufring, rxq->cmdring.size * sizeof (vmxnet3s_bufdesc_t)); vmxnet3s_free(&rxq->compring.dma); error_cmdring: vmxnet3s_free(&rxq->cmdring.dma); error: return (DDI_FAILURE); }
/* * Free rxbuf. */ static void vmxnet3s_free_rxbuf(vmxnet3s_softc_t *dp, vmxnet3s_rxbuf_t *rxbuf) { vmxnet3s_free(&rxbuf->dma); kmem_free(rxbuf, sizeof (vmxnet3s_rxbuf_t)); #ifndef DEBUG atomic_dec_32(&dp->rxnumbufs); #else { uint32_t nv = atomic_dec_32_nv(&dp->rxnumbufs); ASSERT(nv != (uint32_t)-1); } #endif }