Commit 7145074b authored by David S. Miller's avatar David S. Miller

Merge branch 'bcmgenet-next'

Petri Gynther says:

====================
net: bcmgenet: multiple Rx queues support

Final patch set to add support for multiple Rx queues:
1. remove priv->int0_mask and priv->int1_mask
2. modify Tx ring int_enable and int_disable vectors
3. simplify bcmgenet_init_dma()
4. tweak init_umac()
5. rework Tx NAPI code
6. rework Rx NAPI code
7. add support for multiple Rx queues
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 19cc2dec 4055eaef
...@@ -964,36 +964,58 @@ static void bcmgenet_free_cb(struct enet_cb *cb) ...@@ -964,36 +964,58 @@ static void bcmgenet_free_cb(struct enet_cb *cb)
dma_unmap_addr_set(cb, dma_addr, 0); dma_unmap_addr_set(cb, dma_addr, 0);
} }
static inline void bcmgenet_tx_ring16_int_disable(struct bcmgenet_priv *priv, static inline void bcmgenet_rx_ring16_int_disable(struct bcmgenet_rx_ring *ring)
struct bcmgenet_tx_ring *ring)
{ {
bcmgenet_intrl2_0_writel(priv, bcmgenet_intrl2_0_writel(ring->priv,
UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE,
INTRL2_CPU_MASK_SET);
}
static inline void bcmgenet_rx_ring16_int_enable(struct bcmgenet_rx_ring *ring)
{
bcmgenet_intrl2_0_writel(ring->priv,
UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE,
INTRL2_CPU_MASK_CLEAR);
}
static inline void bcmgenet_rx_ring_int_disable(struct bcmgenet_rx_ring *ring)
{
bcmgenet_intrl2_1_writel(ring->priv,
1 << (UMAC_IRQ1_RX_INTR_SHIFT + ring->index),
INTRL2_CPU_MASK_SET);
}
static inline void bcmgenet_rx_ring_int_enable(struct bcmgenet_rx_ring *ring)
{
bcmgenet_intrl2_1_writel(ring->priv,
1 << (UMAC_IRQ1_RX_INTR_SHIFT + ring->index),
INTRL2_CPU_MASK_CLEAR);
}
static inline void bcmgenet_tx_ring16_int_disable(struct bcmgenet_tx_ring *ring)
{
bcmgenet_intrl2_0_writel(ring->priv,
UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE, UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
INTRL2_CPU_MASK_SET); INTRL2_CPU_MASK_SET);
} }
static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_priv *priv, static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_tx_ring *ring)
struct bcmgenet_tx_ring *ring)
{ {
bcmgenet_intrl2_0_writel(priv, bcmgenet_intrl2_0_writel(ring->priv,
UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE, UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
INTRL2_CPU_MASK_CLEAR); INTRL2_CPU_MASK_CLEAR);
} }
static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_priv *priv, static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_tx_ring *ring)
struct bcmgenet_tx_ring *ring)
{ {
bcmgenet_intrl2_1_writel(priv, (1 << ring->index), bcmgenet_intrl2_1_writel(ring->priv, 1 << ring->index,
INTRL2_CPU_MASK_CLEAR); INTRL2_CPU_MASK_CLEAR);
priv->int1_mask &= ~(1 << ring->index);
} }
static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_tx_ring *ring)
struct bcmgenet_tx_ring *ring)
{ {
bcmgenet_intrl2_1_writel(priv, (1 << ring->index), bcmgenet_intrl2_1_writel(ring->priv, 1 << ring->index,
INTRL2_CPU_MASK_SET); INTRL2_CPU_MASK_SET);
priv->int1_mask |= (1 << ring->index);
} }
/* Unlocked version of the reclaim routine */ /* Unlocked version of the reclaim routine */
...@@ -1085,7 +1107,7 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) ...@@ -1085,7 +1107,7 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
if (work_done == 0) { if (work_done == 0) {
napi_complete(napi); napi_complete(napi);
ring->int_enable(ring->priv, ring); ring->int_enable(ring);
return 0; return 0;
} }
...@@ -1396,11 +1418,10 @@ static struct sk_buff *bcmgenet_rx_refill(struct bcmgenet_priv *priv, ...@@ -1396,11 +1418,10 @@ static struct sk_buff *bcmgenet_rx_refill(struct bcmgenet_priv *priv,
/* bcmgenet_desc_rx - descriptor based rx process. /* bcmgenet_desc_rx - descriptor based rx process.
* this could be called from bottom half, or from NAPI polling method. * this could be called from bottom half, or from NAPI polling method.
*/ */
static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
unsigned int index,
unsigned int budget) unsigned int budget)
{ {
struct bcmgenet_rx_ring *ring = &priv->rx_rings[index]; struct bcmgenet_priv *priv = ring->priv;
struct net_device *dev = priv->dev; struct net_device *dev = priv->dev;
struct enet_cb *cb; struct enet_cb *cb;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1412,7 +1433,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, ...@@ -1412,7 +1433,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
unsigned int discards; unsigned int discards;
unsigned int chksum_ok = 0; unsigned int chksum_ok = 0;
p_index = bcmgenet_rdma_ring_readl(priv, index, RDMA_PROD_INDEX); p_index = bcmgenet_rdma_ring_readl(priv, ring->index, RDMA_PROD_INDEX);
discards = (p_index >> DMA_P_INDEX_DISCARD_CNT_SHIFT) & discards = (p_index >> DMA_P_INDEX_DISCARD_CNT_SHIFT) &
DMA_P_INDEX_DISCARD_CNT_MASK; DMA_P_INDEX_DISCARD_CNT_MASK;
...@@ -1425,7 +1446,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, ...@@ -1425,7 +1446,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
/* Clear HW register when we reach 75% of maximum 0xFFFF */ /* Clear HW register when we reach 75% of maximum 0xFFFF */
if (ring->old_discards >= 0xC000) { if (ring->old_discards >= 0xC000) {
ring->old_discards = 0; ring->old_discards = 0;
bcmgenet_rdma_ring_writel(priv, index, 0, bcmgenet_rdma_ring_writel(priv, ring->index, 0,
RDMA_PROD_INDEX); RDMA_PROD_INDEX);
} }
} }
...@@ -1533,7 +1554,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, ...@@ -1533,7 +1554,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
dev->stats.multicast++; dev->stats.multicast++;
/* Notify kernel */ /* Notify kernel */
napi_gro_receive(&priv->napi, skb); napi_gro_receive(&ring->napi, skb);
netif_dbg(priv, rx_status, dev, "pushed up to kernel\n"); netif_dbg(priv, rx_status, dev, "pushed up to kernel\n");
next: next:
...@@ -1544,12 +1565,29 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, ...@@ -1544,12 +1565,29 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
ring->read_ptr = ring->cb_ptr; ring->read_ptr = ring->cb_ptr;
ring->c_index = (ring->c_index + 1) & DMA_C_INDEX_MASK; ring->c_index = (ring->c_index + 1) & DMA_C_INDEX_MASK;
bcmgenet_rdma_ring_writel(priv, index, ring->c_index, RDMA_CONS_INDEX); bcmgenet_rdma_ring_writel(priv, ring->index, ring->c_index, RDMA_CONS_INDEX);
} }
return rxpktprocessed; return rxpktprocessed;
} }
/* Rx NAPI polling method */
static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
{
struct bcmgenet_rx_ring *ring = container_of(napi,
struct bcmgenet_rx_ring, napi);
unsigned int work_done;
work_done = bcmgenet_desc_rx(ring, budget);
if (work_done < budget) {
napi_complete(napi);
ring->int_enable(ring);
}
return work_done;
}
/* Assign skb to RX DMA descriptor. */ /* Assign skb to RX DMA descriptor. */
static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv, static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv,
struct bcmgenet_rx_ring *ring) struct bcmgenet_rx_ring *ring)
...@@ -1658,8 +1696,10 @@ static int init_umac(struct bcmgenet_priv *priv) ...@@ -1658,8 +1696,10 @@ static int init_umac(struct bcmgenet_priv *priv)
{ {
struct device *kdev = &priv->pdev->dev; struct device *kdev = &priv->pdev->dev;
int ret; int ret;
u32 reg, cpu_mask_clear; u32 reg;
int index; u32 int0_enable = 0;
u32 int1_enable = 0;
int i;
dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n"); dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n");
...@@ -1686,15 +1726,17 @@ static int init_umac(struct bcmgenet_priv *priv) ...@@ -1686,15 +1726,17 @@ static int init_umac(struct bcmgenet_priv *priv)
bcmgenet_intr_disable(priv); bcmgenet_intr_disable(priv);
cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; /* Enable Rx default queue 16 interrupts */
int0_enable |= (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE);
dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__); /* Enable Tx default queue 16 interrupts */
int0_enable |= (UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE);
/* Monitor cable plug/unplugged event for internal PHY */ /* Monitor cable plug/unplugged event for internal PHY */
if (phy_is_internal(priv->phydev)) { if (phy_is_internal(priv->phydev)) {
cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP); int0_enable |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
} else if (priv->ext_phy) { } else if (priv->ext_phy) {
cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP); int0_enable |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
reg = bcmgenet_bp_mc_get(priv); reg = bcmgenet_bp_mc_get(priv);
reg |= BIT(priv->hw_params->bp_in_en_shift); reg |= BIT(priv->hw_params->bp_in_en_shift);
...@@ -1709,13 +1751,18 @@ static int init_umac(struct bcmgenet_priv *priv) ...@@ -1709,13 +1751,18 @@ static int init_umac(struct bcmgenet_priv *priv)
/* Enable MDIO interrupts on GENET v3+ */ /* Enable MDIO interrupts on GENET v3+ */
if (priv->hw_params->flags & GENET_HAS_MDIO_INTR) if (priv->hw_params->flags & GENET_HAS_MDIO_INTR)
cpu_mask_clear |= UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR; int0_enable |= (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
/* Enable Rx priority queue interrupts */
for (i = 0; i < priv->hw_params->rx_queues; ++i)
int1_enable |= (1 << (UMAC_IRQ1_RX_INTR_SHIFT + i));
bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); /* Enable Tx priority queue interrupts */
for (i = 0; i < priv->hw_params->tx_queues; ++i)
int1_enable |= (1 << i);
for (index = 0; index < priv->hw_params->tx_queues; index++) bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
bcmgenet_intrl2_1_writel(priv, (1 << index), bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
INTRL2_CPU_MASK_CLEAR);
/* Enable rx/tx engine.*/ /* Enable rx/tx engine.*/
dev_dbg(kdev, "done init umac\n"); dev_dbg(kdev, "done init umac\n");
...@@ -1734,7 +1781,6 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, ...@@ -1734,7 +1781,6 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
spin_lock_init(&ring->lock); spin_lock_init(&ring->lock);
ring->priv = priv; ring->priv = priv;
netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
ring->index = index; ring->index = index;
if (index == DESC_INDEX) { if (index == DESC_INDEX) {
ring->queue = 0; ring->queue = 0;
...@@ -1778,17 +1824,6 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, ...@@ -1778,17 +1824,6 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
TDMA_WRITE_PTR); TDMA_WRITE_PTR);
bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1, bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
DMA_END_ADDR); DMA_END_ADDR);
napi_enable(&ring->napi);
}
static void bcmgenet_fini_tx_ring(struct bcmgenet_priv *priv,
unsigned int index)
{
struct bcmgenet_tx_ring *ring = &priv->tx_rings[index];
napi_disable(&ring->napi);
netif_napi_del(&ring->napi);
} }
/* Initialize a RDMA ring */ /* Initialize a RDMA ring */
...@@ -1800,7 +1835,15 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv, ...@@ -1800,7 +1835,15 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
u32 words_per_bd = WORDS_PER_BD(priv); u32 words_per_bd = WORDS_PER_BD(priv);
int ret; int ret;
ring->priv = priv;
ring->index = index; ring->index = index;
if (index == DESC_INDEX) {
ring->int_enable = bcmgenet_rx_ring16_int_enable;
ring->int_disable = bcmgenet_rx_ring16_int_disable;
} else {
ring->int_enable = bcmgenet_rx_ring_int_enable;
ring->int_disable = bcmgenet_rx_ring_int_disable;
}
ring->cbs = priv->rx_cbs + start_ptr; ring->cbs = priv->rx_cbs + start_ptr;
ring->size = size; ring->size = size;
ring->c_index = 0; ring->c_index = 0;
...@@ -1836,6 +1879,62 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv, ...@@ -1836,6 +1879,62 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
return ret; return ret;
} }
static void bcmgenet_init_tx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_tx_ring *ring;
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
ring = &priv->tx_rings[i];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
}
ring = &priv->tx_rings[DESC_INDEX];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
}
static void bcmgenet_enable_tx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_tx_ring *ring;
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
ring = &priv->tx_rings[i];
napi_enable(&ring->napi);
}
ring = &priv->tx_rings[DESC_INDEX];
napi_enable(&ring->napi);
}
static void bcmgenet_disable_tx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_tx_ring *ring;
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
ring = &priv->tx_rings[i];
napi_disable(&ring->napi);
}
ring = &priv->tx_rings[DESC_INDEX];
napi_disable(&ring->napi);
}
static void bcmgenet_fini_tx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_tx_ring *ring;
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
ring = &priv->tx_rings[i];
netif_napi_del(&ring->napi);
}
ring = &priv->tx_rings[DESC_INDEX];
netif_napi_del(&ring->napi);
}
/* Initialize Tx queues /* Initialize Tx queues
* *
* Queues 0-3 are priority-based, each one has 32 descriptors, * Queues 0-3 are priority-based, each one has 32 descriptors,
...@@ -1896,6 +1995,9 @@ static void bcmgenet_init_tx_queues(struct net_device *dev) ...@@ -1896,6 +1995,9 @@ static void bcmgenet_init_tx_queues(struct net_device *dev)
bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1); bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1);
bcmgenet_tdma_writel(priv, dma_priority[2], DMA_PRIORITY_2); bcmgenet_tdma_writel(priv, dma_priority[2], DMA_PRIORITY_2);
/* Initialize Tx NAPI */
bcmgenet_init_tx_napi(priv);
/* Enable Tx queues */ /* Enable Tx queues */
bcmgenet_tdma_writel(priv, ring_cfg, DMA_RING_CFG); bcmgenet_tdma_writel(priv, ring_cfg, DMA_RING_CFG);
...@@ -1905,6 +2007,62 @@ static void bcmgenet_init_tx_queues(struct net_device *dev) ...@@ -1905,6 +2007,62 @@ static void bcmgenet_init_tx_queues(struct net_device *dev)
bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL); bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL);
} }
static void bcmgenet_init_rx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_rx_ring *ring;
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
ring = &priv->rx_rings[i];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll, 64);
}
ring = &priv->rx_rings[DESC_INDEX];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll, 64);
}
static void bcmgenet_enable_rx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_rx_ring *ring;
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
ring = &priv->rx_rings[i];
napi_enable(&ring->napi);
}
ring = &priv->rx_rings[DESC_INDEX];
napi_enable(&ring->napi);
}
static void bcmgenet_disable_rx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_rx_ring *ring;
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
ring = &priv->rx_rings[i];
napi_disable(&ring->napi);
}
ring = &priv->rx_rings[DESC_INDEX];
napi_disable(&ring->napi);
}
static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
{
unsigned int i;
struct bcmgenet_rx_ring *ring;
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
ring = &priv->rx_rings[i];
netif_napi_del(&ring->napi);
}
ring = &priv->rx_rings[DESC_INDEX];
netif_napi_del(&ring->napi);
}
/* Initialize Rx queues /* Initialize Rx queues
* *
* Queues 0-15 are priority queues. Hardware Filtering Block (HFB) can be * Queues 0-15 are priority queues. Hardware Filtering Block (HFB) can be
...@@ -1954,6 +2112,9 @@ static int bcmgenet_init_rx_queues(struct net_device *dev) ...@@ -1954,6 +2112,9 @@ static int bcmgenet_init_rx_queues(struct net_device *dev)
ring_cfg |= (1 << DESC_INDEX); ring_cfg |= (1 << DESC_INDEX);
dma_ctrl |= (1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT)); dma_ctrl |= (1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT));
/* Initialize Rx NAPI */
bcmgenet_init_rx_napi(priv);
/* Enable rings */ /* Enable rings */
bcmgenet_rdma_writel(priv, ring_cfg, DMA_RING_CFG); bcmgenet_rdma_writel(priv, ring_cfg, DMA_RING_CFG);
...@@ -2037,12 +2198,8 @@ static void __bcmgenet_fini_dma(struct bcmgenet_priv *priv) ...@@ -2037,12 +2198,8 @@ static void __bcmgenet_fini_dma(struct bcmgenet_priv *priv)
static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
{ {
int i; bcmgenet_fini_rx_napi(priv);
bcmgenet_fini_tx_napi(priv);
bcmgenet_fini_tx_ring(priv, DESC_INDEX);
for (i = 0; i < priv->hw_params->tx_queues; i++)
bcmgenet_fini_tx_ring(priv, i);
__bcmgenet_fini_dma(priv); __bcmgenet_fini_dma(priv);
} }
...@@ -2056,9 +2213,6 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) ...@@ -2056,9 +2213,6 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
netif_dbg(priv, hw, priv->dev, "%s\n", __func__); netif_dbg(priv, hw, priv->dev, "%s\n", __func__);
/* Init rDma */
bcmgenet_rdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
/* Initialize common Rx ring structures */ /* Initialize common Rx ring structures */
priv->rx_bds = priv->base + priv->hw_params->rdma_offset; priv->rx_bds = priv->base + priv->hw_params->rdma_offset;
priv->num_rx_bds = TOTAL_DESC; priv->num_rx_bds = TOTAL_DESC;
...@@ -2072,25 +2226,13 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) ...@@ -2072,25 +2226,13 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
cb->bd_addr = priv->rx_bds + i * DMA_DESC_SIZE; cb->bd_addr = priv->rx_bds + i * DMA_DESC_SIZE;
} }
/* Initialize Rx queues */
ret = bcmgenet_init_rx_queues(priv->dev);
if (ret) {
netdev_err(priv->dev, "failed to initialize Rx queues\n");
bcmgenet_free_rx_buffers(priv);
kfree(priv->rx_cbs);
return ret;
}
/* Init tDma */
bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
/* Initialize common TX ring structures */ /* Initialize common TX ring structures */
priv->tx_bds = priv->base + priv->hw_params->tdma_offset; priv->tx_bds = priv->base + priv->hw_params->tdma_offset;
priv->num_tx_bds = TOTAL_DESC; priv->num_tx_bds = TOTAL_DESC;
priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb), priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb),
GFP_KERNEL); GFP_KERNEL);
if (!priv->tx_cbs) { if (!priv->tx_cbs) {
__bcmgenet_fini_dma(priv); kfree(priv->rx_cbs);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2099,28 +2241,26 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) ...@@ -2099,28 +2241,26 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
cb->bd_addr = priv->tx_bds + i * DMA_DESC_SIZE; cb->bd_addr = priv->tx_bds + i * DMA_DESC_SIZE;
} }
/* Initialize Tx queues */ /* Init rDma */
bcmgenet_init_tx_queues(priv->dev); bcmgenet_rdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
return 0;
}
/* NAPI polling method*/ /* Initialize Rx queues */
static int bcmgenet_poll(struct napi_struct *napi, int budget) ret = bcmgenet_init_rx_queues(priv->dev);
{ if (ret) {
struct bcmgenet_priv *priv = container_of(napi, netdev_err(priv->dev, "failed to initialize Rx queues\n");
struct bcmgenet_priv, napi); bcmgenet_free_rx_buffers(priv);
unsigned int work_done; kfree(priv->rx_cbs);
kfree(priv->tx_cbs);
return ret;
}
work_done = bcmgenet_desc_rx(priv, DESC_INDEX, budget); /* Init tDma */
bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
if (work_done < budget) { /* Initialize Tx queues */
napi_complete(napi); bcmgenet_init_tx_queues(priv->dev);
bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
INTRL2_CPU_MASK_CLEAR);
}
return work_done; return 0;
} }
/* Interrupt bottom half */ /* Interrupt bottom half */
...@@ -2147,50 +2287,66 @@ static void bcmgenet_irq_task(struct work_struct *work) ...@@ -2147,50 +2287,66 @@ static void bcmgenet_irq_task(struct work_struct *work)
} }
} }
/* bcmgenet_isr1: interrupt handler for ring buffer. */ /* bcmgenet_isr1: handle Rx and Tx priority queues */
static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
{ {
struct bcmgenet_priv *priv = dev_id; struct bcmgenet_priv *priv = dev_id;
struct bcmgenet_tx_ring *ring; struct bcmgenet_rx_ring *rx_ring;
struct bcmgenet_tx_ring *tx_ring;
unsigned int index; unsigned int index;
/* Save irq status for bottom-half processing. */ /* Save irq status for bottom-half processing. */
priv->irq1_stat = priv->irq1_stat =
bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) & bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS); ~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS);
/* clear interrupts */ /* clear interrupts */
bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR); bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
netif_dbg(priv, intr, priv->dev, netif_dbg(priv, intr, priv->dev,
"%s: IRQ=0x%x\n", __func__, priv->irq1_stat); "%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
/* Check the MBDONE interrupts. /* Check Rx priority queue interrupts */
* packet is done, reclaim descriptors for (index = 0; index < priv->hw_params->rx_queues; index++) {
*/ if (!(priv->irq1_stat & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
continue;
rx_ring = &priv->rx_rings[index];
if (likely(napi_schedule_prep(&rx_ring->napi))) {
rx_ring->int_disable(rx_ring);
__napi_schedule(&rx_ring->napi);
}
}
/* Check Tx priority queue interrupts */
for (index = 0; index < priv->hw_params->tx_queues; index++) { for (index = 0; index < priv->hw_params->tx_queues; index++) {
if (!(priv->irq1_stat & BIT(index))) if (!(priv->irq1_stat & BIT(index)))
continue; continue;
ring = &priv->tx_rings[index]; tx_ring = &priv->tx_rings[index];
if (likely(napi_schedule_prep(&ring->napi))) { if (likely(napi_schedule_prep(&tx_ring->napi))) {
ring->int_disable(priv, ring); tx_ring->int_disable(tx_ring);
__napi_schedule(&ring->napi); __napi_schedule(&tx_ring->napi);
} }
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* bcmgenet_isr0: Handle various interrupts. */ /* bcmgenet_isr0: handle Rx and Tx default queues + other stuff */
static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
{ {
struct bcmgenet_priv *priv = dev_id; struct bcmgenet_priv *priv = dev_id;
struct bcmgenet_rx_ring *rx_ring;
struct bcmgenet_tx_ring *tx_ring;
/* Save irq status for bottom-half processing. */ /* Save irq status for bottom-half processing. */
priv->irq0_stat = priv->irq0_stat =
bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) & bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS); ~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
/* clear interrupts */ /* clear interrupts */
bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR); bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
...@@ -2198,25 +2354,23 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) ...@@ -2198,25 +2354,23 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
"IRQ=0x%x\n", priv->irq0_stat); "IRQ=0x%x\n", priv->irq0_stat);
if (priv->irq0_stat & (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE)) { if (priv->irq0_stat & (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE)) {
/* We use NAPI(software interrupt throttling, if rx_ring = &priv->rx_rings[DESC_INDEX];
* Rx Descriptor throttling is not used.
* Disable interrupt, will be enabled in the poll method. if (likely(napi_schedule_prep(&rx_ring->napi))) {
*/ rx_ring->int_disable(rx_ring);
if (likely(napi_schedule_prep(&priv->napi))) { __napi_schedule(&rx_ring->napi);
bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
INTRL2_CPU_MASK_SET);
__napi_schedule(&priv->napi);
} }
} }
if (priv->irq0_stat &
(UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE)) {
struct bcmgenet_tx_ring *ring = &priv->tx_rings[DESC_INDEX];
if (likely(napi_schedule_prep(&ring->napi))) { if (priv->irq0_stat & (UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE)) {
ring->int_disable(priv, ring); tx_ring = &priv->tx_rings[DESC_INDEX];
__napi_schedule(&ring->napi);
if (likely(napi_schedule_prep(&tx_ring->napi))) {
tx_ring->int_disable(tx_ring);
__napi_schedule(&tx_ring->napi);
} }
} }
if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R | if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R |
UMAC_IRQ_PHY_DET_F | UMAC_IRQ_PHY_DET_F |
UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_UP |
...@@ -2463,7 +2617,8 @@ static void bcmgenet_netif_start(struct net_device *dev) ...@@ -2463,7 +2617,8 @@ static void bcmgenet_netif_start(struct net_device *dev)
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
/* Start the network engine */ /* Start the network engine */
napi_enable(&priv->napi); bcmgenet_enable_rx_napi(priv);
bcmgenet_enable_tx_napi(priv);
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
...@@ -2568,10 +2723,10 @@ static void bcmgenet_netif_stop(struct net_device *dev) ...@@ -2568,10 +2723,10 @@ static void bcmgenet_netif_stop(struct net_device *dev)
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
netif_tx_stop_all_queues(dev); netif_tx_stop_all_queues(dev);
napi_disable(&priv->napi);
phy_stop(priv->phydev); phy_stop(priv->phydev);
bcmgenet_intr_disable(priv); bcmgenet_intr_disable(priv);
bcmgenet_disable_rx_napi(priv);
bcmgenet_disable_tx_napi(priv);
/* Wait for pending work items to complete. Since interrupts are /* Wait for pending work items to complete. Since interrupts are
* disabled no new work will be scheduled. * disabled no new work will be scheduled.
...@@ -2972,7 +3127,6 @@ static int bcmgenet_probe(struct platform_device *pdev) ...@@ -2972,7 +3127,6 @@ static int bcmgenet_probe(struct platform_device *pdev)
dev->watchdog_timeo = 2 * HZ; dev->watchdog_timeo = 2 * HZ;
dev->ethtool_ops = &bcmgenet_ethtool_ops; dev->ethtool_ops = &bcmgenet_ethtool_ops;
dev->netdev_ops = &bcmgenet_netdev_ops; dev->netdev_ops = &bcmgenet_netdev_ops;
netif_napi_add(dev, &priv->napi, bcmgenet_poll, 64);
priv->msg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT); priv->msg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT);
......
...@@ -310,6 +310,11 @@ struct bcmgenet_mib_counters { ...@@ -310,6 +310,11 @@ struct bcmgenet_mib_counters {
#define UMAC_IRQ_MDIO_DONE (1 << 23) #define UMAC_IRQ_MDIO_DONE (1 << 23)
#define UMAC_IRQ_MDIO_ERROR (1 << 24) #define UMAC_IRQ_MDIO_ERROR (1 << 24)
/* INTRL2 instance 1 definitions */
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
#define UMAC_IRQ1_RX_INTR_MASK 0xFFFF
#define UMAC_IRQ1_RX_INTR_SHIFT 16
/* Register block offsets */ /* Register block offsets */
#define GENET_SYS_OFF 0x0000 #define GENET_SYS_OFF 0x0000
#define GENET_GR_BRIDGE_OFF 0x0040 #define GENET_GR_BRIDGE_OFF 0x0040
...@@ -535,14 +540,13 @@ struct bcmgenet_tx_ring { ...@@ -535,14 +540,13 @@ struct bcmgenet_tx_ring {
unsigned int prod_index; /* Tx ring producer index SW copy */ unsigned int prod_index; /* Tx ring producer index SW copy */
unsigned int cb_ptr; /* Tx ring initial CB ptr */ unsigned int cb_ptr; /* Tx ring initial CB ptr */
unsigned int end_ptr; /* Tx ring end CB ptr */ unsigned int end_ptr; /* Tx ring end CB ptr */
void (*int_enable)(struct bcmgenet_priv *priv, void (*int_enable)(struct bcmgenet_tx_ring *);
struct bcmgenet_tx_ring *); void (*int_disable)(struct bcmgenet_tx_ring *);
void (*int_disable)(struct bcmgenet_priv *priv,
struct bcmgenet_tx_ring *);
struct bcmgenet_priv *priv; struct bcmgenet_priv *priv;
}; };
struct bcmgenet_rx_ring { struct bcmgenet_rx_ring {
struct napi_struct napi; /* Rx NAPI struct */
unsigned int index; /* Rx ring index */ unsigned int index; /* Rx ring index */
struct enet_cb *cbs; /* Rx ring buffer control block */ struct enet_cb *cbs; /* Rx ring buffer control block */
unsigned int size; /* Rx ring size */ unsigned int size; /* Rx ring size */
...@@ -551,6 +555,9 @@ struct bcmgenet_rx_ring { ...@@ -551,6 +555,9 @@ struct bcmgenet_rx_ring {
unsigned int cb_ptr; /* Rx ring initial CB ptr */ unsigned int cb_ptr; /* Rx ring initial CB ptr */
unsigned int end_ptr; /* Rx ring end CB ptr */ unsigned int end_ptr; /* Rx ring end CB ptr */
unsigned int old_discards; unsigned int old_discards;
void (*int_enable)(struct bcmgenet_rx_ring *);
void (*int_disable)(struct bcmgenet_rx_ring *);
struct bcmgenet_priv *priv;
}; };
/* device context */ /* device context */
...@@ -558,11 +565,6 @@ struct bcmgenet_priv { ...@@ -558,11 +565,6 @@ struct bcmgenet_priv {
void __iomem *base; void __iomem *base;
enum bcmgenet_version version; enum bcmgenet_version version;
struct net_device *dev; struct net_device *dev;
u32 int0_mask;
u32 int1_mask;
/* NAPI for descriptor based rx */
struct napi_struct napi ____cacheline_aligned;
/* transmit variables */ /* transmit variables */
void __iomem *tx_bds; void __iomem *tx_bds;
......
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