diff options
author | arybchik <arybchik@FreeBSD.org> | 2015-03-25 13:12:15 +0000 |
---|---|---|
committer | arybchik <arybchik@FreeBSD.org> | 2015-03-25 13:12:15 +0000 |
commit | ba7bae884a82938e29ce6d89af1e64b298f1c24c (patch) | |
tree | a3289480bfb89142e81f18d544f93e02fdf11a96 /sys/dev/sfxge/common/efx_tx.c | |
parent | 7226fa93cac4e7cc7b3b6004265f143f7ef24d4c (diff) | |
download | FreeBSD-src-ba7bae884a82938e29ce6d89af1e64b298f1c24c.zip FreeBSD-src-ba7bae884a82938e29ce6d89af1e64b298f1c24c.tar.gz |
MFC: 279183
sfxge: add common code support for changing TX queue pace
To delay packets from a particular TX queue by a particular time, write a value
into the TX Pace table s.t. pace time <= TX Pace Clock Period * (2 ^ pace value)
- the TX pace clock is 1/13 of the system clock, so its period should be 104 or
52 ns depending on whether turbo mode is active.
EFX_TX_PACE_CLOCK_BASE added by me.
Submitted by: Mark Spender <mspender at solarflare.com>
Sponsored by: Solarflare Communications, Inc.
Approved by: gnn (mentor)
Diffstat (limited to 'sys/dev/sfxge/common/efx_tx.c')
-rw-r--r-- | sys/dev/sfxge/common/efx_tx.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/dev/sfxge/common/efx_tx.c b/sys/dev/sfxge/common/efx_tx.c index 2ee9c10..2b0f5e5 100644 --- a/sys/dev/sfxge/common/efx_tx.c +++ b/sys/dev/sfxge/common/efx_tx.c @@ -224,6 +224,53 @@ efx_tx_qpush( etp->et_index, &dword, B_FALSE); } +#define EFX_MAX_PACE_VALUE 20 +#define EFX_TX_PACE_CLOCK_BASE 104 + + __checkReturn int +efx_tx_qpace( + __in efx_txq_t *etp, + __in unsigned int ns) +{ + efx_nic_t *enp = etp->et_enp; + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); + efx_oword_t oword; + unsigned int pace_val; + unsigned int timer_period; + int rc; + + EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); + + if (ns == 0) { + pace_val = 0; + } else { + /* + * The pace_val to write into the table is s.t + * ns <= timer_period * (2 ^ pace_val) + */ + timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult; + for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) { + if ((timer_period << pace_val) >= ns) + break; + } + } + if (pace_val > EFX_MAX_PACE_VALUE) { + rc = EINVAL; + goto fail1; + } + + /* Update the pacing table */ + EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val); + EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index, &oword); + + return (0); + +fail1: + EFSYS_PROBE1(fail1, int, rc); + + return (rc); +} + void efx_tx_qflush( __in efx_txq_t *etp) @@ -234,6 +281,8 @@ efx_tx_qflush( EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); + efx_tx_qpace(etp, 0); + label = etp->et_index; /* Flush the queue */ |