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:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user