/*
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
*
* See the License for the specific language governing permissions
* and limitations under the License.
*/
/*
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
*/
#include <vmxnet3.h>
typedef enum vmxnet3_txstatus {
typedef struct vmxnet3_offload_t {
/*
* Initialize a TxQueue. Currently nothing needs to be done.
*/
/* ARGSUSED */
int
{
return (0);
}
/*
* Finish a TxQueue by freeing all pending Tx.
*/
void
{
unsigned int i;
if (mp) {
}
}
}
/*
* Build the offload context of a msg.
*
* Returns:
* 0 if everything went well.
* +n if n bytes need to be pulled up.
* -1 in case of error (not used).
*/
static int
{
int ret = 0;
ethLen = sizeof (struct ether_vlan_header);
} else {
ethLen = sizeof (struct ether_header);
}
/*
* Copy e1000g's behavior:
* - Do not assume all the headers are in the same mblk.
* - Assume each header is always within one mblk.
* - Assume the ethernet header is in the first mblk.
*/
}
}
/* Careful, '>' instead of '>=' here */
}
}
} else if (flags & HCK_PARTIALCKSUM) {
}
}
return (ret);
}
/*
* Map a msg into the Tx command ring of a vmxnet3 device.
*
* Returns:
* VMXNET3_TX_OK if everything went well.
* VMXNET3_TX_RINGFULL if the ring is nearly full.
* VMXNET3_TX_PULLUP if the msg is overfragmented.
* VMXNET3_TX_FAILURE if there was a DMA or offload error.
*
* Side effects:
* The ring is filled if VMXNET3_TX_OK is returned.
*/
static vmxnet3_txstatus
{
if (len) {
} else {
continue;
}
goto error;
}
do {
do {
frags >= VMXNET3_MAX_TXD_PER_PKT)) {
"overfragmented mp (%u)\n", frags);
(void) ddi_dma_unbind_handle(
dp->txDmaHandle);
goto error;
}
(void) ddi_dma_unbind_handle(
dp->txDmaHandle);
goto error;
}
if (len > VMXNET3_MAX_TX_BUF_SIZE) {
} else {
}
frags++;
/* txd.addr */
/* txd.dw2 */
0 : chunkLen;
/* txd.dw3 */
dw3 = 0;
} while (len);
if (--cookieCount) {
}
} while (cookieCount);
}
/* Update the EOP descriptor */
/* Update the SOP descriptor. Must be done last */
goto error;
}
/* Update the meta ring & metadata */
txqCtrl->txNumDeferred +=
} else {
txqCtrl->txNumDeferred++;
}
goto done;
/* Reverse the generation bits */
}
done:
return (ret);
}
/*
* Send packets on a vmxnet3 device.
*
* Returns:
* NULL in case of success or failure.
* The mps to be retransmitted later if the ring is full.
*/
mblk_t *
{
do {
int pullup;
/*
* PR #315560: M_PROTO mblks could be passed for
* some reason. Drop them because we don't understand
* them and because their contents are not Ethernet
* frames anyway.
*/
continue;
}
/*
* Prepare the offload while we're still handling the original
* message -- msgpullup() discards the metadata afterwards.
*/
if (pullup) {
if (new_mp) {
} else {
continue;
}
}
/*
* Try to map the message in the Tx ring.
* This call might fail for non-fatal reasons.
*/
if (status == VMXNET3_TX_PULLUP) {
/*
* Try one more time after flattening
* the message with msgpullup().
*/
if (new_mp) {
mp);
} else {
continue;
}
}
}
/* Fatal failure, drop it */
}
if (status == VMXNET3_TX_RINGFULL) {
} else {
}
/* Notify the device */
txqCtrl->txNumDeferred = 0;
}
return (mps);
}
/*
* Parse a transmit queue and complete packets.
*
* Returns:
* B_TRUE if Tx must be updated or B_FALSE if no action is required.
*/
{
eopMetaDesc->sopIdx = 0;
eopMetaDesc->frags = 0;
eopIdx);
}
}
return (ret);
}