aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/efx.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2011-12-08 14:51:47 -0500
committerBen Hutchings <bhutchings@solarflare.com>2012-01-26 19:10:50 -0500
commitcc180b69c009ec52f67a56d96b9073b9f774b323 (patch)
tree2d20225099a9a08d3471aeb3cd8ce4295417e5e6 /drivers/net/ethernet/sfc/efx.c
parent6aa9c7f625e8ce07060467051b68fc068118ee64 (diff)
sfc: Correct interrupt timer quantum for Siena (normal and turbo mode)
We currently assume that the timer quantum for Siena is 5 us, the same as for Falcon. This is not correct; timer ticks are generated on a rota which takes a minimum of 768 cycles (each event delivery or other timer change will delay it by 3 cycles). The timer quantum should be 6.144 or 3.072 us depending on whether turbo mode is active. Replace EFX_IRQ_MOD_RESOLUTION with a timer_quantum_ns field in struct efx_nic, initialised by the efx_nic_type::probe function. While we're at it, replace EFX_IRQ_MOD_MAX with a timer_period_max field in struct efx_nic_type. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/efx.c')
-rw-r--r--drivers/net/ethernet/sfc/efx.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index de162474c3c5..9d4ab5e5e1fa 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1513,13 +1513,13 @@ static void efx_remove_all(struct efx_nic *efx)
1513 * 1513 *
1514 **************************************************************************/ 1514 **************************************************************************/
1515 1515
1516static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution) 1516static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns)
1517{ 1517{
1518 if (usecs == 0) 1518 if (usecs == 0)
1519 return 0; 1519 return 0;
1520 if (usecs < resolution) 1520 if (usecs * 1000 < quantum_ns)
1521 return 1; /* never round down to 0 */ 1521 return 1; /* never round down to 0 */
1522 return usecs / resolution; 1522 return usecs * 1000 / quantum_ns;
1523} 1523}
1524 1524
1525/* Set interrupt moderation parameters */ 1525/* Set interrupt moderation parameters */
@@ -1528,14 +1528,20 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
1528 bool rx_may_override_tx) 1528 bool rx_may_override_tx)
1529{ 1529{
1530 struct efx_channel *channel; 1530 struct efx_channel *channel;
1531 unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION); 1531 unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max *
1532 unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION); 1532 efx->timer_quantum_ns,
1533 1000);
1534 unsigned int tx_ticks;
1535 unsigned int rx_ticks;
1533 1536
1534 EFX_ASSERT_RESET_SERIALISED(efx); 1537 EFX_ASSERT_RESET_SERIALISED(efx);
1535 1538
1536 if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX) 1539 if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max)
1537 return -EINVAL; 1540 return -EINVAL;
1538 1541
1542 tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns);
1543 rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns);
1544
1539 if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 && 1545 if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 &&
1540 !rx_may_override_tx) { 1546 !rx_may_override_tx) {
1541 netif_err(efx, drv, efx->net_dev, "Channels are shared. " 1547 netif_err(efx, drv, efx->net_dev, "Channels are shared. "
@@ -1558,8 +1564,14 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
1558void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, 1564void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
1559 unsigned int *rx_usecs, bool *rx_adaptive) 1565 unsigned int *rx_usecs, bool *rx_adaptive)
1560{ 1566{
1567 /* We must round up when converting ticks to microseconds
1568 * because we round down when converting the other way.
1569 */
1570
1561 *rx_adaptive = efx->irq_rx_adaptive; 1571 *rx_adaptive = efx->irq_rx_adaptive;
1562 *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION; 1572 *rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation *
1573 efx->timer_quantum_ns,
1574 1000);
1563 1575
1564 /* If channels are shared between RX and TX, so is IRQ 1576 /* If channels are shared between RX and TX, so is IRQ
1565 * moderation. Otherwise, IRQ moderation is the same for all 1577 * moderation. Otherwise, IRQ moderation is the same for all
@@ -1568,9 +1580,10 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
1568 if (efx->tx_channel_offset == 0) 1580 if (efx->tx_channel_offset == 0)
1569 *tx_usecs = *rx_usecs; 1581 *tx_usecs = *rx_usecs;
1570 else 1582 else
1571 *tx_usecs = 1583 *tx_usecs = DIV_ROUND_UP(
1572 efx->channel[efx->tx_channel_offset]->irq_moderation * 1584 efx->channel[efx->tx_channel_offset]->irq_moderation *
1573 EFX_IRQ_MOD_RESOLUTION; 1585 efx->timer_quantum_ns,
1586 1000);
1574} 1587}
1575 1588
1576/************************************************************************** 1589/**************************************************************************