From 6deee2221e110f6574988120dba6cab7e7313f44 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:45 +0000 Subject: [PATCH 01/11] net: stmmac: prepare dma op mode config for multiple queues This patch prepares DMA Operation Mode configuration for multiple queues. The work consisted on breaking the DMA operation Mode configuration function into RX and TX scope and adapting its mechanism in stmmac_main. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 3 + .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 118 +++++++++--------- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 82 +++++++++--- 3 files changed, 124 insertions(+), 79 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 9f0d26da6813..13bd3d4e381f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -424,6 +424,9 @@ struct stmmac_dma_ops { * An invalid value enables the store-and-forward mode */ void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode, int rxfifosz); + void (*dma_rx_mode)(void __iomem *ioaddr, int mode, u32 channel, + int fifosz); + void (*dma_tx_mode)(void __iomem *ioaddr, int mode, u32 channel); /* To track extra statistic (if supported) */ void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 6ac6b2600a7c..6285e8ad340d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -182,70 +182,26 @@ static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(i)); } -static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, - int rxmode, u32 channel, int rxfifosz) +static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode, + u32 channel, int fifosz) { - unsigned int rqs = rxfifosz / 256 - 1; - u32 mtl_tx_op, mtl_rx_op, mtl_rx_int; - - /* Following code only done for channel 0, other channels not yet - * supported. - */ - mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel)); - - if (txmode == SF_DMA_MODE) { - pr_debug("GMAC: enable TX store and forward mode\n"); - /* Transmit COE type 2 cannot be done in cut-through mode. */ - mtl_tx_op |= MTL_OP_MODE_TSF; - } else { - pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode); - mtl_tx_op &= ~MTL_OP_MODE_TSF; - mtl_tx_op &= MTL_OP_MODE_TTC_MASK; - /* Set the transmit threshold */ - if (txmode <= 32) - mtl_tx_op |= MTL_OP_MODE_TTC_32; - else if (txmode <= 64) - mtl_tx_op |= MTL_OP_MODE_TTC_64; - else if (txmode <= 96) - mtl_tx_op |= MTL_OP_MODE_TTC_96; - else if (txmode <= 128) - mtl_tx_op |= MTL_OP_MODE_TTC_128; - else if (txmode <= 192) - mtl_tx_op |= MTL_OP_MODE_TTC_192; - else if (txmode <= 256) - mtl_tx_op |= MTL_OP_MODE_TTC_256; - else if (txmode <= 384) - mtl_tx_op |= MTL_OP_MODE_TTC_384; - else - mtl_tx_op |= MTL_OP_MODE_TTC_512; - } - /* For an IP with DWC_EQOS_NUM_TXQ == 1, the fields TXQEN and TQS are RO - * with reset values: TXQEN on, TQS == DWC_EQOS_TXFIFO_SIZE. - * For an IP with DWC_EQOS_NUM_TXQ > 1, the fields TXQEN and TQS are R/W - * with reset values: TXQEN off, TQS 256 bytes. - * - * Write the bits in both cases, since it will have no effect when RO. - * For DWC_EQOS_NUM_TXQ > 1, the top bits in MTL_OP_MODE_TQS_MASK might - * be RO, however, writing the whole TQS field will result in a value - * equal to DWC_EQOS_TXFIFO_SIZE, just like for DWC_EQOS_NUM_TXQ == 1. - */ - mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK; - writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); + unsigned int rqs = fifosz / 256 - 1; + u32 mtl_rx_op, mtl_rx_int; mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel)); - if (rxmode == SF_DMA_MODE) { + if (mode == SF_DMA_MODE) { pr_debug("GMAC: enable RX store and forward mode\n"); mtl_rx_op |= MTL_OP_MODE_RSF; } else { - pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode); + pr_debug("GMAC: disable RX SF mode (threshold %d)\n", mode); mtl_rx_op &= ~MTL_OP_MODE_RSF; mtl_rx_op &= MTL_OP_MODE_RTC_MASK; - if (rxmode <= 32) + if (mode <= 32) mtl_rx_op |= MTL_OP_MODE_RTC_32; - else if (rxmode <= 64) + else if (mode <= 64) mtl_rx_op |= MTL_OP_MODE_RTC_64; - else if (rxmode <= 96) + else if (mode <= 96) mtl_rx_op |= MTL_OP_MODE_RTC_96; else mtl_rx_op |= MTL_OP_MODE_RTC_128; @@ -255,7 +211,7 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, mtl_rx_op |= rqs << MTL_OP_MODE_RQS_SHIFT; /* enable flow control only if each channel gets 4 KiB or more FIFO */ - if (rxfifosz >= 4096) { + if (fifosz >= 4096) { unsigned int rfd, rfa; mtl_rx_op |= MTL_OP_MODE_EHFC; @@ -266,7 +222,7 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, * Set Threshold for Deactivating Flow Control to min 1 frame, * i.e. 1500 bytes. */ - switch (rxfifosz) { + switch (fifosz) { case 4096: /* This violates the above formula because of FIFO size * limit therefore overflow may occur in spite of this. @@ -306,11 +262,49 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, ioaddr + MTL_CHAN_INT_CTRL(channel)); } -static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode, - int rxmode, int rxfifosz) +static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode, + u32 channel) { - /* Only Channel 0 is actually configured and used */ - dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0, rxfifosz); + u32 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel)); + + if (mode == SF_DMA_MODE) { + pr_debug("GMAC: enable TX store and forward mode\n"); + /* Transmit COE type 2 cannot be done in cut-through mode. */ + mtl_tx_op |= MTL_OP_MODE_TSF; + } else { + pr_debug("GMAC: disabling TX SF (threshold %d)\n", mode); + mtl_tx_op &= ~MTL_OP_MODE_TSF; + mtl_tx_op &= MTL_OP_MODE_TTC_MASK; + /* Set the transmit threshold */ + if (mode <= 32) + mtl_tx_op |= MTL_OP_MODE_TTC_32; + else if (mode <= 64) + mtl_tx_op |= MTL_OP_MODE_TTC_64; + else if (mode <= 96) + mtl_tx_op |= MTL_OP_MODE_TTC_96; + else if (mode <= 128) + mtl_tx_op |= MTL_OP_MODE_TTC_128; + else if (mode <= 192) + mtl_tx_op |= MTL_OP_MODE_TTC_192; + else if (mode <= 256) + mtl_tx_op |= MTL_OP_MODE_TTC_256; + else if (mode <= 384) + mtl_tx_op |= MTL_OP_MODE_TTC_384; + else + mtl_tx_op |= MTL_OP_MODE_TTC_512; + } + /* For an IP with DWC_EQOS_NUM_TXQ == 1, the fields TXQEN and TQS are RO + * with reset values: TXQEN on, TQS == DWC_EQOS_TXFIFO_SIZE. + * For an IP with DWC_EQOS_NUM_TXQ > 1, the fields TXQEN and TQS are R/W + * with reset values: TXQEN off, TQS 256 bytes. + * + * Write the bits in both cases, since it will have no effect when RO. + * For DWC_EQOS_NUM_TXQ > 1, the top bits in MTL_OP_MODE_TQS_MASK might + * be RO, however, writing the whole TQS field will result in a value + * equal to DWC_EQOS_TXFIFO_SIZE, just like for DWC_EQOS_NUM_TXQ == 1. + */ + mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK; + writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); } static void dwmac4_get_hw_feature(void __iomem *ioaddr, @@ -387,7 +381,8 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { .init = dwmac4_dma_init, .axi = dwmac4_dma_axi, .dump_regs = dwmac4_dump_dma_regs, - .dma_mode = dwmac4_dma_operation_mode, + .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, + .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, .enable_dma_irq = dwmac4_enable_dma_irq, .disable_dma_irq = dwmac4_disable_dma_irq, .start_tx = dwmac4_dma_start_tx, @@ -409,7 +404,8 @@ const struct stmmac_dma_ops dwmac410_dma_ops = { .init = dwmac4_dma_init, .axi = dwmac4_dma_axi, .dump_regs = dwmac4_dump_dma_regs, - .dma_mode = dwmac4_dma_operation_mode, + .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, + .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, .enable_dma_irq = dwmac410_enable_dma_irq, .disable_dma_irq = dwmac4_disable_dma_irq, .start_tx = dwmac4_dma_start_tx, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ec363e19cd79..c4e4a5328951 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1285,14 +1285,20 @@ static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) */ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { + u32 rx_channels_count = priv->plat->rx_queues_to_use; + u32 tx_channels_count = priv->plat->tx_queues_to_use; int rxfifosz = priv->plat->rx_fifo_size; + u32 txmode = 0; + u32 rxmode = 0; + u32 chan = 0; if (rxfifosz == 0) rxfifosz = priv->dma_cap.rx_fifo_size; - if (priv->plat->force_thresh_dma_mode) - priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); - else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { + if (priv->plat->force_thresh_dma_mode) { + txmode = tc; + rxmode = tc; + } else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { /* * In case of GMAC, SF mode can be enabled * to perform the TX COE in HW. This depends on: @@ -1300,12 +1306,26 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) * 2) There is no bugged Jumbo frame support * that needs to not insert csum in the TDES. */ - priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, - rxfifosz); + txmode = SF_DMA_MODE; + rxmode = SF_DMA_MODE; priv->xstats.threshold = SF_DMA_MODE; - } else - priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, + } else { + txmode = tc; + rxmode = SF_DMA_MODE; + } + + /* configure all channels */ + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + for (chan = 0; chan < rx_channels_count; chan++) + priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, + rxfifosz); + + for (chan = 0; chan < tx_channels_count; chan++) + priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); + } else { + priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, rxfifosz); + } } /** @@ -1443,6 +1463,34 @@ static void stmmac_tx_err(struct stmmac_priv *priv) netif_wake_queue(priv->dev); } +/** + * stmmac_set_dma_operation_mode - Set DMA operation mode by channel + * @priv: driver private structure + * @txmode: TX operating mode + * @rxmode: RX operating mode + * @chan: channel index + * Description: it is used for configuring of the DMA operation mode in + * runtime in order to program the tx/rx DMA thresholds or Store-And-Forward + * mode. + */ +static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode, + u32 rxmode, u32 chan) +{ + int rxfifosz = priv->plat->rx_fifo_size; + + if (rxfifosz == 0) + rxfifosz = priv->dma_cap.rx_fifo_size; + + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, + rxfifosz); + priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); + } else { + priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, + rxfifosz); + } +} + /** * stmmac_dma_interrupt - DMA ISR * @priv: driver private structure @@ -1452,11 +1500,8 @@ static void stmmac_tx_err(struct stmmac_priv *priv) */ static void stmmac_dma_interrupt(struct stmmac_priv *priv) { + u32 chan = STMMAC_CHAN0; int status; - int rxfifosz = priv->plat->rx_fifo_size; - - if (rxfifosz == 0) - rxfifosz = priv->dma_cap.rx_fifo_size; status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); if (likely((status & handle_rx)) || (status & handle_tx)) { @@ -1471,11 +1516,12 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) (tc <= 256)) { tc += 64; if (priv->plat->force_thresh_dma_mode) - priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, - rxfifosz); + stmmac_set_dma_operation_mode(priv->ioaddr, + tc, tc, chan); else - priv->hw->dma->dma_mode(priv->ioaddr, tc, - SF_DMA_MODE, rxfifosz); + stmmac_set_dma_operation_mode(priv->ioaddr, tc, + SF_DMA_MODE, chan); + priv->xstats.threshold = tc; } } else if (unlikely(status == tx_hard_error)) @@ -1749,6 +1795,9 @@ static void stmmac_mtl_configuration(struct stmmac_priv *priv) /* Enable MAC RX Queues */ if (rx_queues_count > 1 && priv->hw->mac->rx_queue_enable) stmmac_mac_enable_rx_queues(priv); + + /* Set the HW DMA mode and the COE */ + stmmac_dma_operation_mode(priv); } /** @@ -1812,9 +1861,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) else stmmac_set_mac(priv->ioaddr, true); - /* Set the HW DMA mode and the COE */ - stmmac_dma_operation_mode(priv); - stmmac_mmc_setup(priv); if (init_ptp) { From 4f513ecd2f60d9ebd2ac0fa4cd0b5d0612d70233 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:46 +0000 Subject: [PATCH 02/11] net: stmmac: enable/disable dma irq prepared for multiple queues This patch prepares the DMA IRQ enable/disable process for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h | 6 +++--- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 12 ++++++------ drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++------ 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 13bd3d4e381f..0351b5408372 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -431,8 +431,8 @@ struct stmmac_dma_ops { void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, void __iomem *ioaddr); void (*enable_dma_transmission) (void __iomem *ioaddr); - void (*enable_dma_irq) (void __iomem *ioaddr); - void (*disable_dma_irq) (void __iomem *ioaddr); + void (*enable_dma_irq)(void __iomem *ioaddr, u32 chan); + void (*disable_dma_irq)(void __iomem *ioaddr, u32 chan); void (*start_tx) (void __iomem *ioaddr); void (*stop_tx) (void __iomem *ioaddr); void (*start_rx) (void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 1b06df749e2b..393a657cd9ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -185,9 +185,9 @@ int dwmac4_dma_reset(void __iomem *ioaddr); void dwmac4_enable_dma_transmission(void __iomem *ioaddr, u32 tail_ptr); -void dwmac4_enable_dma_irq(void __iomem *ioaddr); -void dwmac410_enable_dma_irq(void __iomem *ioaddr); -void dwmac4_disable_dma_irq(void __iomem *ioaddr); +void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan); +void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan); +void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan); void dwmac4_dma_start_tx(void __iomem *ioaddr); void dwmac4_dma_stop_tx(void __iomem *ioaddr); void dwmac4_dma_start_rx(void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index c7326d5b2f43..c9327911e29a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -104,21 +104,21 @@ void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len) writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(STMMAC_CHAN0)); } -void dwmac4_enable_dma_irq(void __iomem *ioaddr) +void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan) { writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + - DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); + DMA_CHAN_INTR_ENA(chan)); } -void dwmac410_enable_dma_irq(void __iomem *ioaddr) +void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan) { writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10, - ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); + ioaddr + DMA_CHAN_INTR_ENA(chan)); } -void dwmac4_disable_dma_irq(void __iomem *ioaddr) +void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan) { - writel(0, ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); + writel(0, ioaddr + DMA_CHAN_INTR_ENA(chan)); } int dwmac4_dma_interrupt(void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 56e485f79077..dec0816565f3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -137,8 +137,8 @@ #define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ void dwmac_enable_dma_transmission(void __iomem *ioaddr); -void dwmac_enable_dma_irq(void __iomem *ioaddr); -void dwmac_disable_dma_irq(void __iomem *ioaddr); +void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan); +void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan); void dwmac_dma_start_tx(void __iomem *ioaddr); void dwmac_dma_stop_tx(void __iomem *ioaddr); void dwmac_dma_start_rx(void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index e60bfca2a763..285cfc9b3361 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -47,12 +47,12 @@ void dwmac_enable_dma_transmission(void __iomem *ioaddr) writel(1, ioaddr + DMA_XMT_POLL_DEMAND); } -void dwmac_enable_dma_irq(void __iomem *ioaddr) +void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan) { writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); } -void dwmac_disable_dma_irq(void __iomem *ioaddr) +void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan) { writel(0, ioaddr + DMA_INTR_ENA); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c4e4a5328951..18cf58c16dc3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1422,14 +1422,14 @@ static void stmmac_tx_clean(struct stmmac_priv *priv) netif_tx_unlock(priv->dev); } -static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) +static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan) { - priv->hw->dma->enable_dma_irq(priv->ioaddr); + priv->hw->dma->enable_dma_irq(priv->ioaddr, chan); } -static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) +static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan) { - priv->hw->dma->disable_dma_irq(priv->ioaddr); + priv->hw->dma->disable_dma_irq(priv->ioaddr, chan); } /** @@ -1506,7 +1506,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); if (likely((status & handle_rx)) || (status & handle_tx)) { if (likely(napi_schedule_prep(&priv->napi))) { - stmmac_disable_dma_irq(priv); + stmmac_disable_dma_irq(priv, chan); __napi_schedule(&priv->napi); } } @@ -2832,6 +2832,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget) { struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); int work_done = 0; + u32 chan = STMMAC_CHAN0; priv->xstats.napi_poll++; stmmac_tx_clean(priv); @@ -2839,7 +2840,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget) work_done = stmmac_rx(priv, budget); if (work_done < budget) { napi_complete_done(napi, work_done); - stmmac_enable_dma_irq(priv); + stmmac_enable_dma_irq(priv, chan); } return work_done; } From ae4f0d46830814e11ec91b8c76ebf3ae3f8140d7 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:47 +0000 Subject: [PATCH 03/11] net: stmmac: rx/tx dma start/stop prepared for multiple queues This patch prepares the RX/TX DMA stop/start process for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 8 +- .../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 8 +- .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 24 ++-- .../net/ethernet/stmicro/stmmac/dwmac_dma.h | 8 +- .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 8 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 108 ++++++++++++++++-- 6 files changed, 125 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 0351b5408372..042b4828efaa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -433,10 +433,10 @@ struct stmmac_dma_ops { void (*enable_dma_transmission) (void __iomem *ioaddr); void (*enable_dma_irq)(void __iomem *ioaddr, u32 chan); void (*disable_dma_irq)(void __iomem *ioaddr, u32 chan); - void (*start_tx) (void __iomem *ioaddr); - void (*stop_tx) (void __iomem *ioaddr); - void (*start_rx) (void __iomem *ioaddr); - void (*stop_rx) (void __iomem *ioaddr); + void (*start_tx)(void __iomem *ioaddr, u32 chan); + void (*stop_tx)(void __iomem *ioaddr, u32 chan); + void (*start_rx)(void __iomem *ioaddr, u32 chan); + void (*stop_rx)(void __iomem *ioaddr, u32 chan); int (*dma_interrupt) (void __iomem *ioaddr, struct stmmac_extra_stats *x); /* If supported then get the optional core features */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 393a657cd9ff..2c19042b47df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -188,10 +188,10 @@ void dwmac4_enable_dma_transmission(void __iomem *ioaddr, u32 tail_ptr); void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan); void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan); void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan); -void dwmac4_dma_start_tx(void __iomem *ioaddr); -void dwmac4_dma_stop_tx(void __iomem *ioaddr); -void dwmac4_dma_start_rx(void __iomem *ioaddr); -void dwmac4_dma_stop_rx(void __iomem *ioaddr); +void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan); +void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan); +void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan); +void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan); int dwmac4_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index c9327911e29a..3512d18f626b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -45,49 +45,49 @@ void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(0)); } -void dwmac4_dma_start_tx(void __iomem *ioaddr) +void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); value |= DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); value = readl(ioaddr + GMAC_CONFIG); value |= GMAC_CONFIG_TE; writel(value, ioaddr + GMAC_CONFIG); } -void dwmac4_dma_stop_tx(void __iomem *ioaddr) +void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); value &= ~DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); value = readl(ioaddr + GMAC_CONFIG); value &= ~GMAC_CONFIG_TE; writel(value, ioaddr + GMAC_CONFIG); } -void dwmac4_dma_start_rx(void __iomem *ioaddr) +void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); value |= DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); value = readl(ioaddr + GMAC_CONFIG); value |= GMAC_CONFIG_RE; writel(value, ioaddr + GMAC_CONFIG); } -void dwmac4_dma_stop_rx(void __iomem *ioaddr) +void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); value &= ~DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); value = readl(ioaddr + GMAC_CONFIG); value &= ~GMAC_CONFIG_RE; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index dec0816565f3..6c6cc7137ee0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -139,10 +139,10 @@ void dwmac_enable_dma_transmission(void __iomem *ioaddr); void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan); void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan); -void dwmac_dma_start_tx(void __iomem *ioaddr); -void dwmac_dma_stop_tx(void __iomem *ioaddr); -void dwmac_dma_start_rx(void __iomem *ioaddr); -void dwmac_dma_stop_rx(void __iomem *ioaddr); +void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan); +void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan); +void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan); +void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan); int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); int dwmac_dma_reset(void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 285cfc9b3361..7be60c3a24e8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -57,28 +57,28 @@ void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan) writel(0, ioaddr + DMA_INTR_ENA); } -void dwmac_dma_start_tx(void __iomem *ioaddr) +void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan) { u32 value = readl(ioaddr + DMA_CONTROL); value |= DMA_CONTROL_ST; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_stop_tx(void __iomem *ioaddr) +void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan) { u32 value = readl(ioaddr + DMA_CONTROL); value &= ~DMA_CONTROL_ST; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_start_rx(void __iomem *ioaddr) +void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan) { u32 value = readl(ioaddr + DMA_CONTROL); value |= DMA_CONTROL_SR; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_stop_rx(void __iomem *ioaddr) +void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan) { u32 value = readl(ioaddr + DMA_CONTROL); value &= ~DMA_CONTROL_SR; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 18cf58c16dc3..a537276e1055 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1277,6 +1277,96 @@ static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) } } +/** + * stmmac_start_rx_dma - start RX DMA channel + * @priv: driver private structure + * @chan: RX channel index + * Description: + * This starts a RX DMA channel + */ +static void stmmac_start_rx_dma(struct stmmac_priv *priv, u32 chan) +{ + netdev_dbg(priv->dev, "DMA RX processes started in channel %d\n", chan); + priv->hw->dma->start_rx(priv->ioaddr, chan); +} + +/** + * stmmac_start_tx_dma - start TX DMA channel + * @priv: driver private structure + * @chan: TX channel index + * Description: + * This starts a TX DMA channel + */ +static void stmmac_start_tx_dma(struct stmmac_priv *priv, u32 chan) +{ + netdev_dbg(priv->dev, "DMA TX processes started in channel %d\n", chan); + priv->hw->dma->start_tx(priv->ioaddr, chan); +} + +/** + * stmmac_stop_rx_dma - stop RX DMA channel + * @priv: driver private structure + * @chan: RX channel index + * Description: + * This stops a RX DMA channel + */ +static void stmmac_stop_rx_dma(struct stmmac_priv *priv, u32 chan) +{ + netdev_dbg(priv->dev, "DMA RX processes stopped in channel %d\n", chan); + priv->hw->dma->stop_rx(priv->ioaddr, chan); +} + +/** + * stmmac_stop_tx_dma - stop TX DMA channel + * @priv: driver private structure + * @chan: TX channel index + * Description: + * This stops a TX DMA channel + */ +static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan) +{ + netdev_dbg(priv->dev, "DMA TX processes stopped in channel %d\n", chan); + priv->hw->dma->stop_tx(priv->ioaddr, chan); +} + +/** + * stmmac_start_all_dma - start all RX and TX DMA channels + * @priv: driver private structure + * Description: + * This starts all the RX and TX DMA channels + */ +static void stmmac_start_all_dma(struct stmmac_priv *priv) +{ + u32 rx_channels_count = priv->plat->rx_queues_to_use; + u32 tx_channels_count = priv->plat->tx_queues_to_use; + u32 chan = 0; + + for (chan = 0; chan < rx_channels_count; chan++) + stmmac_start_rx_dma(priv, chan); + + for (chan = 0; chan < tx_channels_count; chan++) + stmmac_start_tx_dma(priv, chan); +} + +/** + * stmmac_stop_all_dma - stop all RX and TX DMA channels + * @priv: driver private structure + * Description: + * This stops the RX and TX DMA channels + */ +static void stmmac_stop_all_dma(struct stmmac_priv *priv) +{ + u32 rx_channels_count = priv->plat->rx_queues_to_use; + u32 tx_channels_count = priv->plat->tx_queues_to_use; + u32 chan = 0; + + for (chan = 0; chan < rx_channels_count; chan++) + stmmac_stop_rx_dma(priv, chan); + + for (chan = 0; chan < tx_channels_count; chan++) + stmmac_stop_tx_dma(priv, chan); +} + /** * stmmac_dma_operation_mode - HW DMA operation mode * @priv: driver private structure @@ -1440,10 +1530,11 @@ static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan) */ static void stmmac_tx_err(struct stmmac_priv *priv) { + u32 chan = STMMAC_CHAN0; int i; netif_stop_queue(priv->dev); - priv->hw->dma->stop_tx(priv->ioaddr); + stmmac_stop_tx_dma(priv, chan); dma_free_tx_skbufs(priv); for (i = 0; i < DMA_TX_SIZE; i++) if (priv->extend_desc) @@ -1457,7 +1548,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv) priv->dirty_tx = 0; priv->cur_tx = 0; netdev_reset_queue(priv->dev); - priv->hw->dma->start_tx(priv->ioaddr); + stmmac_start_tx_dma(priv, chan); priv->dev->stats.tx_errors++; netif_wake_queue(priv->dev); @@ -1882,9 +1973,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) __func__); #endif /* Start the ball rolling... */ - netdev_dbg(priv->dev, "DMA RX/TX processes started...\n"); - priv->hw->dma->start_tx(priv->ioaddr); - priv->hw->dma->start_rx(priv->ioaddr); + stmmac_start_all_dma(priv); priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; @@ -2070,8 +2159,7 @@ static int stmmac_release(struct net_device *dev) free_irq(priv->lpi_irq, dev); /* Stop TX/RX DMA and clear the descriptors */ - priv->hw->dma->stop_tx(priv->ioaddr); - priv->hw->dma->stop_rx(priv->ioaddr); + stmmac_stop_all_dma(priv); /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv); @@ -3546,8 +3634,7 @@ int stmmac_dvr_remove(struct device *dev) netdev_info(priv->dev, "%s: removing driver", __func__); - priv->hw->dma->stop_rx(priv->ioaddr); - priv->hw->dma->stop_tx(priv->ioaddr); + stmmac_stop_all_dma(priv); stmmac_set_mac(priv->ioaddr, false); netif_carrier_off(ndev); @@ -3593,8 +3680,7 @@ int stmmac_suspend(struct device *dev) napi_disable(&priv->napi); /* Stop TX/RX DMA */ - priv->hw->dma->stop_tx(priv->ioaddr); - priv->hw->dma->stop_rx(priv->ioaddr); + stmmac_stop_all_dma(priv); /* Enable Power down mode by programming the PMT regs */ if (device_may_wakeup(priv->device)) { From 4e593262290c3488ca7ab8b41a5c70c284e12b57 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:48 +0000 Subject: [PATCH 04/11] net: stmmac: prepare stmmac_tx_err for multiple queues This patch prepares stmmac_err for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a537276e1055..b166c05e2a5d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1525,12 +1525,12 @@ static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan) /** * stmmac_tx_err - to manage the tx error * @priv: driver private structure + * @chan: channel index * Description: it cleans the descriptors and restarts the transmission * in case of transmission errors. */ -static void stmmac_tx_err(struct stmmac_priv *priv) +static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan) { - u32 chan = STMMAC_CHAN0; int i; netif_stop_queue(priv->dev); @@ -1616,7 +1616,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) priv->xstats.threshold = tc; } } else if (unlikely(status == tx_hard_error)) - stmmac_tx_err(priv); + stmmac_tx_err(priv, chan); } /** @@ -2944,9 +2944,10 @@ static int stmmac_poll(struct napi_struct *napi, int budget) static void stmmac_tx_timeout(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); + u32 chan = STMMAC_CHAN0; /* Clear Tx resources and restart transmitting again */ - stmmac_tx_err(priv); + stmmac_tx_err(priv, chan); } /** From d62a107a4f154c9aa826dbe03ac2322a389b37b5 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:49 +0000 Subject: [PATCH 05/11] net: stmmac: prepare dma interrupt treatment for multiple queues This patch prepares DMA interrupts treatment for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- .../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 2 +- .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 8 +-- .../net/ethernet/stmicro/stmmac/dwmac_dma.h | 3 +- .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 53 +++++++++++-------- 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 042b4828efaa..6dfb7f31898e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -438,7 +438,7 @@ struct stmmac_dma_ops { void (*start_rx)(void __iomem *ioaddr, u32 chan); void (*stop_rx)(void __iomem *ioaddr, u32 chan); int (*dma_interrupt) (void __iomem *ioaddr, - struct stmmac_extra_stats *x); + struct stmmac_extra_stats *x, u32 chan); /* If supported then get the optional core features */ void (*get_hw_feature)(void __iomem *ioaddr, struct dma_features *dma_cap); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 2c19042b47df..946dc14fe77f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -193,7 +193,7 @@ void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan); void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan); void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan); int dwmac4_dma_interrupt(void __iomem *ioaddr, - struct stmmac_extra_stats *x); + struct stmmac_extra_stats *x, u32 chan); void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len); void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len); void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index 3512d18f626b..fcd8ec8a240b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -122,11 +122,11 @@ void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan) } int dwmac4_dma_interrupt(void __iomem *ioaddr, - struct stmmac_extra_stats *x) + struct stmmac_extra_stats *x, u32 chan) { int ret = 0; - u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(0)); + u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan)); /* ABNORMAL interrupts */ if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { @@ -153,7 +153,7 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr, if (likely(intr_status & DMA_CHAN_STATUS_RI)) { u32 value; - value = readl(ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); + value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); /* to schedule NAPI on real RIE event. */ if (likely(value & DMA_CHAN_INTR_ENA_RIE)) { x->rx_normal_irq_n++; @@ -172,7 +172,7 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr, * status [21-0] expect reserved bits [5-3] */ writel((intr_status & 0x3fffc7), - ioaddr + DMA_CHAN_STATUS(STMMAC_CHAN0)); + ioaddr + DMA_CHAN_STATUS(chan)); return ret; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 6c6cc7137ee0..9091df86723a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -143,7 +143,8 @@ void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan); void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan); void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan); void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan); -int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); +int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x, + u32 chan); int dwmac_dma_reset(void __iomem *ioaddr); #endif /* __DWMAC_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 7be60c3a24e8..38f94305aab5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -156,7 +156,7 @@ static void show_rx_process_state(unsigned int status) #endif int dwmac_dma_interrupt(void __iomem *ioaddr, - struct stmmac_extra_stats *x) + struct stmmac_extra_stats *x, u32 chan) { int ret = 0; /* read the status register (CSR5) */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b166c05e2a5d..79a792a0c12e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1591,32 +1591,41 @@ static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode, */ static void stmmac_dma_interrupt(struct stmmac_priv *priv) { - u32 chan = STMMAC_CHAN0; + u32 tx_channel_count = priv->plat->tx_queues_to_use; int status; + u32 chan; - status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); - if (likely((status & handle_rx)) || (status & handle_tx)) { - if (likely(napi_schedule_prep(&priv->napi))) { - stmmac_disable_dma_irq(priv, chan); - __napi_schedule(&priv->napi); + for (chan = 0; chan < tx_channel_count; chan++) { + status = priv->hw->dma->dma_interrupt(priv->ioaddr, + &priv->xstats, chan); + if (likely((status & handle_rx)) || (status & handle_tx)) { + if (likely(napi_schedule_prep(&priv->napi))) { + stmmac_disable_dma_irq(priv, chan); + __napi_schedule(&priv->napi); + } + } + + if (unlikely(status & tx_hard_error_bump_tc)) { + /* Try to bump up the dma threshold on this failure */ + if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && + (tc <= 256)) { + tc += 64; + if (priv->plat->force_thresh_dma_mode) + stmmac_set_dma_operation_mode(priv, + tc, + tc, + chan); + else + stmmac_set_dma_operation_mode(priv, + tc, + SF_DMA_MODE, + chan); + priv->xstats.threshold = tc; + } + } else if (unlikely(status == tx_hard_error)) { + stmmac_tx_err(priv, chan); } } - if (unlikely(status & tx_hard_error_bump_tc)) { - /* Try to bump up the dma threshold on this failure */ - if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && - (tc <= 256)) { - tc += 64; - if (priv->plat->force_thresh_dma_mode) - stmmac_set_dma_operation_mode(priv->ioaddr, - tc, tc, chan); - else - stmmac_set_dma_operation_mode(priv->ioaddr, tc, - SF_DMA_MODE, chan); - - priv->xstats.threshold = tc; - } - } else if (unlikely(status == tx_hard_error)) - stmmac_tx_err(priv, chan); } /** From 3c55d4d08bc9e94901a26eb57c9aa0b8c76a18c0 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:50 +0000 Subject: [PATCH 06/11] net: stmmac: rx watchdog config prepared for multiple queues This patch adds rx watchdog configuration for all queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 8 ++++---- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 6dfb7f31898e..5fa23b13d3cd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -443,7 +443,7 @@ struct stmmac_dma_ops { void (*get_hw_feature)(void __iomem *ioaddr, struct dma_features *dma_cap); /* Program the HW RX Watchdog */ - void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); + void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan); void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len); void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len); void (*set_rx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index d3654a447046..471a9aa6ac94 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -247,7 +247,8 @@ static void dwmac1000_get_hw_feature(void __iomem *ioaddr, dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; } -static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt) +static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt, + u32 number_chan) { writel(riwt, ioaddr + DMA_RX_WATCHDOG); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 6285e8ad340d..74177f9d640b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -174,12 +174,12 @@ static void dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) _dwmac4_dump_dma_regs(ioaddr, i, reg_space); } -static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) +static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 number_chan) { - int i; + u32 chan; - for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) - writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(i)); + for (chan = 0; chan < number_chan; chan++) + writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(chan)); } static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 61b9369a041e..16808e48ca1c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -730,6 +730,7 @@ static int stmmac_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) { struct stmmac_priv *priv = netdev_priv(dev); + u32 rx_cnt = priv->plat->rx_queues_to_use; unsigned int rx_riwt; /* Check not supported parameters */ @@ -768,7 +769,7 @@ static int stmmac_set_coalesce(struct net_device *dev, priv->tx_coal_frames = ec->tx_max_coalesced_frames; priv->tx_coal_timer = ec->tx_coalesce_usecs; priv->rx_riwt = rx_riwt; - priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); + priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt, rx_cnt); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 79a792a0c12e..00d0f5ea7682 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1915,6 +1915,7 @@ static void stmmac_mtl_configuration(struct stmmac_priv *priv) static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) { struct stmmac_priv *priv = netdev_priv(dev); + u32 rx_cnt = priv->plat->rx_queues_to_use; int ret; /* DMA initialization and SW reset */ @@ -1988,7 +1989,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { priv->rx_riwt = MAX_DMA_RIWT; - priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); + priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT, rx_cnt); } if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) From 4854ab9966e10ca002e4cc7a12e34c1444357d3d Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:51 +0000 Subject: [PATCH 07/11] net: stmmac: rx and tx ring length prepared for multiple queues This patch prepares tx and rx ring length configuration for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 4 +-- .../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 4 +-- .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 8 ++--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 32 ++++++++++++++----- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 5fa23b13d3cd..bef1fc6a6756 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -444,8 +444,8 @@ struct stmmac_dma_ops { struct dma_features *dma_cap); /* Program the HW RX Watchdog */ void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan); - void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len); - void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len); + void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan); + void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan); void (*set_rx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); void (*set_tx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); void (*enable_tso)(void __iomem *ioaddr, bool en, u32 chan); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 946dc14fe77f..8474bf961dd0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -194,8 +194,8 @@ void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan); void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan); int dwmac4_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan); -void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len); -void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len); +void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan); +void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan); void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index fcd8ec8a240b..da54c0b0bdf5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -94,14 +94,14 @@ void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan) writel(value, ioaddr + GMAC_CONFIG); } -void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len) +void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan) { - writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(STMMAC_CHAN0)); + writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(chan)); } -void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len) +void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan) { - writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(STMMAC_CHAN0)); + writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(chan)); } void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 00d0f5ea7682..26695d9a3283 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1802,6 +1802,27 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) add_timer(&priv->txtimer); } +static void stmmac_set_rings_length(struct stmmac_priv *priv) +{ + u32 rx_channels_count = priv->plat->rx_queues_to_use; + u32 tx_channels_count = priv->plat->tx_queues_to_use; + u32 chan; + + /* set TX ring length */ + if (priv->hw->dma->set_tx_ring_len) { + for (chan = 0; chan < tx_channels_count; chan++) + priv->hw->dma->set_tx_ring_len(priv->ioaddr, + (DMA_TX_SIZE - 1), chan); + } + + /* set RX ring length */ + if (priv->hw->dma->set_rx_ring_len) { + for (chan = 0; chan < rx_channels_count; chan++) + priv->hw->dma->set_rx_ring_len(priv->ioaddr, + (DMA_RX_SIZE - 1), chan); + } +} + /** * stmmac_set_tx_queue_weight - Set TX queue weight * @priv: driver private structure @@ -1995,14 +2016,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0); - /* set TX ring length */ - if (priv->hw->dma->set_tx_ring_len) - priv->hw->dma->set_tx_ring_len(priv->ioaddr, - (DMA_TX_SIZE - 1)); - /* set RX ring length */ - if (priv->hw->dma->set_rx_ring_len) - priv->hw->dma->set_rx_ring_len(priv->ioaddr, - (DMA_RX_SIZE - 1)); + /* set TX and RX rings length */ + stmmac_set_rings_length(priv); + /* Enable TSO */ if (priv->tso) priv->hw->dma->enable_tso(priv->ioaddr, 1, STMMAC_CHAN0); From 89cc57c55c1a7627b5dc912184da7e68d0d193bd Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:52 +0000 Subject: [PATCH 08/11] net: stmmac: prepare rx/tx set tail function for multiple queues This patch prepares RX and TX set tail functions for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index da54c0b0bdf5..49f5687879df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -37,12 +37,12 @@ int dwmac4_dma_reset(void __iomem *ioaddr) void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) { - writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(0)); + writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(chan)); } void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) { - writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(0)); + writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(chan)); } void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan) From 47f2a9ce527addf8a2c384efc47f0c812dc1a162 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:53 +0000 Subject: [PATCH 09/11] net: stmmac: dma channel init prepared for multiple queues This patch prepares the DMA initialization process for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 8 +++ .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 68 +++++++++++-------- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 51 +++++++++++--- 3 files changed, 89 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index bef1fc6a6756..badc4414d67b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -416,6 +416,14 @@ struct stmmac_dma_ops { int (*reset)(void __iomem *ioaddr); void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, u32 dma_tx, u32 dma_rx, int atds); + void (*init_chan)(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan); + void (*init_rx_chan)(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + u32 dma_rx_phy, u32 chan); + void (*init_tx_chan)(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + u32 dma_tx_phy, u32 chan); /* Configure the AXI Bus Mode Register */ void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi); /* Dump DMA registers */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 74177f9d640b..eec8463057fd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -71,36 +71,48 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) writel(value, ioaddr + DMA_SYS_BUS_MODE); } -static void dwmac4_dma_init_channel(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, - u32 dma_tx_phy, u32 dma_rx_phy, - u32 channel) +void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + u32 dma_rx_phy, u32 chan) { u32 value; - int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; - int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; + u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; - /* set PBL for each channels. Currently we affect same configuration - * on each channel - */ - value = readl(ioaddr + DMA_CHAN_CONTROL(channel)); + value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); + value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); + + writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(chan)); +} + +void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + u32 dma_tx_phy, u32 chan) +{ + u32 value; + u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; + + value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); + value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT); + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); + + writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); +} + +void dwmac4_dma_init_channel(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan) +{ + u32 value; + + /* common channel control register config */ + value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); if (dma_cfg->pblx8) value = value | DMA_BUS_MODE_PBL; - writel(value, ioaddr + DMA_CHAN_CONTROL(channel)); - - value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)); - value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT); - writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel)); - - value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)); - value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); - writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel)); + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); /* Mask interrupts by writing to CSR7 */ - writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(channel)); - - writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)); - writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)); + writel(DMA_CHAN_INTR_DEFAULT_MASK, + ioaddr + DMA_CHAN_INTR_ENA(chan)); } static void dwmac4_dma_init(void __iomem *ioaddr, @@ -108,7 +120,6 @@ static void dwmac4_dma_init(void __iomem *ioaddr, u32 dma_tx, u32 dma_rx, int atds) { u32 value = readl(ioaddr + DMA_SYS_BUS_MODE); - int i; /* Set the Fixed burst mode */ if (dma_cfg->fixed_burst) @@ -122,9 +133,6 @@ static void dwmac4_dma_init(void __iomem *ioaddr, value |= DMA_SYS_BUS_AAL; writel(value, ioaddr + DMA_SYS_BUS_MODE); - - for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) - dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i); } static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel, @@ -379,6 +387,9 @@ static void dwmac4_enable_tso(void __iomem *ioaddr, bool en, u32 chan) const struct stmmac_dma_ops dwmac4_dma_ops = { .reset = dwmac4_dma_reset, .init = dwmac4_dma_init, + .init_chan = dwmac4_dma_init_channel, + .init_rx_chan = dwmac4_dma_init_rx_chan, + .init_tx_chan = dwmac4_dma_init_tx_chan, .axi = dwmac4_dma_axi, .dump_regs = dwmac4_dump_dma_regs, .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, @@ -402,6 +413,9 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { const struct stmmac_dma_ops dwmac410_dma_ops = { .reset = dwmac4_dma_reset, .init = dwmac4_dma_init, + .init_chan = dwmac4_dma_init_channel, + .init_rx_chan = dwmac4_dma_init_rx_chan, + .init_tx_chan = dwmac4_dma_init_tx_chan, .axi = dwmac4_dma_axi, .dump_regs = dwmac4_dump_dma_regs, .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 26695d9a3283..2868391de0fb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1732,6 +1732,11 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv) */ static int stmmac_init_dma_engine(struct stmmac_priv *priv) { + u32 rx_channels_count = priv->plat->rx_queues_to_use; + u32 tx_channels_count = priv->plat->tx_queues_to_use; + u32 dummy_dma_rx_phy = 0; + u32 dummy_dma_tx_phy = 0; + u32 chan = 0; int atds = 0; int ret = 0; @@ -1749,19 +1754,43 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) return ret; } - priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, - priv->dma_tx_phy, priv->dma_rx_phy, atds); - if (priv->synopsys_id >= DWMAC_CORE_4_00) { - priv->rx_tail_addr = priv->dma_rx_phy + - (DMA_RX_SIZE * sizeof(struct dma_desc)); - priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, priv->rx_tail_addr, - STMMAC_CHAN0); + /* DMA Configuration */ + priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, + dummy_dma_tx_phy, dummy_dma_rx_phy, atds); - priv->tx_tail_addr = priv->dma_tx_phy + - (DMA_TX_SIZE * sizeof(struct dma_desc)); - priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, - STMMAC_CHAN0); + /* DMA RX Channel Configuration */ + for (chan = 0; chan < rx_channels_count; chan++) { + priv->hw->dma->init_rx_chan(priv->ioaddr, + priv->plat->dma_cfg, + priv->dma_rx_phy, chan); + + priv->rx_tail_addr = priv->dma_rx_phy + + (DMA_RX_SIZE * sizeof(struct dma_desc)); + priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, + priv->rx_tail_addr, + chan); + } + + /* DMA TX Channel Configuration */ + for (chan = 0; chan < tx_channels_count; chan++) { + priv->hw->dma->init_chan(priv->ioaddr, + priv->plat->dma_cfg, + chan); + + priv->hw->dma->init_tx_chan(priv->ioaddr, + priv->plat->dma_cfg, + priv->dma_tx_phy, chan); + + priv->tx_tail_addr = priv->dma_tx_phy + + (DMA_TX_SIZE * sizeof(struct dma_desc)); + priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, + priv->tx_tail_addr, + chan); + } + } else { + priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, + priv->dma_tx_phy, priv->dma_rx_phy, atds); } if (priv->plat->axi && priv->hw->dma->axi) From 146617b88b86c3d1f1309604d5d4cb38d5b24f1a Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:54 +0000 Subject: [PATCH 10/11] net: stmmac: tso init prepared for multiple queues This patch configures TSO for all available tx queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2868391de0fb..c802286380dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1966,6 +1966,8 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) { struct stmmac_priv *priv = netdev_priv(dev); u32 rx_cnt = priv->plat->rx_queues_to_use; + u32 tx_cnt = priv->plat->tx_queues_to_use; + u32 chan; int ret; /* DMA initialization and SW reset */ @@ -2049,8 +2051,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) stmmac_set_rings_length(priv); /* Enable TSO */ - if (priv->tso) - priv->hw->dma->enable_tso(priv->ioaddr, 1, STMMAC_CHAN0); + if (priv->tso) { + for (chan = 0; chan < tx_cnt; chan++) + priv->hw->dma->enable_tso(priv->ioaddr, 1, chan); + } return 0; } From 7bac4e1ec3ca2342929a39638d615c6b672c27a0 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Wed, 15 Mar 2017 11:04:55 +0000 Subject: [PATCH 11/11] net: stmmac: stmmac interrupt treatment prepared for multiple queues This patch prepares the main ISR for multiple queues. Signed-off-by: Joao Pinto Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c802286380dc..d3a21519e4c0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3115,6 +3115,12 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct stmmac_priv *priv = netdev_priv(dev); + u32 rx_cnt = priv->plat->rx_queues_to_use; + u32 tx_cnt = priv->plat->tx_queues_to_use; + u32 queues_count; + u32 queue; + + queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt; if (priv->irq_wake) pm_wakeup_event(priv->device, 0); @@ -3129,20 +3135,26 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) int status = priv->hw->mac->host_irq_status(priv->hw, &priv->xstats); - if (priv->synopsys_id >= DWMAC_CORE_4_00) - status |= priv->hw->mac->host_mtl_irq_status(priv->hw, - STMMAC_CHAN0); - if (unlikely(status)) { /* For LPI we need to save the tx status */ if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) priv->tx_path_in_lpi_mode = true; if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) priv->tx_path_in_lpi_mode = false; - if (status & CORE_IRQ_MTL_RX_OVERFLOW && priv->hw->dma->set_rx_tail_ptr) - priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, - priv->rx_tail_addr, - STMMAC_CHAN0); + } + + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + for (queue = 0; queue < queues_count; queue++) { + status |= + priv->hw->mac->host_mtl_irq_status(priv->hw, + queue); + + if (status & CORE_IRQ_MTL_RX_OVERFLOW && + priv->hw->dma->set_rx_tail_ptr) + priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, + priv->rx_tail_addr, + queue); + } } /* PCS link status */