62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Copyright (C) 2007 VMware, Inc. All rights reserved.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * The contents of this file are subject to the terms of the Common
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Development and Distribution License (the "License") version 1.0
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * and no later version. You may not use this file except in
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * compliance with the License.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * You can obtain a copy of the License at
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * See the License for the specific language governing permissions
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * and limitations under the License.
6849994e8263545ed3c0f6f5676e47b38e14f63eSebastien Roy * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Initialize a TxQueue. Currently nothing needs to be done.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov/* ARGSUSED */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankovvmxnet3_txqueue_init(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq)
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Finish a TxQueue by freeing all pending Tx.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankovvmxnet3_txqueue_fini(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq)
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov unsigned int i;
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Build the offload context of a msg.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * 0 if everything went well.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * +n if n bytes need to be pulled up.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * -1 in case of error (not used).
62dadd654b88164ac263978699c78aa01647a39bYuri Pankovvmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol,
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy uint32_t start, stuff, value, flags, lso_flag, mss;
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov hcksum_retrieve(mp, NULL, NULL, &start, &stuff, NULL, &value, &flags);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov struct ether_vlan_header *eth = (void *) mp->b_rptr;
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_DEBUG(dp, 4, "flags=0x%x, ethLen=%u, start=%u, "
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov "stuff=%u, value=%u\n", flags, ethLen, start, stuff, value);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Copy e1000g's behavior:
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * - Do not assume all the headers are in the same mblk.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * - Assume each header is always within one mblk.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * - Assume the ethernet header is in the first mblk.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Careful, '>' instead of '>=' here */
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Map a msg into the Tx command ring of a vmxnet3 device.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * VMXNET3_TX_OK if everything went well.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * VMXNET3_TX_RINGFULL if the ring is nearly full.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * VMXNET3_TX_PULLUP if the msg is overfragmented.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * VMXNET3_TX_FAILURE if there was a DMA or offload error.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Side effects:
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * The ring is filled if VMXNET3_TX_OK is returned.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankovvmxnet3_tx_one(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq,
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov for (mblk = mp; mblk != NULL; mblk = mblk->b_cont) {
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov if (ddi_dma_addr_bind_handle(dp->txDmaHandle, NULL,
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL,
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_WARN(dp, "ddi_dma_addr_bind_handle() failed\n");
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* txd.addr */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* txd.dw2 */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* txd.dw3 */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Update the EOP descriptor */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov txDesc->dword[3] |= VMXNET3_TXD_CQ | VMXNET3_TXD_EOP;
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Update the SOP descriptor. Must be done last */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov if (ol->om == VMXNET3_OM_TSO && txDesc->txd.len != 0 &&
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Update the meta ring & metadata */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov (totLen - ol->hlen + ol->msscof - 1) / ol->msscof;
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_DEBUG(dp, 3, "tx 0x%p on [%u;%u]\n", mp, sopIdx, eopIdx);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Reverse the generation bits */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_DEC_RING_IDX(cmdRing, cmdRing->next2fill);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov txDesc = VMXNET3_GET_DESC(cmdRing, cmdRing->next2fill);
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Send packets on a vmxnet3 device.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * NULL in case of success or failure.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * The mps to be retransmitted later if the ring is full.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * PR #315560: M_PROTO mblks could be passed for
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * some reason. Drop them because we don't understand
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * them and because their contents are not Ethernet
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * frames anyway.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Prepare the offload while we're still handling the original
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * message -- msgpullup() discards the metadata afterwards.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov pullup = vmxnet3_tx_prepare_offload(dp, &ol, mp);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Try to map the message in the Tx ring.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * This call might fail for non-fatal reasons.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * Try one more time after flattening
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov * the message with msgpullup().
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov if (status != VMXNET3_TX_OK && status != VMXNET3_TX_RINGFULL) {
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Fatal failure, drop it */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov /* Notify the device */
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov if (txqCtrl->txNumDeferred >= txqCtrl->txThreshold) {
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_BAR0_PUT32(dp, VMXNET3_REG_TXPROD, cmdRing->next2fill);
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * Parse a transmit queue and complete packets.
ca5345b6a28e9e9bfd0c135121d62c6b35a5390dSebastien Roy * B_TRUE if Tx must be updated or B_FALSE if no action is required.
62dadd654b88164ac263978699c78aa01647a39bYuri Pankovvmxnet3_tx_complete(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq)
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov compDesc = VMXNET3_GET_DESC(compRing, compRing->next2comp);
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_DEBUG(dp, 3, "cp 0x%p on [%u;%u]\n", mp, sopIdx,
62dadd654b88164ac263978699c78aa01647a39bYuri Pankov VMXNET3_INC_RING_IDX(compRing, compRing->next2comp);