aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-05-12 23:08:47 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-12 23:08:47 -0400
commit147ef3e218eab03e84f165e8352728719f5d7be4 (patch)
tree1bfea0efc79318e2405b50edf1455b42fa55b9be
parenta2029240e5836e73ebcc1a8ddb8c22d636f89c9a (diff)
parentd0634868d30ed2c511b45c63efe8eeb85c62c7f6 (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.c63
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.h2
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
459static 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
478static 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
459static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb) 520static 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
1646static const struct net_device_ops bcm_sysport_netdev_ops = { 1709static 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