linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping
@ 2016-06-15 14:58 John Crispin
  2016-06-15 14:58 ` [PATCH 1/4] net-next: mediatek: remove superfluous register reads John Crispin
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: John Crispin @ 2016-06-15 14:58 UTC (permalink / raw)
  To: David S. Miller
  Cc: Felix Fietkau, Sean Wang, netdev, linux-mediatek, linux-kernel,
	John Crispin

This series contains 2 small code cleanups that are leftovers from the
MIPS support. There is also a small fix that adds proper locking to the
code accessing the IRQ registers. Without this fix we saw deadlocks caused
by the last patch of the series, which adds IRQ grouping. The grouping
feature allows us to use different IRQs for TX and RX. By doing so we can
use affinity to let the SoC handle the IRQs on different cores.

John Crispin (4):
  net-next: mediatek: remove superfluous register reads
  net-next: mediatek: don't use intermediate variables to store IRQ
    masks
  net-next: mediatek: add IRQ locking
  net-next: mediatek: add support for IRQ grouping

 drivers/net/ethernet/mediatek/mtk_eth_soc.c |  175 +++++++++++++++++----------
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |   16 ++-
 2 files changed, 122 insertions(+), 69 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] net-next: mediatek: remove superfluous register reads
  2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
@ 2016-06-15 14:58 ` John Crispin
  2016-06-15 14:58 ` [PATCH 2/4] net-next: mediatek: don't use intermediate variables to store IRQ masks John Crispin
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2016-06-15 14:58 UTC (permalink / raw)
  To: David S. Miller
  Cc: Felix Fietkau, Sean Wang, netdev, linux-mediatek, linux-kernel,
	John Crispin

The driver was originally written for MIPS based SoC. These required the
IRQ mask register to be read after writing it to ensure that the content
was actually applied. As this version only works on ARM based SoCs, we can
safely remove the 2 reads as they are no longer required.

Signed-off-by: John Crispin <john@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ebfca7d..b3032f4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -304,8 +304,6 @@ static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask)
 
 	val = mtk_r32(eth, MTK_QDMA_INT_MASK);
 	mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK);
-	/* flush write */
-	mtk_r32(eth, MTK_QDMA_INT_MASK);
 }
 
 static inline void mtk_irq_enable(struct mtk_eth *eth, u32 mask)
@@ -314,8 +312,6 @@ static inline void mtk_irq_enable(struct mtk_eth *eth, u32 mask)
 
 	val = mtk_r32(eth, MTK_QDMA_INT_MASK);
 	mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK);
-	/* flush write */
-	mtk_r32(eth, MTK_QDMA_INT_MASK);
 }
 
 static int mtk_set_mac_address(struct net_device *dev, void *p)
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/4] net-next: mediatek: don't use intermediate variables to store IRQ masks
  2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
  2016-06-15 14:58 ` [PATCH 1/4] net-next: mediatek: remove superfluous register reads John Crispin
@ 2016-06-15 14:58 ` John Crispin
  2016-06-15 14:58 ` [PATCH 3/4] net-next: mediatek: add IRQ locking John Crispin
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2016-06-15 14:58 UTC (permalink / raw)
  To: David S. Miller
  Cc: Felix Fietkau, Sean Wang, netdev, linux-mediatek, linux-kernel,
	John Crispin

The code currently uses variables to store and never modify the bit masks
of interrupts. This is legacy code from an early version of the driver
that supported MIPS based SoCs where the IRQ bits depended on the actual
SoC. As the bits are the same for all ARM based SoCs using this driver we
can remove the intermediate variables.

Signed-off-by: John Crispin <john@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |   22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b3032f4..cc38eae 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -775,7 +775,7 @@ drop:
 }
 
 static int mtk_poll_rx(struct napi_struct *napi, int budget,
-		       struct mtk_eth *eth, u32 rx_intr)
+		       struct mtk_eth *eth)
 {
 	struct mtk_rx_ring *ring = &eth->rx_ring;
 	int idx = ring->calc_idx;
@@ -863,7 +863,7 @@ release_desc:
 	}
 
 	if (done < budget)
-		mtk_w32(eth, rx_intr, MTK_QMTK_INT_STATUS);
+		mtk_w32(eth, MTK_RX_DONE_INT, MTK_QMTK_INT_STATUS);
 
 	return done;
 }
@@ -946,28 +946,26 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
 static int mtk_poll(struct napi_struct *napi, int budget)
 {
 	struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
-	u32 status, status2, mask, tx_intr, rx_intr, status_intr;
+	u32 status, status2, mask;
 	int tx_done, rx_done;
 	bool tx_again = false;
 
 	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
 	status2 = mtk_r32(eth, MTK_INT_STATUS2);
-	tx_intr = MTK_TX_DONE_INT;
-	rx_intr = MTK_RX_DONE_INT;
-	status_intr = (MTK_GDM1_AF | MTK_GDM2_AF);
 	tx_done = 0;
 	rx_done = 0;
 	tx_again = 0;
 
-	if (status & tx_intr)
+	if (status & MTK_TX_DONE_INT)
 		tx_done = mtk_poll_tx(eth, budget, &tx_again);
 
-	if (status & rx_intr)
-		rx_done = mtk_poll_rx(napi, budget, eth, rx_intr);
+	if (status & MTK_RX_DONE_INT)
+		rx_done = mtk_poll_rx(napi, budget, eth);
 
-	if (unlikely(status2 & status_intr)) {
+	if (unlikely(status2 & (MTK_GDM1_AF | MTK_GDM2_AF))) {
 		mtk_stats_update(eth);
-		mtk_w32(eth, status_intr, MTK_INT_STATUS2);
+		mtk_w32(eth, (MTK_GDM1_AF | MTK_GDM2_AF),
+			MTK_INT_STATUS2);
 	}
 
 	if (unlikely(netif_msg_intr(eth))) {
@@ -985,7 +983,7 @@ static int mtk_poll(struct napi_struct *napi, int budget)
 		return budget;
 
 	napi_complete(napi);
-	mtk_irq_enable(eth, tx_intr | rx_intr);
+	mtk_irq_enable(eth, MTK_RX_DONE_INT | MTK_RX_DONE_INT);
 
 	return rx_done;
 }
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/4] net-next: mediatek: add IRQ locking
  2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
  2016-06-15 14:58 ` [PATCH 1/4] net-next: mediatek: remove superfluous register reads John Crispin
  2016-06-15 14:58 ` [PATCH 2/4] net-next: mediatek: don't use intermediate variables to store IRQ masks John Crispin
@ 2016-06-15 14:58 ` John Crispin
  2016-06-15 14:58 ` [PATCH 4/4] net-next: mediatek: add support for IRQ grouping John Crispin
  2016-06-16  5:20 ` [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping David Miller
  4 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2016-06-15 14:58 UTC (permalink / raw)
  To: David S. Miller
  Cc: Felix Fietkau, Sean Wang, netdev, linux-mediatek, linux-kernel,
	John Crispin

The code that enables and disables IRQs is missing proper locking. After
adding the IRQ grouping patch and routing the RX and TX IRQs to different
cores we experienced IRQ stalls. Fix this by adding proper locking.
We use a dedicated lock to reduce the latency if the IRQ code.

Signed-off-by: John Crispin <john@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |    7 +++++++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |    1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index cc38eae..c7da00b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -300,18 +300,24 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
 
 static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask)
 {
+	unsigned long flags;
 	u32 val;
 
+	spin_lock_irqsave(&eth->irq_lock, flags);
 	val = mtk_r32(eth, MTK_QDMA_INT_MASK);
 	mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK);
+	spin_unlock_irqrestore(&eth->irq_lock, flags);
 }
 
 static inline void mtk_irq_enable(struct mtk_eth *eth, u32 mask)
 {
+	unsigned long flags;
 	u32 val;
 
+	spin_lock_irqsave(&eth->irq_lock, flags);
 	val = mtk_r32(eth, MTK_QDMA_INT_MASK);
 	mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK);
+	spin_unlock_irqrestore(&eth->irq_lock, flags);
 }
 
 static int mtk_set_mac_address(struct net_device *dev, void *p)
@@ -1739,6 +1745,7 @@ static int mtk_probe(struct platform_device *pdev)
 		return PTR_ERR(eth->base);
 
 	spin_lock_init(&eth->page_lock);
+	spin_lock_init(&eth->irq_lock);
 
 	eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 						      "mediatek,ethsys");
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index a5eb7c6..3159d2a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -373,6 +373,7 @@ struct mtk_eth {
 	void __iomem			*base;
 	struct reset_control		*rstc;
 	spinlock_t			page_lock;
+	spinlock_t			irq_lock;
 	struct net_device		dummy_dev;
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/4] net-next: mediatek: add support for IRQ grouping
  2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
                   ` (2 preceding siblings ...)
  2016-06-15 14:58 ` [PATCH 3/4] net-next: mediatek: add IRQ locking John Crispin
@ 2016-06-15 14:58 ` John Crispin
  2016-06-16  5:20 ` [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping David Miller
  4 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2016-06-15 14:58 UTC (permalink / raw)
  To: David S. Miller
  Cc: Felix Fietkau, Sean Wang, netdev, linux-mediatek, linux-kernel,
	John Crispin

The ethernet core has 3 IRQs. Using the IRQ grouping registers we are able
to separate TX and RX IRQs, which allows us to service them on separate
cores. This patch splits the IRQ handler into 2 separate functions, one for
TX and another for RX. The TX housekeeping is split out into its own NAPI
handler.

Signed-off-by: John Crispin <john@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |  156 +++++++++++++++++----------
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |   15 ++-
 2 files changed, 111 insertions(+), 60 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c7da00b..79fdb07 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -874,14 +874,13 @@ release_desc:
 	return done;
 }
 
-static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
+static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 {
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	struct mtk_tx_dma *desc;
 	struct sk_buff *skb;
 	struct mtk_tx_buf *tx_buf;
-	int total = 0, done = 0;
-	unsigned int bytes = 0;
+	unsigned int bytes = 0, done = 0;
 	u32 cpu, dma;
 	static int condition;
 	int i;
@@ -933,63 +932,82 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
 		netdev_completed_queue(eth->netdev[i], done, bytes);
 	}
 
-	/* read hw index again make sure no new tx packet */
-	if (cpu != dma || cpu != mtk_r32(eth, MTK_QTX_DRX_PTR))
-		*tx_again = true;
-	else
-		mtk_w32(eth, MTK_TX_DONE_INT, MTK_QMTK_INT_STATUS);
-
-	if (!total)
-		return 0;
-
 	if (mtk_queue_stopped(eth) &&
 	    (atomic_read(&ring->free_count) > ring->thresh))
 		mtk_wake_queue(eth);
 
-	return total;
+	return done;
 }
 
-static int mtk_poll(struct napi_struct *napi, int budget)
+static void mtk_handle_status_irq(struct mtk_eth *eth)
 {
-	struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
-	u32 status, status2, mask;
-	int tx_done, rx_done;
-	bool tx_again = false;
-
-	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
-	status2 = mtk_r32(eth, MTK_INT_STATUS2);
-	tx_done = 0;
-	rx_done = 0;
-	tx_again = 0;
-
-	if (status & MTK_TX_DONE_INT)
-		tx_done = mtk_poll_tx(eth, budget, &tx_again);
-
-	if (status & MTK_RX_DONE_INT)
-		rx_done = mtk_poll_rx(napi, budget, eth);
+	u32 status2 = mtk_r32(eth, MTK_INT_STATUS2);
 
 	if (unlikely(status2 & (MTK_GDM1_AF | MTK_GDM2_AF))) {
 		mtk_stats_update(eth);
 		mtk_w32(eth, (MTK_GDM1_AF | MTK_GDM2_AF),
 			MTK_INT_STATUS2);
 	}
+}
+
+static int mtk_napi_tx(struct napi_struct *napi, int budget)
+{
+	struct mtk_eth *eth = container_of(napi, struct mtk_eth, tx_napi);
+	u32 status, mask;
+	int tx_done = 0;
+
+	mtk_handle_status_irq(eth);
+	mtk_w32(eth, MTK_TX_DONE_INT, MTK_QMTK_INT_STATUS);
+	tx_done = mtk_poll_tx(eth, budget);
+
+	if (unlikely(netif_msg_intr(eth))) {
+		status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
+		mask = mtk_r32(eth, MTK_QDMA_INT_MASK);
+		dev_info(eth->dev,
+			 "done tx %d, intr 0x%08x/0x%x\n",
+			 tx_done, status, mask);
+	}
+
+	if (tx_done == budget)
+		return budget;
+
+	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
+	if (status & MTK_TX_DONE_INT)
+		return budget;
+
+	napi_complete(napi);
+	mtk_irq_enable(eth, MTK_TX_DONE_INT);
+
+	return tx_done;
+}
+
+static int mtk_napi_rx(struct napi_struct *napi, int budget)
+{
+	struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
+	u32 status, mask;
+	int rx_done = 0;
+
+	mtk_handle_status_irq(eth);
+	mtk_w32(eth, MTK_RX_DONE_INT, MTK_QMTK_INT_STATUS);
+	rx_done = mtk_poll_rx(napi, budget, eth);
 
 	if (unlikely(netif_msg_intr(eth))) {
+		status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
 		mask = mtk_r32(eth, MTK_QDMA_INT_MASK);
-		netdev_info(eth->netdev[0],
-			    "done tx %d, rx %d, intr 0x%08x/0x%x\n",
-			    tx_done, rx_done, status, mask);
+		dev_info(eth->dev,
+			 "done rx %d, intr 0x%08x/0x%x\n",
+			 rx_done, status, mask);
 	}
 
-	if (tx_again || rx_done == budget)
+	if (rx_done == budget)
 		return budget;
 
 	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
-	if (status & (tx_intr | rx_intr))
+	if (status & MTK_RX_DONE_INT)
 		return budget;
 
 	napi_complete(napi);
-	mtk_irq_enable(eth, MTK_RX_DONE_INT | MTK_RX_DONE_INT);
+	mtk_irq_enable(eth, MTK_RX_DONE_INT);
 
 	return rx_done;
 }
@@ -1225,22 +1243,26 @@ static void mtk_tx_timeout(struct net_device *dev)
 	schedule_work(&eth->pending_work);
 }
 
-static irqreturn_t mtk_handle_irq(int irq, void *_eth)
+static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
 {
 	struct mtk_eth *eth = _eth;
-	u32 status;
 
-	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
-	if (unlikely(!status))
-		return IRQ_NONE;
+	if (likely(napi_schedule_prep(&eth->rx_napi))) {
+		__napi_schedule(&eth->rx_napi);
+		mtk_irq_disable(eth, MTK_RX_DONE_INT);
+	}
 
-	if (likely(status & (MTK_RX_DONE_INT | MTK_TX_DONE_INT))) {
-		if (likely(napi_schedule_prep(&eth->rx_napi)))
-			__napi_schedule(&eth->rx_napi);
-	} else {
-		mtk_w32(eth, status, MTK_QMTK_INT_STATUS);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
+{
+	struct mtk_eth *eth = _eth;
+
+	if (likely(napi_schedule_prep(&eth->tx_napi))) {
+		__napi_schedule(&eth->tx_napi);
+		mtk_irq_disable(eth, MTK_TX_DONE_INT);
 	}
-	mtk_irq_disable(eth, (MTK_RX_DONE_INT | MTK_TX_DONE_INT));
 
 	return IRQ_HANDLED;
 }
@@ -1253,7 +1275,7 @@ static void mtk_poll_controller(struct net_device *dev)
 	u32 int_mask = MTK_TX_DONE_INT | MTK_RX_DONE_INT;
 
 	mtk_irq_disable(eth, int_mask);
-	mtk_handle_irq(dev->irq, dev);
+	mtk_handle_irq(dev->irq[0], dev);
 	mtk_irq_enable(eth, int_mask);
 }
 #endif
@@ -1289,6 +1311,7 @@ static int mtk_open(struct net_device *dev)
 		if (err)
 			return err;
 
+		napi_enable(&eth->tx_napi);
 		napi_enable(&eth->rx_napi);
 		mtk_irq_enable(eth, MTK_TX_DONE_INT | MTK_RX_DONE_INT);
 	}
@@ -1337,6 +1360,7 @@ static int mtk_stop(struct net_device *dev)
 		return 0;
 
 	mtk_irq_disable(eth, MTK_TX_DONE_INT | MTK_RX_DONE_INT);
+	napi_disable(&eth->tx_napi);
 	napi_disable(&eth->rx_napi);
 
 	mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
@@ -1374,7 +1398,11 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 	/* Enable RX VLan Offloading */
 	mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
-	err = devm_request_irq(eth->dev, eth->irq, mtk_handle_irq, 0,
+	err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+			       dev_name(eth->dev), eth);
+	if (err)
+		return err;
+	err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
 			       dev_name(eth->dev), eth);
 	if (err)
 		return err;
@@ -1390,7 +1418,11 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 	mtk_w32(eth, 0, MTK_RST_GL);
 
 	/* FE int grouping */
-	mtk_w32(eth, 0, MTK_FE_INT_GRP);
+	mtk_w32(eth, MTK_TX_DONE_INT, MTK_PDMA_INT_GRP1);
+	mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_GRP2);
+	mtk_w32(eth, MTK_TX_DONE_INT, MTK_QDMA_INT_GRP1);
+	mtk_w32(eth, MTK_RX_DONE_INT, MTK_QDMA_INT_GRP2);
+	mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
 
 	for (i = 0; i < 2; i++) {
 		u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i));
@@ -1438,7 +1470,9 @@ static void mtk_uninit(struct net_device *dev)
 	phy_disconnect(mac->phy_dev);
 	mtk_mdio_cleanup(eth);
 	mtk_irq_disable(eth, ~0);
-	free_irq(dev->irq, dev);
+	free_irq(eth->irq[0], dev);
+	free_irq(eth->irq[1], dev);
+	free_irq(eth->irq[2], dev);
 }
 
 static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1712,10 +1746,10 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 		dev_err(eth->dev, "error bringing up device\n");
 		goto free_netdev;
 	}
-	eth->netdev[id]->irq = eth->irq;
+	eth->netdev[id]->irq = eth->irq[0];
 	netif_info(eth, probe, eth->netdev[id],
 		   "mediatek frame engine at 0x%08lx, irq %d\n",
-		   eth->netdev[id]->base_addr, eth->netdev[id]->irq);
+		   eth->netdev[id]->base_addr, eth->irq[0]);
 
 	return 0;
 
@@ -1732,6 +1766,7 @@ static int mtk_probe(struct platform_device *pdev)
 	struct mtk_soc_data *soc;
 	struct mtk_eth *eth;
 	int err;
+	int i;
 
 	match = of_match_device(of_mtk_match, &pdev->dev);
 	soc = (struct mtk_soc_data *)match->data;
@@ -1767,10 +1802,12 @@ static int mtk_probe(struct platform_device *pdev)
 		return PTR_ERR(eth->rstc);
 	}
 
-	eth->irq = platform_get_irq(pdev, 0);
-	if (eth->irq < 0) {
-		dev_err(&pdev->dev, "no IRQ resource found\n");
-		return -ENXIO;
+	for (i = 0; i < 3; i++) {
+		eth->irq[i] = platform_get_irq(pdev, i);
+		if (eth->irq[i] < 0) {
+			dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
+			return -ENXIO;
+		}
 	}
 
 	eth->clk_ethif = devm_clk_get(&pdev->dev, "ethif");
@@ -1811,7 +1848,9 @@ static int mtk_probe(struct platform_device *pdev)
 	 * for NAPI to work
 	 */
 	init_dummy_netdev(&eth->dummy_dev);
-	netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_poll,
+	netif_napi_add(&eth->dummy_dev, &eth->tx_napi, mtk_napi_tx,
+		       MTK_NAPI_WEIGHT);
+	netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_napi_rx,
 		       MTK_NAPI_WEIGHT);
 
 	platform_set_drvdata(pdev, eth);
@@ -1832,6 +1871,7 @@ static int mtk_remove(struct platform_device *pdev)
 	clk_disable_unprepare(eth->clk_gp1);
 	clk_disable_unprepare(eth->clk_gp2);
 
+	netif_napi_del(&eth->tx_napi);
 	netif_napi_del(&eth->rx_napi);
 	mtk_cleanup(eth);
 	platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 3159d2a..f82e3ac 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -68,6 +68,10 @@
 /* Unicast Filter MAC Address Register - High */
 #define MTK_GDMA_MAC_ADRH(x)	(0x50C + (x * 0x1000))
 
+/* PDMA Interrupt grouping registers */
+#define MTK_PDMA_INT_GRP1	0xa50
+#define MTK_PDMA_INT_GRP2	0xa54
+
 /* QDMA TX Queue Configuration Registers */
 #define MTK_QTX_CFG(x)		(0x1800 + (x * 0x10))
 #define QDMA_RES_THRES		4
@@ -125,6 +129,11 @@
 #define MTK_TX_DONE_INT		(MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
 				 MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
 
+/* QDMA Interrupt grouping registers */
+#define MTK_QDMA_INT_GRP1	0x1a20
+#define MTK_QDMA_INT_GRP2	0x1a24
+#define MTK_RLS_DONE_INT	BIT(0)
+
 /* QDMA Interrupt Status Register */
 #define MTK_QDMA_INT_MASK	0x1A1C
 
@@ -356,7 +365,8 @@ struct mtk_rx_ring {
  * @dma_refcnt:		track how many netdevs are using the DMA engine
  * @tx_ring:		Pointer to the memore holding info about the TX ring
  * @rx_ring:		Pointer to the memore holding info about the RX ring
- * @rx_napi:		The NAPI struct
+ * @tx_napi:		The TX NAPI struct
+ * @rx_napi:		The RX NAPI struct
  * @scratch_ring:	Newer SoCs need memory for a second HW managed TX ring
  * @phy_scratch_ring:	physical address of scratch_ring
  * @scratch_head:	The scratch memory that scratch_ring points to.
@@ -377,7 +387,7 @@ struct mtk_eth {
 	struct net_device		dummy_dev;
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
-	int				irq;
+	int				irq[3];
 	u32				msg_enable;
 	unsigned long			sysclk;
 	struct regmap			*ethsys;
@@ -385,6 +395,7 @@ struct mtk_eth {
 	atomic_t			dma_refcnt;
 	struct mtk_tx_ring		tx_ring;
 	struct mtk_rx_ring		rx_ring;
+	struct napi_struct		tx_napi;
 	struct napi_struct		rx_napi;
 	struct mtk_tx_dma		*scratch_ring;
 	dma_addr_t			phy_scratch_ring;
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping
  2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
                   ` (3 preceding siblings ...)
  2016-06-15 14:58 ` [PATCH 4/4] net-next: mediatek: add support for IRQ grouping John Crispin
@ 2016-06-16  5:20 ` David Miller
  2016-06-16  9:44   ` John Crispin
  4 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2016-06-16  5:20 UTC (permalink / raw)
  To: john; +Cc: nbd, keyhaede, netdev, linux-mediatek, linux-kernel

From: John Crispin <john@phrozen.org>
Date: Wed, 15 Jun 2016 16:58:46 +0200

> This series contains 2 small code cleanups that are leftovers from the
> MIPS support. There is also a small fix that adds proper locking to the
> code accessing the IRQ registers. Without this fix we saw deadlocks caused
> by the last patch of the series, which adds IRQ grouping. The grouping
> feature allows us to use different IRQs for TX and RX. By doing so we can
> use affinity to let the SoC handle the IRQs on different cores.

This patch series doesn't apply cleanly to the net-next tree, I get rejects
on patch #4.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping
  2016-06-16  5:20 ` [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping David Miller
@ 2016-06-16  9:44   ` John Crispin
  2016-06-16  9:51     ` Daniel Borkmann
  2016-06-17  0:27     ` David Miller
  0 siblings, 2 replies; 9+ messages in thread
From: John Crispin @ 2016-06-16  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-mediatek, keyhaede, linux-kernel, nbd



On 16/06/2016 07:20, David Miller wrote:
> From: John Crispin <john@phrozen.org>
> Date: Wed, 15 Jun 2016 16:58:46 +0200
> 
>> This series contains 2 small code cleanups that are leftovers from the
>> MIPS support. There is also a small fix that adds proper locking to the
>> code accessing the IRQ registers. Without this fix we saw deadlocks caused
>> by the last patch of the series, which adds IRQ grouping. The grouping
>> feature allows us to use different IRQs for TX and RX. By doing so we can
>> use affinity to let the SoC handle the IRQs on different cores.
> 
> This patch series doesn't apply cleanly to the net-next tree, I get rejects
> on patch #4.
> 

it depends on the series with the 11 fixes that i sent last week which
is however in the net tree and not the next tree (i also still had the
DQL hack in my tree). if i resend this at the start of the next rc1
would you merge it into the net tree so that it becomes part of v4.8 ?

	John

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping
  2016-06-16  9:44   ` John Crispin
@ 2016-06-16  9:51     ` Daniel Borkmann
  2016-06-17  0:27     ` David Miller
  1 sibling, 0 replies; 9+ messages in thread
From: Daniel Borkmann @ 2016-06-16  9:51 UTC (permalink / raw)
  To: John Crispin, David Miller
  Cc: netdev, linux-mediatek, keyhaede, linux-kernel, nbd

On 06/16/2016 11:44 AM, John Crispin wrote:
> On 16/06/2016 07:20, David Miller wrote:
>> From: John Crispin <john@phrozen.org>
>> Date: Wed, 15 Jun 2016 16:58:46 +0200
>>
>>> This series contains 2 small code cleanups that are leftovers from the
>>> MIPS support. There is also a small fix that adds proper locking to the
>>> code accessing the IRQ registers. Without this fix we saw deadlocks caused
>>> by the last patch of the series, which adds IRQ grouping. The grouping
>>> feature allows us to use different IRQs for TX and RX. By doing so we can
>>> use affinity to let the SoC handle the IRQs on different cores.
>>
>> This patch series doesn't apply cleanly to the net-next tree, I get rejects
>> on patch #4.
>
> it depends on the series with the 11 fixes that i sent last week which
> is however in the net tree and not the next tree (i also still had the
> DQL hack in my tree). if i resend this at the start of the next rc1
> would you merge it into the net tree so that it becomes part of v4.8 ?

Well, it would rather require a merge of -net into -net-next then. But
that would be useful indeed.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping
  2016-06-16  9:44   ` John Crispin
  2016-06-16  9:51     ` Daniel Borkmann
@ 2016-06-17  0:27     ` David Miller
  1 sibling, 0 replies; 9+ messages in thread
From: David Miller @ 2016-06-17  0:27 UTC (permalink / raw)
  To: john; +Cc: netdev, linux-mediatek, keyhaede, linux-kernel, nbd

From: John Crispin <john@phrozen.org>
Date: Thu, 16 Jun 2016 11:44:44 +0200

> 
> 
> On 16/06/2016 07:20, David Miller wrote:
>> From: John Crispin <john@phrozen.org>
>> Date: Wed, 15 Jun 2016 16:58:46 +0200
>> 
>>> This series contains 2 small code cleanups that are leftovers from the
>>> MIPS support. There is also a small fix that adds proper locking to the
>>> code accessing the IRQ registers. Without this fix we saw deadlocks caused
>>> by the last patch of the series, which adds IRQ grouping. The grouping
>>> feature allows us to use different IRQs for TX and RX. By doing so we can
>>> use affinity to let the SoC handle the IRQs on different cores.
>> 
>> This patch series doesn't apply cleanly to the net-next tree, I get rejects
>> on patch #4.
>> 
> 
> it depends on the series with the 11 fixes that i sent last week which
> is however in the net tree and not the next tree (i also still had the
> DQL hack in my tree).

Then you need to tell me about such dependencies in your submission.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-06-17  0:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-15 14:58 [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping John Crispin
2016-06-15 14:58 ` [PATCH 1/4] net-next: mediatek: remove superfluous register reads John Crispin
2016-06-15 14:58 ` [PATCH 2/4] net-next: mediatek: don't use intermediate variables to store IRQ masks John Crispin
2016-06-15 14:58 ` [PATCH 3/4] net-next: mediatek: add IRQ locking John Crispin
2016-06-15 14:58 ` [PATCH 4/4] net-next: mediatek: add support for IRQ grouping John Crispin
2016-06-16  5:20 ` [PATCH 0/4] net-next: mediatek: IRQ cleanups, fixes and grouping David Miller
2016-06-16  9:44   ` John Crispin
2016-06-16  9:51     ` Daniel Borkmann
2016-06-17  0:27     ` David Miller

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).