--- v9
+++ v2
@@ -1,135 +1,107 @@
From: Stefan Chulski <stefanc@marvell.com>
-The firmware needs to monitor the RX Non-occupied descriptor
-bits for flow control to move to XOFF mode.
-These bits need to be unmasked to be functional, but they will
-not raise interrupts as we leave the RX exception summary
-bit in MVPP2_ISR_RX_TX_MASK_REG clear.
+Flow Control periodic timer would be used if port in
+XOFF to transmit periodic XOFF frames.
Signed-off-by: Stefan Chulski <stefanc@marvell.com>
---
- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 3 ++
- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 44 ++++++++++++++++----
- 2 files changed, 40 insertions(+), 7 deletions(-)
+ drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 13 +++++-
+ drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 45 ++++++++++++++++++++
+ 2 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
-index 9239d80..d2cc513c 100644
+index cac9885..0861c0b 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
-@@ -295,6 +295,8 @@
- #define MVPP2_PON_CAUSE_TXP_OCCUP_DESC_ALL_MASK 0x3fc00000
- #define MVPP2_PON_CAUSE_MISC_SUM_MASK BIT(31)
- #define MVPP2_ISR_MISC_CAUSE_REG 0x55b0
-+#define MVPP2_ISR_RX_ERR_CAUSE_REG(port) (0x5520 + 4 * (port))
-+#define MVPP2_ISR_RX_ERR_CAUSE_NONOCC_MASK 0x00ff
+@@ -596,6 +596,15 @@
+ #define MVPP22_MPCS_CLK_RESET_DIV_RATIO(n) ((n) << 4)
+ #define MVPP22_MPCS_CLK_RESET_DIV_SET BIT(11)
- /* Buffer Manager registers */
- #define MVPP2_BM_POOL_BASE_REG(pool) (0x6000 + ((pool) * 4))
-@@ -763,6 +765,7 @@
++/* FCA registers. PPv2.2 and PPv2.3 */
++#define MVPP22_FCA_BASE(port) (0x7600 + (port) * 0x1000)
++#define MVPP22_FCA_REG_SIZE 16
++#define MVPP22_FCA_REG_MASK 0xFFFF
++#define MVPP22_FCA_CONTROL_REG 0x0
++#define MVPP22_FCA_ENABLE_PERIODIC BIT(11)
++#define MVPP22_PERIODIC_COUNTER_LSB_REG (0x110)
++#define MVPP22_PERIODIC_COUNTER_MSB_REG (0x114)
++
+ /* XPCS registers. PPv2.2 and PPv2.3 */
+ #define MVPP22_XPCS_BASE(port) (0x7400 + (port) * 0x1000)
+ #define MVPP22_XPCS_CFG0 0x0
+@@ -752,7 +761,9 @@
+ ((kb) * 1024 - MVPP2_TX_FIFO_THRESHOLD_MIN)
+
/* MSS Flow control */
- #define FC_QUANTA 0xFFFF
- #define FC_CLK_DIVIDER 100
-+#define MSS_THRESHOLD_STOP 768
+-#define MSS_SRAM_SIZE 0x800
++#define MSS_SRAM_SIZE 0x800
++#define FC_QUANTA 0xFFFF
++#define FC_CLK_DIVIDER 0x140
/* RX buffer constants */
#define MVPP2_SKB_SHINFO_SIZE \
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
-index 761f745..8b4073c 100644
+index 7143909..9d69752 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
-@@ -1133,14 +1133,19 @@ static inline void mvpp2_qvec_interrupt_disable(struct mvpp2_queue_vector *qvec)
- static void mvpp2_interrupts_mask(void *arg)
- {
- struct mvpp2_port *port = arg;
-+ int cpu = smp_processor_id();
-+ u32 thread;
-
- /* If the thread isn't used, don't do anything */
-- if (smp_processor_id() > port->priv->nthreads)
-+ if (cpu > port->priv->nthreads)
- return;
-
-- mvpp2_thread_write(port->priv,
-- mvpp2_cpu_to_thread(port->priv, smp_processor_id()),
-+ thread = mvpp2_cpu_to_thread(port->priv, cpu);
-+
-+ mvpp2_thread_write(port->priv, thread,
- MVPP2_ISR_RX_TX_MASK_REG(port->id), 0);
-+ mvpp2_thread_write(port->priv, thread,
-+ MVPP2_ISR_RX_ERR_CAUSE_REG(port->id), 0);
+@@ -1293,6 +1293,49 @@ static void mvpp22_gop_init_10gkr(struct mvpp2_port *port)
+ writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
}
- /* Unmask the current thread's Rx/Tx interrupts.
-@@ -1150,20 +1155,25 @@ static void mvpp2_interrupts_mask(void *arg)
- static void mvpp2_interrupts_unmask(void *arg)
- {
- struct mvpp2_port *port = arg;
-- u32 val;
-+ int cpu = smp_processor_id();
-+ u32 val, thread;
-
- /* If the thread isn't used, don't do anything */
-- if (smp_processor_id() > port->priv->nthreads)
-+ if (cpu > port->priv->nthreads)
- return;
-
-+ thread = mvpp2_cpu_to_thread(port->priv, cpu);
-+
- val = MVPP2_CAUSE_MISC_SUM_MASK |
- MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK(port->priv->hw_version);
- if (port->has_tx_irqs)
- val |= MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
-
-- mvpp2_thread_write(port->priv,
-- mvpp2_cpu_to_thread(port->priv, smp_processor_id()),
-+ mvpp2_thread_write(port->priv, thread,
- MVPP2_ISR_RX_TX_MASK_REG(port->id), val);
-+ mvpp2_thread_write(port->priv, thread,
-+ MVPP2_ISR_RX_ERR_CAUSE_REG(port->id),
-+ MVPP2_ISR_RX_ERR_CAUSE_NONOCC_MASK);
- }
-
- static void
-@@ -1188,6 +1198,9 @@ static void mvpp2_interrupts_unmask(void *arg)
-
- mvpp2_thread_write(port->priv, v->sw_thread_id,
- MVPP2_ISR_RX_TX_MASK_REG(port->id), val);
-+ mvpp2_thread_write(port->priv, v->sw_thread_id,
-+ MVPP2_ISR_RX_ERR_CAUSE_REG(port->id),
-+ MVPP2_ISR_RX_ERR_CAUSE_NONOCC_MASK);
- }
- }
-
-@@ -2393,6 +2406,20 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
- }
- }
-
-+/* Set the number of non-occupied descriptors threshold */
-+static void mvpp2_set_rxq_free_tresh(struct mvpp2_port *port,
-+ struct mvpp2_rx_queue *rxq)
++static void mvpp22_gop_fca_enable_periodic(struct mvpp2_port *port, bool en)
+{
++ struct mvpp2 *priv = port->priv;
++ void __iomem *fca = priv->iface_base + MVPP22_FCA_BASE(port->gop_id);
+ u32 val;
+
-+ mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
-+
-+ val = mvpp2_read(port->priv, MVPP2_RXQ_THRESH_REG);
-+ val &= ~MVPP2_RXQ_NON_OCCUPIED_MASK;
-+ val |= MSS_THRESHOLD_STOP << MVPP2_RXQ_NON_OCCUPIED_OFFSET;
-+ mvpp2_write(port->priv, MVPP2_RXQ_THRESH_REG, val);
++ val = readl(fca + MVPP22_FCA_CONTROL_REG);
++ val &= ~MVPP22_FCA_ENABLE_PERIODIC;
++ if (en)
++ val |= MVPP22_FCA_ENABLE_PERIODIC;
++ writel(val, fca + MVPP22_FCA_CONTROL_REG);
+}
+
- /* Set the number of packets that will be received before Rx interrupt
- * will be generated by HW.
- */
-@@ -2648,6 +2675,9 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
- mvpp2_rx_pkts_coal_set(port, rxq);
- mvpp2_rx_time_coal_set(port, rxq);
++static void mvpp22_gop_fca_set_timer(struct mvpp2_port *port, u32 timer)
++{
++ struct mvpp2 *priv = port->priv;
++ void __iomem *fca = priv->iface_base + MVPP22_FCA_BASE(port->gop_id);
++ u32 lsb, msb;
++
++ lsb = timer & MVPP22_FCA_REG_MASK;
++ msb = timer >> MVPP22_FCA_REG_SIZE;
++
++ writel(lsb, fca + MVPP22_PERIODIC_COUNTER_LSB_REG);
++ writel(msb, fca + MVPP22_PERIODIC_COUNTER_MSB_REG);
++}
++
++/* Set Flow Control timer x140 faster than pause quanta to ensure that link
++ * partner won't send taffic if port in XOFF mode.
++ */
++static void mvpp22_gop_fca_set_periodic_timer(struct mvpp2_port *port)
++{
++ u32 timer;
++
++ timer = (port->priv->tclk / (USEC_PER_SEC * FC_CLK_DIVIDER))
++ * FC_QUANTA;
++
++ mvpp22_gop_fca_enable_periodic(port, false);
++
++ mvpp22_gop_fca_set_timer(port, timer);
++
++ mvpp22_gop_fca_enable_periodic(port, true);
++}
++
+ static int mvpp22_gop_init(struct mvpp2_port *port)
+ {
+ struct mvpp2 *priv = port->priv;
+@@ -1337,6 +1380,8 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
+ val |= GENCONF_SOFT_RESET1_GOP;
+ regmap_write(priv->sysctrl_base, GENCONF_SOFT_RESET1, val);
-+ /* Set the number of non occupied descriptors threshold */
-+ mvpp2_set_rxq_free_tresh(port, rxq);
++ mvpp22_gop_fca_set_periodic_timer(port);
+
- /* Add number of descriptors ready for receiving packets */
- mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size);
+ unsupported_conf:
+ return 0;
--
1.9.1