efx_tx.c revision 49ef7e0638c8b771d8a136eae78b1c0f99acc8e0
/*
* Copyright (c) 2007-2015 Solarflare Communications Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include "efx.h"
#include "efx_impl.h"
#if EFSYS_OPT_QSTATS
do { \
} while (B_FALSE)
#else
#endif
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
static void
static __checkReturn efx_rc_t
static void
static __checkReturn efx_rc_t
__in unsigned int n,
static void
static __checkReturn efx_rc_t
static __checkReturn efx_rc_t
static void
__in unsigned int n,
void
#if EFSYS_OPT_QSTATS
static void
#endif
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_SIENA
static const efx_tx_ops_t __efx_tx_siena_ops = {
siena_tx_init, /* etxo_init */
siena_tx_fini, /* etxo_fini */
siena_tx_qcreate, /* etxo_qcreate */
siena_tx_qdestroy, /* etxo_qdestroy */
siena_tx_qpost, /* etxo_qpost */
siena_tx_qpush, /* etxo_qpush */
siena_tx_qpace, /* etxo_qpace */
siena_tx_qflush, /* etxo_qflush */
siena_tx_qenable, /* etxo_qenable */
NULL, /* etxo_qpio_enable */
NULL, /* etxo_qpio_disable */
NULL, /* etxo_qpio_write */
NULL, /* etxo_qpio_post */
siena_tx_qdesc_post, /* etxo_qdesc_post */
siena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
NULL, /* etxo_qdesc_tso2_create */
NULL, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
siena_tx_qstats_update, /* etxo_qstats_update */
#endif
};
#endif /* EFSYS_OPT_SIENA */
static const efx_tx_ops_t __efx_tx_hunt_ops = {
ef10_tx_init, /* etxo_init */
ef10_tx_fini, /* etxo_fini */
ef10_tx_qcreate, /* etxo_qcreate */
ef10_tx_qdestroy, /* etxo_qdestroy */
ef10_tx_qpost, /* etxo_qpost */
ef10_tx_qpush, /* etxo_qpush */
ef10_tx_qpace, /* etxo_qpace */
ef10_tx_qflush, /* etxo_qflush */
ef10_tx_qenable, /* etxo_qenable */
ef10_tx_qpio_enable, /* etxo_qpio_enable */
ef10_tx_qpio_disable, /* etxo_qpio_disable */
ef10_tx_qpio_write, /* etxo_qpio_write */
ef10_tx_qpio_post, /* etxo_qpio_post */
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
ef10_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
#endif
};
#endif /* EFSYS_OPT_HUNTINGTON */
static const efx_tx_ops_t __efx_tx_medford_ops = {
ef10_tx_init, /* etxo_init */
ef10_tx_fini, /* etxo_fini */
ef10_tx_qcreate, /* etxo_qcreate */
ef10_tx_qdestroy, /* etxo_qdestroy */
ef10_tx_qpost, /* etxo_qpost */
ef10_tx_qpush, /* etxo_qpush */
ef10_tx_qpace, /* etxo_qpace */
ef10_tx_qflush, /* etxo_qflush */
ef10_tx_qenable, /* etxo_qenable */
ef10_tx_qpio_enable, /* etxo_qpio_enable */
ef10_tx_qpio_disable, /* etxo_qpio_disable */
ef10_tx_qpio_write, /* etxo_qpio_write */
ef10_tx_qpio_post, /* etxo_qpio_post */
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
#endif
};
#endif /* EFSYS_OPT_MEDFORD */
{
const efx_tx_ops_t *etxop;
goto fail1;
}
goto fail2;
}
#if EFSYS_OPT_SIENA
case EFX_FAMILY_SIENA:
break;
#endif /* EFSYS_OPT_SIENA */
case EFX_FAMILY_HUNTINGTON:
break;
#endif /* EFSYS_OPT_HUNTINGTON */
case EFX_FAMILY_MEDFORD:
break;
#endif /* EFSYS_OPT_MEDFORD */
default:
EFSYS_ASSERT(0);
goto fail3;
}
goto fail4;
return (0);
return (rc);
}
void
{
}
{
/* Allocate an TXQ object */
goto fail1;
}
/* Initial descriptor index may be modified by etxo_qcreate */
*addedp = 0;
goto fail2;
enp->en_tx_qcount++;
return (0);
return (rc);
}
void
{
--enp->en_tx_qcount;
/* Free the TXQ object */
}
__in unsigned int n,
{
goto fail1;
return (0);
return (rc);
}
void
{
}
{
goto fail1;
return (0);
return (rc);
}
{
goto fail1;
return (0);
return (rc);
}
void
{
}
{
goto fail1;
}
goto fail2;
}
goto fail3;
return (0);
return (rc);
}
void
{
}
{
pio_buf_offset)) != 0)
goto fail1;
return (0);
}
return (ENOTSUP);
return (rc);
}
{
addedp)) != 0)
goto fail1;
return (0);
}
return (ENOTSUP);
return (rc);
}
__in unsigned int n,
{
goto fail1;
return (0);
return (rc);
}
void
{
}
void
{
}
void
{
}
void
{
}
#if EFSYS_OPT_QSTATS
void
{
}
#endif
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
{
/*
* Disable the timer-based TX DMA backoff and allow TX DMA to be
* controlled by the RX FIFO fill level (although always allow a
* minimal trickle).
*/
/*
* Filter all packets less than 14 bytes to avoid parsing
* errors.
*/
/*
* Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
* descriptors (which is bad).
*/
return (0);
}
do { \
unsigned int id; \
efx_qword_t qword; \
\
\
\
\
} while (B_FALSE)
static __checkReturn efx_rc_t
__in unsigned int n,
{
unsigned int i;
goto fail1;
for (i = 0; i < n; i++) {
/* Fragments must not span 4k boundaries. */
}
return (0);
return (rc);
}
static void
{
/* Push the populated descriptors out */
/* Only write the third DWORD */
/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
}
#define EFX_MAX_PACE_VALUE 20
static __checkReturn efx_rc_t
{
unsigned int pace_val;
unsigned int timer_period;
if (ns == 0) {
pace_val = 0;
} else {
/*
* The pace_val to write into the table is s.t
* ns <= timer_period * (2 ^ pace_val)
*/
break;
}
}
if (pace_val > EFX_MAX_PACE_VALUE) {
goto fail1;
}
/* Update the pacing table */
return (0);
return (rc);
}
static __checkReturn efx_rc_t
{
(void) efx_tx_qpace(etp, 0);
/* Flush the queue */
return (0);
}
static void
{
}
static __checkReturn efx_rc_t
{
(1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
goto fail1;
}
goto fail2;
}
for (size = 0;
size++)
break;
goto fail3;
}
/* Set up the new descriptor queue */
*addedp = 0;
FRF_AZ_TX_DESCQ_TYPE, 0);
return (0);
return (rc);
}
__in unsigned int n,
{
unsigned int i;
goto fail1;
}
for (i = 0; i < n; i++) {
unsigned int id;
}
unsigned int, added, unsigned int, n);
return (0);
return (rc);
}
void
{
/* Fragments must not span 4k boundaries. */
}
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_QSTATS
#if EFSYS_OPT_NAMES
/* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 9d8d26a0a5e2c453 */
static const char *__efx_tx_qstat_name[] = {
"post",
"post_pio",
};
/* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
const char *
{
return (__efx_tx_qstat_name[id]);
}
#endif /* EFSYS_OPT_NAMES */
#endif /* EFSYS_OPT_QSTATS */
#if EFSYS_OPT_SIENA
#if EFSYS_OPT_QSTATS
static void
{
unsigned int id;
}
}
#endif /* EFSYS_OPT_QSTATS */
static void
{
/* Purge descriptor queue */
}
static void
{
}
#endif /* EFSYS_OPT_SIENA */