netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Florian Fainelli <f.fainelli@gmail.com>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Florian Fainelli <f.fainelli@gmail.com>
Subject: [PATCH net-next 3/4] net: bcmgenet: add support for ethtool rx-frames
Date: Mon, 21 Apr 2014 08:45:23 -0700	[thread overview]
Message-ID: <1398095124-5411-4-git-send-email-f.fainelli@gmail.com> (raw)
In-Reply-To: <1398095124-5411-1-git-send-email-f.fainelli@gmail.com>

Add support for the ethtool rx-frames coalescing parameter which allows
defining the number of RX interrupts per frames received. Make sure that
whenever the link speed changes, we also re-program a correct push timer
value.

We can no longer enable the BDONE/PDONE interrupts as those would
fire for each packet/buffer received, which would defeat the MBDONE
interrupt purpose. The MBDONE interrupt is guaranteed to correspond to a
PDONE/BDONE interrupt when the threshold is set to 1.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c | 44 ++++++++++++++++++++++----
 drivers/net/ethernet/broadcom/genet/bcmgenet.h |  1 +
 drivers/net/ethernet/broadcom/genet/bcmmii.c   |  3 ++
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index f1b3969de10b..4922958ec4aa 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -78,13 +78,10 @@
 #define GENET_RDMA_REG_OFF	(priv->hw_params->rdma_offset + \
 				TOTAL_DESC * DMA_DESC_SIZE)
 
-/* TX DMA done mask: multiple buffer done */
+/* RX/TX DMA done mask: multiple buffer done */
 #define UMAC_TXDMA_DONE_MASK	(UMAC_IRQ_TXDMA_MBDONE)
 
-/* Rx DMA done masks: packet, buffer and multiple buffer done */
-#define UMAC_RXDMA_DONE_MASK	(UMAC_IRQ_RXDMA_BDONE | \
-				 UMAC_IRQ_RXDMA_PDONE | \
-				 UMAC_IRQ_RXDMA_MBDONE)
+#define UMAC_RXDMA_DONE_MASK	(UMAC_IRQ_RXDMA_MBDONE)
 
 static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
 						void __iomem *d, u32 value)
@@ -210,6 +207,7 @@ enum dma_reg {
 	DMA_ARB_CTRL,
 	DMA_PRIORITY,
 	DMA_RING_PRIORITY,
+	DMA_RING16_TIMEOUT,
 };
 
 static const u8 bcmgenet_dma_regs_v3plus[] = {
@@ -220,6 +218,7 @@ static const u8 bcmgenet_dma_regs_v3plus[] = {
 	[DMA_ARB_CTRL]		= 0x2C,
 	[DMA_PRIORITY]		= 0x30,
 	[DMA_RING_PRIORITY]	= 0x38,
+	[DMA_RING16_TIMEOUT]	= 0x6C,
 };
 
 static const u8 bcmgenet_dma_regs_v2[] = {
@@ -230,6 +229,7 @@ static const u8 bcmgenet_dma_regs_v2[] = {
 	[DMA_ARB_CTRL]		= 0x30,
 	[DMA_PRIORITY]		= 0x34,
 	[DMA_RING_PRIORITY]	= 0x3C,
+	[DMA_RING16_TIMEOUT]	= 0x6C,
 };
 
 static const u8 bcmgenet_dma_regs_v1[] = {
@@ -239,6 +239,7 @@ static const u8 bcmgenet_dma_regs_v1[] = {
 	[DMA_ARB_CTRL]		= 0x30,
 	[DMA_PRIORITY]		= 0x34,
 	[DMA_RING_PRIORITY]	= 0x3C,
+	[DMA_RING16_TIMEOUT]	= 0x6C,
 };
 
 /* Set at runtime once bcmgenet version is known */
@@ -501,17 +502,42 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
 
 	ec->tx_max_coalesced_frames = bcmgenet_tdma_ring_readl(priv,
 			DESC_INDEX, DMA_MBUF_DONE_THRESH);
+	ec->rx_max_coalesced_frames = bcmgenet_rdma_ring_readl(priv,
+			DESC_INDEX, DMA_MBUF_DONE_THRESH);
 
 	return 0;
 }
 
+/* Update RX coalescing scheme based on the current link speed, caller
+ * must have updated the ring threshold before calling us.
+ */
+void bcmgenet_update_rx_coal(struct net_device *dev)
+{
+	unsigned int speeds[] = { SPEED_10, SPEED_100, SPEED_1000, SPEED_2500 };
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 cur_speed;
+	u32 timeout;
+	u32 rx_coal;
+
+	rx_coal = bcmgenet_rdma_ring_readl(priv, DESC_INDEX,
+			DMA_MBUF_DONE_THRESH);
+
+	cur_speed = (bcmgenet_umac_readl(priv, UMAC_CMD) >> CMD_SPEED_SHIFT) &
+			CMD_SPEED_MASK;
+
+	timeout = 2 * (rx_coal * ENET_MAX_MTU_SIZE) / speeds[cur_speed];
+	bcmgenet_rdma_writel(priv, timeout, DMA_RING16_TIMEOUT);
+}
+
 static int bcmgenet_set_coalesce(struct net_device *dev,
 				 struct ethtool_coalesce *ec)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	unsigned int i;
 
-	if (ec->tx_max_coalesced_frames > 255)
+	if (ec->tx_max_coalesced_frames > 255 ||
+	    ec->rx_max_coalesced_frames < 1 ||
+	    ec->rx_max_coalesced_frames > 255)
 		return -EINVAL;
 
 	/* Program all TX queues with the same values, as there is no
@@ -523,6 +549,11 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
 	bcmgenet_tdma_ring_writel(priv, DESC_INDEX,
 			ec->tx_max_coalesced_frames, DMA_MBUF_DONE_THRESH);
 
+	bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
+			ec->rx_max_coalesced_frames, DMA_MBUF_DONE_THRESH);
+
+	bcmgenet_update_rx_coal(dev);
+
 	return 0;
 }
 
@@ -1680,6 +1711,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
 			(DMA_FC_THRESH_LO << DMA_XOFF_THRESHOLD_SHIFT) |
 			DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
 	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_READ_PTR);
+	bcmgenet_rdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
 
 	return ret;
 }
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 0f117105fed1..e9c17dcbc9ab 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -624,5 +624,6 @@ int bcmgenet_mii_init(struct net_device *dev);
 int bcmgenet_mii_config(struct net_device *dev);
 void bcmgenet_mii_exit(struct net_device *dev);
 void bcmgenet_mii_reset(struct net_device *dev);
+void bcmgenet_update_rx_coal(struct net_device *dev);
 
 #endif /* __BCMGENET_H__ */
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 4608673beaff..fd2f9ba70977 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -143,6 +143,9 @@ static void bcmgenet_mii_setup(struct net_device *dev)
 			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
 		reg |= cmd_bits;
 		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+		/* Update coalescing scheme based on current speed */
+		bcmgenet_update_rx_coal(priv->dev);
 	}
 
 	if (status_changed)
-- 
1.9.1

  parent reply	other threads:[~2014-04-21 15:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-21 15:45 [PATCH net-next 0/4] net: bcmgenet: interrupt coalescing support Florian Fainelli
2014-04-21 15:45 ` [PATCH net-next 1/4] net: bcmgenet: prepare for MBDONE interrupts support Florian Fainelli
2014-04-21 15:45 ` [PATCH net-next 2/4] net: bcmgenet: add support for ethtool tx-frames Florian Fainelli
2014-04-21 19:17   ` David Miller
2014-04-21 19:55     ` Florian Fainelli
2014-04-21 19:59       ` David Miller
2014-04-21 15:45 ` Florian Fainelli [this message]
2014-04-21 15:45 ` [PATCH net-next 4/4] net: bcmgenet: do not set RX buffer length Florian Fainelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1398095124-5411-4-git-send-email-f.fainelli@gmail.com \
    --to=f.fainelli@gmail.com \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).