Commit 5cce0322 authored by John Crispin's avatar John Crispin Committed by David S. Miller

net-next: mediatek: split IRQ register locking into TX and RX

Originally the driver only utilised the new QDMA engine. The current code
still assumes this is the case when locking the IRQ mask register. Since
RX now runs on the old style PDMA engine we can add a second lock. This
patch reduces the IRQ latency as the TX and RX path no longer need to wait
on each other under heavy load.
Signed-off-by: default avatarJohn Crispin <john@phrozen.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 671d41e6
...@@ -372,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth) ...@@ -372,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
mdiobus_unregister(eth->mii_bus); mdiobus_unregister(eth->mii_bus);
} }
static inline void mtk_irq_disable(struct mtk_eth *eth, static inline void mtk_tx_irq_disable(struct mtk_eth *eth, u32 mask)
unsigned reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
u32 val; u32 val;
spin_lock_irqsave(&eth->irq_lock, flags); spin_lock_irqsave(&eth->tx_irq_lock, flags);
val = mtk_r32(eth, reg); val = mtk_r32(eth, MTK_QDMA_INT_MASK);
mtk_w32(eth, val & ~mask, reg); mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK);
spin_unlock_irqrestore(&eth->irq_lock, flags); spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
} }
static inline void mtk_irq_enable(struct mtk_eth *eth, static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask)
unsigned reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
u32 val; u32 val;
spin_lock_irqsave(&eth->irq_lock, flags); spin_lock_irqsave(&eth->tx_irq_lock, flags);
val = mtk_r32(eth, reg); val = mtk_r32(eth, MTK_QDMA_INT_MASK);
mtk_w32(eth, val | mask, reg); mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK);
spin_unlock_irqrestore(&eth->irq_lock, flags); spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
}
static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&eth->rx_irq_lock, flags);
val = mtk_r32(eth, MTK_PDMA_INT_MASK);
mtk_w32(eth, val & ~mask, MTK_PDMA_INT_MASK);
spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
}
static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&eth->rx_irq_lock, flags);
val = mtk_r32(eth, MTK_PDMA_INT_MASK);
mtk_w32(eth, val | mask, MTK_PDMA_INT_MASK);
spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
} }
static int mtk_set_mac_address(struct net_device *dev, void *p) static int mtk_set_mac_address(struct net_device *dev, void *p)
...@@ -1101,7 +1121,7 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget) ...@@ -1101,7 +1121,7 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget)
return budget; return budget;
napi_complete(napi); napi_complete(napi);
mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
return tx_done; return tx_done;
} }
...@@ -1135,7 +1155,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget) ...@@ -1135,7 +1155,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget)
goto poll_again; goto poll_again;
} }
napi_complete(napi); napi_complete(napi);
mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
return rx_done + budget - remain_budget; return rx_done + budget - remain_budget;
} }
...@@ -1670,7 +1690,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) ...@@ -1670,7 +1690,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
if (likely(napi_schedule_prep(&eth->rx_napi))) { if (likely(napi_schedule_prep(&eth->rx_napi))) {
__napi_schedule(&eth->rx_napi); __napi_schedule(&eth->rx_napi);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1682,7 +1702,7 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) ...@@ -1682,7 +1702,7 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
if (likely(napi_schedule_prep(&eth->tx_napi))) { if (likely(napi_schedule_prep(&eth->tx_napi))) {
__napi_schedule(&eth->tx_napi); __napi_schedule(&eth->tx_napi);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1694,11 +1714,11 @@ static void mtk_poll_controller(struct net_device *dev) ...@@ -1694,11 +1714,11 @@ static void mtk_poll_controller(struct net_device *dev)
struct mtk_mac *mac = netdev_priv(dev); struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw; struct mtk_eth *eth = mac->hw;
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
mtk_handle_irq_rx(eth->irq[2], dev); mtk_handle_irq_rx(eth->irq[2], dev);
mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
} }
#endif #endif
...@@ -1739,8 +1759,8 @@ static int mtk_open(struct net_device *dev) ...@@ -1739,8 +1759,8 @@ static int mtk_open(struct net_device *dev)
napi_enable(&eth->tx_napi); napi_enable(&eth->tx_napi);
napi_enable(&eth->rx_napi); napi_enable(&eth->rx_napi);
mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
} }
atomic_inc(&eth->dma_refcnt); atomic_inc(&eth->dma_refcnt);
...@@ -1785,8 +1805,8 @@ static int mtk_stop(struct net_device *dev) ...@@ -1785,8 +1805,8 @@ static int mtk_stop(struct net_device *dev)
if (!atomic_dec_and_test(&eth->dma_refcnt)) if (!atomic_dec_and_test(&eth->dma_refcnt))
return 0; return 0;
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
napi_disable(&eth->tx_napi); napi_disable(&eth->tx_napi);
napi_disable(&eth->rx_napi); napi_disable(&eth->rx_napi);
...@@ -1866,8 +1886,8 @@ static int mtk_hw_init(struct mtk_eth *eth) ...@@ -1866,8 +1886,8 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* disable delay and normal interrupt */ /* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); mtk_tx_irq_disable(eth, ~0);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); mtk_rx_irq_disable(eth, ~0);
mtk_w32(eth, RST_GL_PSE, MTK_RST_GL); mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
mtk_w32(eth, 0, MTK_RST_GL); mtk_w32(eth, 0, MTK_RST_GL);
...@@ -1938,8 +1958,8 @@ static void mtk_uninit(struct net_device *dev) ...@@ -1938,8 +1958,8 @@ static void mtk_uninit(struct net_device *dev)
phy_disconnect(dev->phydev); phy_disconnect(dev->phydev);
if (of_phy_is_fixed_link(mac->of_node)) if (of_phy_is_fixed_link(mac->of_node))
of_phy_deregister_fixed_link(mac->of_node); of_phy_deregister_fixed_link(mac->of_node);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); mtk_tx_irq_disable(eth, ~0);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); mtk_rx_irq_disable(eth, ~0);
} }
static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
...@@ -2399,7 +2419,8 @@ static int mtk_probe(struct platform_device *pdev) ...@@ -2399,7 +2419,8 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->base); return PTR_ERR(eth->base);
spin_lock_init(&eth->page_lock); spin_lock_init(&eth->page_lock);
spin_lock_init(&eth->irq_lock); spin_lock_init(&eth->tx_irq_lock);
spin_lock_init(&eth->rx_irq_lock);
eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"mediatek,ethsys"); "mediatek,ethsys");
......
...@@ -519,6 +519,8 @@ struct mtk_rx_ring { ...@@ -519,6 +519,8 @@ struct mtk_rx_ring {
* @dev: The device pointer * @dev: The device pointer
* @base: The mapped register i/o base * @base: The mapped register i/o base
* @page_lock: Make sure that register operations are atomic * @page_lock: Make sure that register operations are atomic
* @tx_irq__lock: Make sure that IRQ register operations are atomic
* @rx_irq__lock: Make sure that IRQ register operations are atomic
* @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a
* dummy for NAPI to work * dummy for NAPI to work
* @netdev: The netdev instances * @netdev: The netdev instances
...@@ -547,7 +549,8 @@ struct mtk_eth { ...@@ -547,7 +549,8 @@ struct mtk_eth {
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
spinlock_t page_lock; spinlock_t page_lock;
spinlock_t irq_lock; spinlock_t tx_irq_lock;
spinlock_t rx_irq_lock;
struct net_device dummy_dev; struct net_device dummy_dev;
struct net_device *netdev[MTK_MAX_DEVS]; struct net_device *netdev[MTK_MAX_DEVS];
struct mtk_mac *mac[MTK_MAX_DEVS]; struct mtk_mac *mac[MTK_MAX_DEVS];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment