sfxge(4): add helper to compute timer quantum

This also adjusts the timer values used to match the Linux net
driver implementation:
a) non-zero time intervals should result in at least one quantum
b) timer load/reload values are only zero biased for Falcon/Siena

Submitted by:   Andy Moreton <amoreton at solarflare.com>
Sponsored by:   Solarflare Communications, Inc.
MFC after:      1 week
Differential Revision:  https://reviews.freebsd.org/D6704
This commit is contained in:
Andrew Rybchenko
2016-06-04 09:17:45 +00:00
parent 64efe94d06
commit b839ed60bd
3 changed files with 55 additions and 31 deletions
+21 -23
View File
@@ -141,7 +141,6 @@ efx_mcdi_init_evq(
__in uint32_t irq,
__in uint32_t us)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_mcdi_req_t req;
uint8_t payload[
MAX(MC_CMD_INIT_EVQ_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_MAXNEVS)),
@@ -189,25 +188,22 @@ efx_mcdi_init_evq(
INIT_EVQ_IN_FLAG_RX_MERGE, 1,
INIT_EVQ_IN_FLAG_TX_MERGE, 1);
/* If the value is zero then disable the timer */
if (us == 0) {
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0);
} else {
uint32_t timer_val;
unsigned int ticks;
/* Calculate the timer value in quanta */
timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
/* Moderation value is base 0 so we need to deduct 1 */
if (timer_val > 0)
timer_val--;
if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
goto fail2;
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, timer_val);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, timer_val);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, ticks);
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, ticks);
}
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE,
@@ -230,18 +226,20 @@ efx_mcdi_init_evq(
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail2;
goto fail3;
}
if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) {
rc = EMSGSIZE;
goto fail3;
goto fail4;
}
/* NOTE: ignore the returned IRQ param as firmware does not set it. */
return (0);
fail4:
EFSYS_PROBE(fail4);
fail3:
EFSYS_PROBE(fail3);
fail2:
@@ -483,7 +481,7 @@ ef10_ev_qmoderate(
efx_nic_t *enp = eep->ee_enp;
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_dword_t dword;
uint32_t timer_ns, timer_val, mode;
uint32_t mode;
efx_rc_t rc;
/* Check that hardware and MCDI use the same timer MODE values */
@@ -503,37 +501,35 @@ ef10_ev_qmoderate(
/* If the value is zero then disable the timer */
if (us == 0) {
timer_ns = 0;
mode = FFE_CZ_TIMER_MODE_DIS;
} else {
timer_ns = us * 1000u;
mode = FFE_CZ_TIMER_MODE_INT_HLDOFF;
}
if (encp->enc_bug61265_workaround) {
rc = efx_mcdi_set_evq_tmr(enp, eep->ee_index, mode, timer_ns);
uint32_t ns = us * 1000;
rc = efx_mcdi_set_evq_tmr(enp, eep->ee_index, mode, ns);
if (rc != 0)
goto fail2;
} else {
/* Calculate the timer value in quanta */
timer_val = timer_ns / encp->enc_evq_timer_quantum_ns;
unsigned int ticks;
/* Moderation value is base 0 so we need to deduct 1 */
if (timer_val > 0)
timer_val--;
if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
goto fail3;
if (encp->enc_bug35388_workaround) {
EFX_POPULATE_DWORD_3(dword,
ERF_DD_EVQ_IND_TIMER_FLAGS,
EFE_DD_EVQ_IND_TIMER_FLAGS,
ERF_DD_EVQ_IND_TIMER_MODE, mode,
ERF_DD_EVQ_IND_TIMER_VAL, timer_val);
ERF_DD_EVQ_IND_TIMER_VAL, ticks);
EFX_BAR_TBL_WRITED(enp, ER_DD_EVQ_INDIRECT,
eep->ee_index, &dword, 0);
} else {
EFX_POPULATE_DWORD_2(dword,
ERF_DZ_TC_TIMER_MODE, mode,
ERF_DZ_TC_TIMER_VAL, timer_val);
ERF_DZ_TC_TIMER_VAL, ticks);
EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG,
eep->ee_index, &dword, 0);
}
@@ -541,6 +537,8 @@ ef10_ev_qmoderate(
return (0);
fail3:
EFSYS_PROBE(fail3);
fail2:
EFSYS_PROBE(fail2);
fail1:
+6
View File
@@ -1772,6 +1772,12 @@ efx_ev_qpoll(
__in const efx_ev_callbacks_t *eecp,
__in_opt void *arg);
extern __checkReturn efx_rc_t
efx_ev_usecs_to_ticks(
__in efx_nic_t *enp,
__in unsigned int usecs,
__out unsigned int *ticksp);
extern __checkReturn efx_rc_t
efx_ev_qmoderate(
__in efx_evq_t *eep,
+28 -8
View File
@@ -405,6 +405,27 @@ efx_ev_qpost(
eevop->eevo_qpost(eep, data);
}
__checkReturn efx_rc_t
efx_ev_usecs_to_ticks(
__in efx_nic_t *enp,
__in unsigned int us,
__out unsigned int *ticksp)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
unsigned int ticks;
/* Convert microseconds to a timer tick count */
if (us == 0)
ticks = 0;
else if (us * 1000 < encp->enc_evq_timer_quantum_ns)
ticks = 1; /* Never round down to zero */
else
ticks = us * 1000 / encp->enc_evq_timer_quantum_ns;
*ticksp = ticks;
return (0);
}
__checkReturn efx_rc_t
efx_ev_qmoderate(
__in efx_evq_t *eep,
@@ -1224,18 +1245,15 @@ siena_ev_qmoderate(
FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS,
FRF_CZ_TC_TIMER_VAL, 0);
} else {
uint32_t timer_val;
unsigned int ticks;
/* Calculate the timer value in quanta */
timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
/* Moderation value is base 0 so we need to deduct 1 */
if (timer_val > 0)
timer_val--;
if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
goto fail2;
EFSYS_ASSERT(ticks > 0);
EFX_POPULATE_DWORD_2(dword,
FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_INT_HLDOFF,
FRF_CZ_TC_TIMER_VAL, timer_val);
FRF_CZ_TC_TIMER_VAL, ticks - 1);
}
locked = (eep->ee_index == 0) ? 1 : 0;
@@ -1245,6 +1263,8 @@ siena_ev_qmoderate(
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);