mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 13:58:46 +00:00
sfc: set interrupt moderation via MCDI
SFN8000-series NICs require a new method of setting interrupt moderation, via MCDI. This is indicated by a workaround flag. This new MCDI command takes an explicit time value rather than a number of ticks. It therefore makes sense to also store the moderation values in terms of time, since that is what the ethtool interface is interested in. Signed-off-by: Bert Kenward <bkenward@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a995560a27
commit
539de7c524
@ -1749,27 +1749,43 @@ static size_t efx_ef10_update_stats_vf(struct efx_nic *efx, u64 *full_stats,
|
|||||||
static void efx_ef10_push_irq_moderation(struct efx_channel *channel)
|
static void efx_ef10_push_irq_moderation(struct efx_channel *channel)
|
||||||
{
|
{
|
||||||
struct efx_nic *efx = channel->efx;
|
struct efx_nic *efx = channel->efx;
|
||||||
unsigned int mode, value;
|
unsigned int mode, usecs;
|
||||||
efx_dword_t timer_cmd;
|
efx_dword_t timer_cmd;
|
||||||
|
|
||||||
if (channel->irq_moderation) {
|
if (channel->irq_moderation_us) {
|
||||||
mode = 3;
|
mode = 3;
|
||||||
value = channel->irq_moderation - 1;
|
usecs = channel->irq_moderation_us;
|
||||||
} else {
|
} else {
|
||||||
mode = 0;
|
mode = 0;
|
||||||
value = 0;
|
usecs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EFX_EF10_WORKAROUND_35388(efx)) {
|
if (EFX_EF10_WORKAROUND_61265(efx)) {
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_EVQ_TMR_IN_LEN);
|
||||||
|
unsigned int ns = usecs * 1000;
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_INSTANCE,
|
||||||
|
channel->channel);
|
||||||
|
MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_LOAD_REQ_NS, ns);
|
||||||
|
MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_RELOAD_REQ_NS, ns);
|
||||||
|
MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_MODE, mode);
|
||||||
|
|
||||||
|
efx_mcdi_rpc_async(efx, MC_CMD_SET_EVQ_TMR,
|
||||||
|
inbuf, sizeof(inbuf), 0, NULL, 0);
|
||||||
|
} else if (EFX_EF10_WORKAROUND_35388(efx)) {
|
||||||
|
unsigned int ticks = efx_usecs_to_ticks(efx, usecs);
|
||||||
|
|
||||||
EFX_POPULATE_DWORD_3(timer_cmd, ERF_DD_EVQ_IND_TIMER_FLAGS,
|
EFX_POPULATE_DWORD_3(timer_cmd, ERF_DD_EVQ_IND_TIMER_FLAGS,
|
||||||
EFE_DD_EVQ_IND_TIMER_FLAGS,
|
EFE_DD_EVQ_IND_TIMER_FLAGS,
|
||||||
ERF_DD_EVQ_IND_TIMER_MODE, mode,
|
ERF_DD_EVQ_IND_TIMER_MODE, mode,
|
||||||
ERF_DD_EVQ_IND_TIMER_VAL, value);
|
ERF_DD_EVQ_IND_TIMER_VAL, ticks);
|
||||||
efx_writed_page(efx, &timer_cmd, ER_DD_EVQ_INDIRECT,
|
efx_writed_page(efx, &timer_cmd, ER_DD_EVQ_INDIRECT,
|
||||||
channel->channel);
|
channel->channel);
|
||||||
} else {
|
} else {
|
||||||
|
unsigned int ticks = efx_usecs_to_ticks(efx, usecs);
|
||||||
|
|
||||||
EFX_POPULATE_DWORD_2(timer_cmd, ERF_DZ_TC_TIMER_MODE, mode,
|
EFX_POPULATE_DWORD_2(timer_cmd, ERF_DZ_TC_TIMER_MODE, mode,
|
||||||
ERF_DZ_TC_TIMER_VAL, value);
|
ERF_DZ_TC_TIMER_VAL, ticks);
|
||||||
efx_writed_page(efx, &timer_cmd, ER_DZ_EVQ_TMR,
|
efx_writed_page(efx, &timer_cmd, ER_DZ_EVQ_TMR,
|
||||||
channel->channel);
|
channel->channel);
|
||||||
}
|
}
|
||||||
@ -2615,10 +2631,11 @@ static int efx_ef10_ev_init(struct efx_channel *channel)
|
|||||||
/* Successfully created event queue on channel 0 */
|
/* Successfully created event queue on channel 0 */
|
||||||
rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
|
rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
|
||||||
if (rc == -ENOSYS) {
|
if (rc == -ENOSYS) {
|
||||||
/* GET_WORKAROUNDS was implemented before the bug26807
|
/* GET_WORKAROUNDS was implemented before these workarounds,
|
||||||
* workaround, thus the latter must be unavailable in this fw
|
* thus they must be unavailable in this firmware.
|
||||||
*/
|
*/
|
||||||
nic_data->workaround_26807 = false;
|
nic_data->workaround_26807 = false;
|
||||||
|
nic_data->workaround_61265 = false;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2658,6 +2675,9 @@ static int efx_ef10_ev_init(struct efx_channel *channel)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nic_data->workaround_61265 =
|
||||||
|
!!(implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG61265);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
|
@ -281,6 +281,27 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
|
|||||||
* NAPI guarantees serialisation of polls of the same device, which
|
* NAPI guarantees serialisation of polls of the same device, which
|
||||||
* provides the guarantee required by efx_process_channel().
|
* provides the guarantee required by efx_process_channel().
|
||||||
*/
|
*/
|
||||||
|
static void efx_update_irq_mod(struct efx_nic *efx, struct efx_channel *channel)
|
||||||
|
{
|
||||||
|
int step = efx->irq_mod_step_us;
|
||||||
|
|
||||||
|
if (channel->irq_mod_score < irq_adapt_low_thresh) {
|
||||||
|
if (channel->irq_moderation_us > step) {
|
||||||
|
channel->irq_moderation_us -= step;
|
||||||
|
efx->type->push_irq_moderation(channel);
|
||||||
|
}
|
||||||
|
} else if (channel->irq_mod_score > irq_adapt_high_thresh) {
|
||||||
|
if (channel->irq_moderation_us <
|
||||||
|
efx->irq_rx_moderation_us) {
|
||||||
|
channel->irq_moderation_us += step;
|
||||||
|
efx->type->push_irq_moderation(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->irq_count = 0;
|
||||||
|
channel->irq_mod_score = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_poll(struct napi_struct *napi, int budget)
|
static int efx_poll(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct efx_channel *channel =
|
struct efx_channel *channel =
|
||||||
@ -301,22 +322,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
|
|||||||
if (efx_channel_has_rx_queue(channel) &&
|
if (efx_channel_has_rx_queue(channel) &&
|
||||||
efx->irq_rx_adaptive &&
|
efx->irq_rx_adaptive &&
|
||||||
unlikely(++channel->irq_count == 1000)) {
|
unlikely(++channel->irq_count == 1000)) {
|
||||||
if (unlikely(channel->irq_mod_score <
|
efx_update_irq_mod(efx, channel);
|
||||||
irq_adapt_low_thresh)) {
|
|
||||||
if (channel->irq_moderation > 1) {
|
|
||||||
channel->irq_moderation -= 1;
|
|
||||||
efx->type->push_irq_moderation(channel);
|
|
||||||
}
|
|
||||||
} else if (unlikely(channel->irq_mod_score >
|
|
||||||
irq_adapt_high_thresh)) {
|
|
||||||
if (channel->irq_moderation <
|
|
||||||
efx->irq_rx_moderation) {
|
|
||||||
channel->irq_moderation += 1;
|
|
||||||
efx->type->push_irq_moderation(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
channel->irq_count = 0;
|
|
||||||
channel->irq_mod_score = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
efx_filter_rfs_expire(channel);
|
efx_filter_rfs_expire(channel);
|
||||||
@ -1703,6 +1709,7 @@ static int efx_probe_nic(struct efx_nic *efx)
|
|||||||
netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
|
netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
|
||||||
|
|
||||||
/* Initialise the interrupt moderation settings */
|
/* Initialise the interrupt moderation settings */
|
||||||
|
efx->irq_mod_step_us = DIV_ROUND_UP(efx->timer_quantum_ns, 1000);
|
||||||
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true,
|
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
@ -1949,14 +1956,21 @@ static void efx_remove_all(struct efx_nic *efx)
|
|||||||
* Interrupt moderation
|
* Interrupt moderation
|
||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
unsigned int efx_usecs_to_ticks(struct efx_nic *efx, unsigned int usecs)
|
||||||
static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns)
|
|
||||||
{
|
{
|
||||||
if (usecs == 0)
|
if (usecs == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (usecs * 1000 < quantum_ns)
|
if (usecs * 1000 < efx->timer_quantum_ns)
|
||||||
return 1; /* never round down to 0 */
|
return 1; /* never round down to 0 */
|
||||||
return usecs * 1000 / quantum_ns;
|
return usecs * 1000 / efx->timer_quantum_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int efx_ticks_to_usecs(struct efx_nic *efx, unsigned int ticks)
|
||||||
|
{
|
||||||
|
/* We must round up when converting ticks to microseconds
|
||||||
|
* because we round down when converting the other way.
|
||||||
|
*/
|
||||||
|
return DIV_ROUND_UP(ticks * efx->timer_quantum_ns, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set interrupt moderation parameters */
|
/* Set interrupt moderation parameters */
|
||||||
@ -1968,18 +1982,12 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
|
|||||||
unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max *
|
unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max *
|
||||||
efx->timer_quantum_ns,
|
efx->timer_quantum_ns,
|
||||||
1000);
|
1000);
|
||||||
unsigned int tx_ticks;
|
|
||||||
unsigned int rx_ticks;
|
|
||||||
|
|
||||||
EFX_ASSERT_RESET_SERIALISED(efx);
|
EFX_ASSERT_RESET_SERIALISED(efx);
|
||||||
|
|
||||||
if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max)
|
if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns);
|
if (tx_usecs != rx_usecs && efx->tx_channel_offset == 0 &&
|
||||||
rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns);
|
|
||||||
|
|
||||||
if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 &&
|
|
||||||
!rx_may_override_tx) {
|
!rx_may_override_tx) {
|
||||||
netif_err(efx, drv, efx->net_dev, "Channels are shared. "
|
netif_err(efx, drv, efx->net_dev, "Channels are shared. "
|
||||||
"RX and TX IRQ moderation must be equal\n");
|
"RX and TX IRQ moderation must be equal\n");
|
||||||
@ -1987,12 +1995,12 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
efx->irq_rx_adaptive = rx_adaptive;
|
efx->irq_rx_adaptive = rx_adaptive;
|
||||||
efx->irq_rx_moderation = rx_ticks;
|
efx->irq_rx_moderation_us = rx_usecs;
|
||||||
efx_for_each_channel(channel, efx) {
|
efx_for_each_channel(channel, efx) {
|
||||||
if (efx_channel_has_rx_queue(channel))
|
if (efx_channel_has_rx_queue(channel))
|
||||||
channel->irq_moderation = rx_ticks;
|
channel->irq_moderation_us = rx_usecs;
|
||||||
else if (efx_channel_has_tx_queues(channel))
|
else if (efx_channel_has_tx_queues(channel))
|
||||||
channel->irq_moderation = tx_ticks;
|
channel->irq_moderation_us = tx_usecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2001,26 +2009,21 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
|
|||||||
void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
|
void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
|
||||||
unsigned int *rx_usecs, bool *rx_adaptive)
|
unsigned int *rx_usecs, bool *rx_adaptive)
|
||||||
{
|
{
|
||||||
/* We must round up when converting ticks to microseconds
|
|
||||||
* because we round down when converting the other way.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*rx_adaptive = efx->irq_rx_adaptive;
|
*rx_adaptive = efx->irq_rx_adaptive;
|
||||||
*rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation *
|
*rx_usecs = efx->irq_rx_moderation_us;
|
||||||
efx->timer_quantum_ns,
|
|
||||||
1000);
|
|
||||||
|
|
||||||
/* If channels are shared between RX and TX, so is IRQ
|
/* If channels are shared between RX and TX, so is IRQ
|
||||||
* moderation. Otherwise, IRQ moderation is the same for all
|
* moderation. Otherwise, IRQ moderation is the same for all
|
||||||
* TX channels and is not adaptive.
|
* TX channels and is not adaptive.
|
||||||
*/
|
*/
|
||||||
if (efx->tx_channel_offset == 0)
|
if (efx->tx_channel_offset == 0) {
|
||||||
*tx_usecs = *rx_usecs;
|
*tx_usecs = *rx_usecs;
|
||||||
else
|
} else {
|
||||||
*tx_usecs = DIV_ROUND_UP(
|
struct efx_channel *tx_channel;
|
||||||
efx->channel[efx->tx_channel_offset]->irq_moderation *
|
|
||||||
efx->timer_quantum_ns,
|
tx_channel = efx->channel[efx->tx_channel_offset];
|
||||||
1000);
|
*tx_usecs = tx_channel->irq_moderation_us;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
@ -204,6 +204,8 @@ int efx_try_recovery(struct efx_nic *efx);
|
|||||||
|
|
||||||
/* Global */
|
/* Global */
|
||||||
void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
|
void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
|
||||||
|
unsigned int efx_usecs_to_ticks(struct efx_nic *efx, unsigned int usecs);
|
||||||
|
unsigned int efx_ticks_to_usecs(struct efx_nic *efx, unsigned int ticks);
|
||||||
int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
|
int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
|
||||||
unsigned int rx_usecs, bool rx_adaptive,
|
unsigned int rx_usecs, bool rx_adaptive,
|
||||||
bool rx_may_override_tx);
|
bool rx_may_override_tx);
|
||||||
|
@ -378,12 +378,15 @@ static void falcon_push_irq_moderation(struct efx_channel *channel)
|
|||||||
struct efx_nic *efx = channel->efx;
|
struct efx_nic *efx = channel->efx;
|
||||||
|
|
||||||
/* Set timer register */
|
/* Set timer register */
|
||||||
if (channel->irq_moderation) {
|
if (channel->irq_moderation_us) {
|
||||||
|
unsigned int ticks;
|
||||||
|
|
||||||
|
ticks = efx_usecs_to_ticks(efx, channel->irq_moderation_us);
|
||||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||||
FRF_AB_TC_TIMER_MODE,
|
FRF_AB_TC_TIMER_MODE,
|
||||||
FFE_BB_TIMER_MODE_INT_HLDOFF,
|
FFE_BB_TIMER_MODE_INT_HLDOFF,
|
||||||
FRF_AB_TC_TIMER_VAL,
|
FRF_AB_TC_TIMER_VAL,
|
||||||
channel->irq_moderation - 1);
|
ticks - 1);
|
||||||
} else {
|
} else {
|
||||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||||
FRF_AB_TC_TIMER_MODE,
|
FRF_AB_TC_TIMER_MODE,
|
||||||
|
@ -392,7 +392,7 @@ enum efx_sync_events_state {
|
|||||||
* @eventq_init: Event queue initialised flag
|
* @eventq_init: Event queue initialised flag
|
||||||
* @enabled: Channel enabled indicator
|
* @enabled: Channel enabled indicator
|
||||||
* @irq: IRQ number (MSI and MSI-X only)
|
* @irq: IRQ number (MSI and MSI-X only)
|
||||||
* @irq_moderation: IRQ moderation value (in hardware ticks)
|
* @irq_moderation_us: IRQ moderation value (in microseconds)
|
||||||
* @napi_dev: Net device used with NAPI
|
* @napi_dev: Net device used with NAPI
|
||||||
* @napi_str: NAPI control structure
|
* @napi_str: NAPI control structure
|
||||||
* @state: state for NAPI vs busy polling
|
* @state: state for NAPI vs busy polling
|
||||||
@ -433,7 +433,7 @@ struct efx_channel {
|
|||||||
bool eventq_init;
|
bool eventq_init;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int irq;
|
int irq;
|
||||||
unsigned int irq_moderation;
|
unsigned int irq_moderation_us;
|
||||||
struct net_device *napi_dev;
|
struct net_device *napi_dev;
|
||||||
struct napi_struct napi_str;
|
struct napi_struct napi_str;
|
||||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||||
@ -811,7 +811,8 @@ struct vfdi_status;
|
|||||||
* @interrupt_mode: Interrupt mode
|
* @interrupt_mode: Interrupt mode
|
||||||
* @timer_quantum_ns: Interrupt timer quantum, in nanoseconds
|
* @timer_quantum_ns: Interrupt timer quantum, in nanoseconds
|
||||||
* @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
|
* @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
|
||||||
* @irq_rx_moderation: IRQ moderation time for RX event queues
|
* @irq_rx_mod_step_us: Step size for IRQ moderation for RX event queues
|
||||||
|
* @irq_rx_moderation_us: IRQ moderation time for RX event queues
|
||||||
* @msg_enable: Log message enable flags
|
* @msg_enable: Log message enable flags
|
||||||
* @state: Device state number (%STATE_*). Serialised by the rtnl_lock.
|
* @state: Device state number (%STATE_*). Serialised by the rtnl_lock.
|
||||||
* @reset_pending: Bitmask for pending resets
|
* @reset_pending: Bitmask for pending resets
|
||||||
@ -941,7 +942,8 @@ struct efx_nic {
|
|||||||
enum efx_int_mode interrupt_mode;
|
enum efx_int_mode interrupt_mode;
|
||||||
unsigned int timer_quantum_ns;
|
unsigned int timer_quantum_ns;
|
||||||
bool irq_rx_adaptive;
|
bool irq_rx_adaptive;
|
||||||
unsigned int irq_rx_moderation;
|
unsigned int irq_mod_step_us;
|
||||||
|
unsigned int irq_rx_moderation_us;
|
||||||
u32 msg_enable;
|
u32 msg_enable;
|
||||||
|
|
||||||
enum nic_state state;
|
enum nic_state state;
|
||||||
|
@ -507,6 +507,7 @@ enum {
|
|||||||
* @stats: Hardware statistics
|
* @stats: Hardware statistics
|
||||||
* @workaround_35388: Flag: firmware supports workaround for bug 35388
|
* @workaround_35388: Flag: firmware supports workaround for bug 35388
|
||||||
* @workaround_26807: Flag: firmware supports workaround for bug 26807
|
* @workaround_26807: Flag: firmware supports workaround for bug 26807
|
||||||
|
* @workaround_61265: Flag: firmware supports workaround for bug 61265
|
||||||
* @must_check_datapath_caps: Flag: @datapath_caps needs to be revalidated
|
* @must_check_datapath_caps: Flag: @datapath_caps needs to be revalidated
|
||||||
* after MC reboot
|
* after MC reboot
|
||||||
* @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of
|
* @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of
|
||||||
@ -542,6 +543,7 @@ struct efx_ef10_nic_data {
|
|||||||
u64 stats[EF10_STAT_COUNT];
|
u64 stats[EF10_STAT_COUNT];
|
||||||
bool workaround_35388;
|
bool workaround_35388;
|
||||||
bool workaround_26807;
|
bool workaround_26807;
|
||||||
|
bool workaround_61265;
|
||||||
bool must_check_datapath_caps;
|
bool must_check_datapath_caps;
|
||||||
u32 datapath_caps;
|
u32 datapath_caps;
|
||||||
u32 datapath_caps2;
|
u32 datapath_caps2;
|
||||||
|
@ -1306,7 +1306,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
|
|||||||
{
|
{
|
||||||
struct efx_nic *efx = channel->efx;
|
struct efx_nic *efx = channel->efx;
|
||||||
|
|
||||||
channel->irq_moderation = 0;
|
channel->irq_moderation_us = 0;
|
||||||
channel->rx_queue.core_index = 0;
|
channel->rx_queue.core_index = 0;
|
||||||
|
|
||||||
return efx_ptp_probe(efx, channel);
|
return efx_ptp_probe(efx, channel);
|
||||||
|
@ -34,19 +34,24 @@ static void siena_init_wol(struct efx_nic *efx);
|
|||||||
|
|
||||||
static void siena_push_irq_moderation(struct efx_channel *channel)
|
static void siena_push_irq_moderation(struct efx_channel *channel)
|
||||||
{
|
{
|
||||||
|
struct efx_nic *efx = channel->efx;
|
||||||
efx_dword_t timer_cmd;
|
efx_dword_t timer_cmd;
|
||||||
|
|
||||||
if (channel->irq_moderation)
|
if (channel->irq_moderation_us) {
|
||||||
|
unsigned int ticks;
|
||||||
|
|
||||||
|
ticks = efx_usecs_to_ticks(efx, channel->irq_moderation_us);
|
||||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||||
FRF_CZ_TC_TIMER_MODE,
|
FRF_CZ_TC_TIMER_MODE,
|
||||||
FFE_CZ_TIMER_MODE_INT_HLDOFF,
|
FFE_CZ_TIMER_MODE_INT_HLDOFF,
|
||||||
FRF_CZ_TC_TIMER_VAL,
|
FRF_CZ_TC_TIMER_VAL,
|
||||||
channel->irq_moderation - 1);
|
ticks - 1);
|
||||||
else
|
} else {
|
||||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||||
FRF_CZ_TC_TIMER_MODE,
|
FRF_CZ_TC_TIMER_MODE,
|
||||||
FFE_CZ_TIMER_MODE_DIS,
|
FFE_CZ_TIMER_MODE_DIS,
|
||||||
FRF_CZ_TC_TIMER_VAL, 0);
|
FRF_CZ_TC_TIMER_VAL, 0);
|
||||||
|
}
|
||||||
efx_writed_page_locked(channel->efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
|
efx_writed_page_locked(channel->efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
|
||||||
channel->channel);
|
channel->channel);
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,8 @@
|
|||||||
#define EFX_WORKAROUND_35388(efx) \
|
#define EFX_WORKAROUND_35388(efx) \
|
||||||
(efx_nic_rev(efx) == EFX_REV_HUNT_A0 && EFX_EF10_WORKAROUND_35388(efx))
|
(efx_nic_rev(efx) == EFX_REV_HUNT_A0 && EFX_EF10_WORKAROUND_35388(efx))
|
||||||
|
|
||||||
|
/* Moderation timer access must go through MCDI */
|
||||||
|
#define EFX_EF10_WORKAROUND_61265(efx) \
|
||||||
|
(((struct efx_ef10_nic_data *)efx->nic_data)->workaround_61265)
|
||||||
|
|
||||||
#endif /* EFX_WORKAROUNDS_H */
|
#endif /* EFX_WORKAROUNDS_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user