diff options
author | David S. Miller <davem@davemloft.net> | 2015-05-12 23:08:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-12 23:08:47 -0400 |
commit | 147ef3e218eab03e84f165e8352728719f5d7be4 (patch) | |
tree | 1bfea0efc79318e2405b50edf1455b42fa55b9be | |
parent | a2029240e5836e73ebcc1a8ddb8c22d636f89c9a (diff) | |
parent | d0634868d30ed2c511b45c63efe8eeb85c62c7f6 (diff) |
Merge branch 'systemport-irq-coalesce'
Florian Fainelli says:
====================
net: systemport: interrupt coalescing support
This patch series adds support for RX & TX interrupt coalescing in the
systemport driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.c | 63 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.h | 2 |
2 files changed, 64 insertions, 1 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 783543ad1fcf..084a50a555de 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c | |||
@@ -456,6 +456,67 @@ static int bcm_sysport_set_wol(struct net_device *dev, | |||
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | static int bcm_sysport_get_coalesce(struct net_device *dev, | ||
460 | struct ethtool_coalesce *ec) | ||
461 | { | ||
462 | struct bcm_sysport_priv *priv = netdev_priv(dev); | ||
463 | u32 reg; | ||
464 | |||
465 | reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(0)); | ||
466 | |||
467 | ec->tx_coalesce_usecs = (reg >> RING_TIMEOUT_SHIFT) * 8192 / 1000; | ||
468 | ec->tx_max_coalesced_frames = reg & RING_INTR_THRESH_MASK; | ||
469 | |||
470 | reg = rdma_readl(priv, RDMA_MBDONE_INTR); | ||
471 | |||
472 | ec->rx_coalesce_usecs = (reg >> RDMA_TIMEOUT_SHIFT) * 8192 / 1000; | ||
473 | ec->rx_max_coalesced_frames = reg & RDMA_INTR_THRESH_MASK; | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int bcm_sysport_set_coalesce(struct net_device *dev, | ||
479 | struct ethtool_coalesce *ec) | ||
480 | { | ||
481 | struct bcm_sysport_priv *priv = netdev_priv(dev); | ||
482 | unsigned int i; | ||
483 | u32 reg; | ||
484 | |||
485 | /* Base system clock is 125Mhz, DMA timeout is this reference clock | ||
486 | * divided by 1024, which yield roughly 8.192 us, our maximum value has | ||
487 | * to fit in the RING_TIMEOUT_MASK (16 bits). | ||
488 | */ | ||
489 | if (ec->tx_max_coalesced_frames > RING_INTR_THRESH_MASK || | ||
490 | ec->tx_coalesce_usecs > (RING_TIMEOUT_MASK * 8) + 1 || | ||
491 | ec->rx_max_coalesced_frames > RDMA_INTR_THRESH_MASK || | ||
492 | ec->rx_coalesce_usecs > (RDMA_TIMEOUT_MASK * 8) + 1) | ||
493 | return -EINVAL; | ||
494 | |||
495 | if ((ec->tx_coalesce_usecs == 0 && ec->tx_max_coalesced_frames == 0) || | ||
496 | (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0)) | ||
497 | return -EINVAL; | ||
498 | |||
499 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
500 | reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(i)); | ||
501 | reg &= ~(RING_INTR_THRESH_MASK | | ||
502 | RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT); | ||
503 | reg |= ec->tx_max_coalesced_frames; | ||
504 | reg |= DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000, 8192) << | ||
505 | RING_TIMEOUT_SHIFT; | ||
506 | tdma_writel(priv, reg, TDMA_DESC_RING_INTR_CONTROL(i)); | ||
507 | } | ||
508 | |||
509 | reg = rdma_readl(priv, RDMA_MBDONE_INTR); | ||
510 | reg &= ~(RDMA_INTR_THRESH_MASK | | ||
511 | RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT); | ||
512 | reg |= ec->rx_max_coalesced_frames; | ||
513 | reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192) << | ||
514 | RDMA_TIMEOUT_SHIFT; | ||
515 | rdma_writel(priv, reg, RDMA_MBDONE_INTR); | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
459 | static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb) | 520 | static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb) |
460 | { | 521 | { |
461 | dev_kfree_skb_any(cb->skb); | 522 | dev_kfree_skb_any(cb->skb); |
@@ -1641,6 +1702,8 @@ static struct ethtool_ops bcm_sysport_ethtool_ops = { | |||
1641 | .get_sset_count = bcm_sysport_get_sset_count, | 1702 | .get_sset_count = bcm_sysport_get_sset_count, |
1642 | .get_wol = bcm_sysport_get_wol, | 1703 | .get_wol = bcm_sysport_get_wol, |
1643 | .set_wol = bcm_sysport_set_wol, | 1704 | .set_wol = bcm_sysport_set_wol, |
1705 | .get_coalesce = bcm_sysport_get_coalesce, | ||
1706 | .set_coalesce = bcm_sysport_set_coalesce, | ||
1644 | }; | 1707 | }; |
1645 | 1708 | ||
1646 | static const struct net_device_ops bcm_sysport_netdev_ops = { | 1709 | static const struct net_device_ops bcm_sysport_netdev_ops = { |
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index e2c043eabbf3..42a4b4a0bc14 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h | |||
@@ -292,7 +292,7 @@ struct bcm_rsb { | |||
292 | #define RDMA_END_ADDR_LO 0x102c | 292 | #define RDMA_END_ADDR_LO 0x102c |
293 | 293 | ||
294 | #define RDMA_MBDONE_INTR 0x1030 | 294 | #define RDMA_MBDONE_INTR 0x1030 |
295 | #define RDMA_INTR_THRESH_MASK 0xff | 295 | #define RDMA_INTR_THRESH_MASK 0x1ff |
296 | #define RDMA_TIMEOUT_SHIFT 16 | 296 | #define RDMA_TIMEOUT_SHIFT 16 |
297 | #define RDMA_TIMEOUT_MASK 0xffff | 297 | #define RDMA_TIMEOUT_MASK 0xffff |
298 | 298 | ||