diff mbox series

[v7,net-next,10/15] net: mvpp2: add RXQ flow control configurations

Message ID 1612253821-1148-11-git-send-email-stefanc@marvell.com
State Superseded
Headers show
Series net: mvpp2: Add TX Flow Control support | expand

Commit Message

Stefan Chulski Feb. 2, 2021, 8:16 a.m. UTC
From: Stefan Chulski <stefanc@marvell.com>

This patch adds RXQ flow control configurations.
Flow control disabled by default.
Minimum ring size limited to 1024 descriptors.

Signed-off-by: Stefan Chulski <stefanc@marvell.com>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2.h      |  35 +++++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 116 ++++++++++++++++++++
 2 files changed, 150 insertions(+), 1 deletion(-)

Comments

Marcin Wojtas Feb. 4, 2021, 7 p.m. UTC | #1
Hi,

wt., 2 lut 2021 o 09:18 <stefanc@marvell.com> napisaƂ(a):
>

> From: Stefan Chulski <stefanc@marvell.com>

>

> This patch adds RXQ flow control configurations.

> Flow control disabled by default.

> Minimum ring size limited to 1024 descriptors.

>

> Signed-off-by: Stefan Chulski <stefanc@marvell.com>

> ---

>  drivers/net/ethernet/marvell/mvpp2/mvpp2.h      |  35 +++++-

>  drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 116 ++++++++++++++++++++

>  2 files changed, 150 insertions(+), 1 deletion(-)

>

> diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h

> index e010410..0f27be0 100644

> --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h

> +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h

> @@ -766,9 +766,36 @@

>  #define MSS_SRAM_SIZE                  0x800

>  #define MSS_FC_COM_REG                 0

>  #define FLOW_CONTROL_ENABLE_BIT                BIT(0)

> +#define FLOW_CONTROL_UPDATE_COMMAND_BIT        BIT(31)

>  #define FC_QUANTA                      0xFFFF

>  #define FC_CLK_DIVIDER                 100

> -#define MSS_THRESHOLD_STOP             768

> +

> +#define MSS_RXQ_TRESH_BASE             0x200

> +#define MSS_RXQ_TRESH_OFFS             4

> +#define MSS_RXQ_TRESH_REG(q, fq)       (MSS_RXQ_TRESH_BASE + (((q) + (fq)) \

> +                                       * MSS_RXQ_TRESH_OFFS))

> +

> +#define MSS_RXQ_TRESH_START_MASK       0xFFFF

> +#define MSS_RXQ_TRESH_STOP_MASK                (0xFFFF << MSS_RXQ_TRESH_STOP_OFFS)

> +#define MSS_RXQ_TRESH_STOP_OFFS                16

> +

> +#define MSS_RXQ_ASS_BASE       0x80

> +#define MSS_RXQ_ASS_OFFS       4

> +#define MSS_RXQ_ASS_PER_REG    4

> +#define MSS_RXQ_ASS_PER_OFFS   8

> +#define MSS_RXQ_ASS_PORTID_OFFS        0

> +#define MSS_RXQ_ASS_PORTID_MASK        0x3

> +#define MSS_RXQ_ASS_HOSTID_OFFS        2

> +#define MSS_RXQ_ASS_HOSTID_MASK        0x3F

> +

> +#define MSS_RXQ_ASS_Q_BASE(q, fq) ((((q) + (fq)) % MSS_RXQ_ASS_PER_REG)         \

> +                                 * MSS_RXQ_ASS_PER_OFFS)

> +#define MSS_RXQ_ASS_PQ_BASE(q, fq) ((((q) + (fq)) / MSS_RXQ_ASS_PER_REG) \

> +                                  * MSS_RXQ_ASS_OFFS)

> +#define MSS_RXQ_ASS_REG(q, fq) (MSS_RXQ_ASS_BASE + MSS_RXQ_ASS_PQ_BASE(q, fq))

> +

> +#define MSS_THRESHOLD_STOP     768

> +#define MSS_THRESHOLD_START    1024

>

>  /* RX buffer constants */

>  #define MVPP2_SKB_SHINFO_SIZE \

> @@ -1026,6 +1053,9 @@ struct mvpp2 {

>

>         /* Global TX Flow Control config */

>         bool global_tx_fc;

> +

> +       /* Spinlocks for CM3 shared memory configuration */

> +       spinlock_t mss_spinlock;

>  };

>

>  struct mvpp2_pcpu_stats {

> @@ -1188,6 +1218,9 @@ struct mvpp2_port {

>         bool rx_hwtstamp;

>         enum hwtstamp_tx_types tx_hwtstamp_type;

>         struct mvpp2_hwtstamp_queue tx_hwtstamp_queue[2];

> +

> +       /* Firmware TX flow control */

> +       bool tx_fc;

>  };

>

>  /* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the

> diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

> index 770f45a..d778ae1 100644

> --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

> +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

> @@ -742,6 +742,110 @@ static void *mvpp2_buf_alloc(struct mvpp2_port *port,

>         return data;

>  }

>

> +/* Routine enable flow control for RXQs condition */

> +static void mvpp2_rxq_enable_fc(struct mvpp2_port *port)

> +{

> +       int val, cm3_state, host_id, q;

> +       int fq = port->first_rxq;

> +       unsigned long flags;

> +

> +       spin_lock_irqsave(&port->priv->mss_spinlock, flags);

> +

> +       /* Remove Flow control enable bit to prevent race between FW and Kernel

> +        * If Flow control were enabled, it would be re-enabled.


Nit:

s/were/was/

Thanks,
Marcin


> +        */

> +       val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);

> +       cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);

> +       val &= ~FLOW_CONTROL_ENABLE_BIT;

> +       mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);

> +

> +       /* Set same Flow control for all RXQs */

> +       for (q = 0; q < port->nrxqs; q++) {

> +               /* Set stop and start Flow control RXQ thresholds */

> +               val = MSS_THRESHOLD_START;

> +               val |= (MSS_THRESHOLD_STOP << MSS_RXQ_TRESH_STOP_OFFS);

> +               mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);

> +

> +               val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));

> +               /* Set RXQ port ID */

> +               val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));

> +               val |= (port->id << MSS_RXQ_ASS_Q_BASE(q, fq));

> +               val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)

> +                       + MSS_RXQ_ASS_HOSTID_OFFS));

> +

> +               /* Calculate RXQ host ID:

> +                * In Single queue mode: Host ID equal to Host ID used for

> +                *                       shared RX interrupt

> +                * In Multi queue mode: Host ID equal to number of

> +                *                      RXQ ID / number of CoS queues

> +                * In Single resource mode: Host ID always equal to 0

> +                */

> +               if (queue_mode == MVPP2_QDIST_SINGLE_MODE)

> +                       host_id = port->nqvecs;

> +               else if (queue_mode == MVPP2_QDIST_MULTI_MODE)

> +                       host_id = q;

> +               else

> +                       host_id = 0;

> +

> +               /* Set RXQ host ID */

> +               val |= (host_id << (MSS_RXQ_ASS_Q_BASE(q, fq)

> +                       + MSS_RXQ_ASS_HOSTID_OFFS));

> +

> +               mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);

> +       }

> +

> +       /* Notify Firmware that Flow control config space ready for update */

> +       val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);

> +       val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;

> +       val |= cm3_state;

> +       mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);

> +

> +       spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);

> +}

> +

> +/* Routine disable flow control for RXQs condition */

> +static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)

> +{

> +       int val, cm3_state, q;

> +       unsigned long flags;

> +       int fq = port->first_rxq;

> +

> +       spin_lock_irqsave(&port->priv->mss_spinlock, flags);

> +

> +       /* Remove Flow control enable bit to prevent race between FW and Kernel

> +        * If Flow control were enabled, it would be re-enabled.

> +        */

> +       val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);

> +       cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);

> +       val &= ~FLOW_CONTROL_ENABLE_BIT;

> +       mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);

> +

> +       /* Disable Flow control for all RXQs */

> +       for (q = 0; q < port->nrxqs; q++) {

> +               /* Set threshold 0 to disable Flow control */

> +               val = 0;

> +               val |= (0 << MSS_RXQ_TRESH_STOP_OFFS);

> +               mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);

> +

> +               val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));

> +

> +               val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));

> +

> +               val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)

> +                       + MSS_RXQ_ASS_HOSTID_OFFS));

> +

> +               mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);

> +       }

> +

> +       /* Notify Firmware that Flow control config space ready for update */

> +       val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);

> +       val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;

> +       val |= cm3_state;

> +       mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);

> +

> +       spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);

> +}

> +

>  /* Release buffer to BM */

>  static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,

>                                      dma_addr_t buf_dma_addr,

> @@ -3006,6 +3110,9 @@ static void mvpp2_cleanup_rxqs(struct mvpp2_port *port)

>

>         for (queue = 0; queue < port->nrxqs; queue++)

>                 mvpp2_rxq_deinit(port, port->rxqs[queue]);

> +

> +       if (port->tx_fc)

> +               mvpp2_rxq_disable_fc(port);

>  }

>

>  /* Init all Rx queues for port */

> @@ -3018,6 +3125,10 @@ static int mvpp2_setup_rxqs(struct mvpp2_port *port)

>                 if (err)

>                         goto err_cleanup;

>         }

> +

> +       if (port->tx_fc)

> +               mvpp2_rxq_enable_fc(port);

> +

>         return 0;

>

>  err_cleanup:

> @@ -4317,6 +4428,8 @@ static int mvpp2_check_ringparam_valid(struct net_device *dev,

>

>         if (ring->rx_pending > MVPP2_MAX_RXD_MAX)

>                 new_rx_pending = MVPP2_MAX_RXD_MAX;

> +       else if (ring->rx_pending < MSS_THRESHOLD_START)

> +               new_rx_pending = MSS_THRESHOLD_START;

>         else if (!IS_ALIGNED(ring->rx_pending, 16))

>                 new_rx_pending = ALIGN(ring->rx_pending, 16);

>

> @@ -7170,6 +7283,9 @@ static int mvpp2_probe(struct platform_device *pdev)

>                         priv->hw_version = MVPP23;

>         }

>

> +       /* Init mss lock */

> +       spin_lock_init(&priv->mss_spinlock);

> +

>         /* Initialize network controller */

>         err = mvpp2_init(pdev, priv);

>         if (err < 0) {

> --

> 1.9.1

>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
index e010410..0f27be0 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -766,9 +766,36 @@ 
 #define MSS_SRAM_SIZE			0x800
 #define MSS_FC_COM_REG			0
 #define FLOW_CONTROL_ENABLE_BIT		BIT(0)
+#define FLOW_CONTROL_UPDATE_COMMAND_BIT	BIT(31)
 #define FC_QUANTA			0xFFFF
 #define FC_CLK_DIVIDER			100
-#define MSS_THRESHOLD_STOP		768
+
+#define MSS_RXQ_TRESH_BASE		0x200
+#define MSS_RXQ_TRESH_OFFS		4
+#define MSS_RXQ_TRESH_REG(q, fq)	(MSS_RXQ_TRESH_BASE + (((q) + (fq)) \
+					* MSS_RXQ_TRESH_OFFS))
+
+#define MSS_RXQ_TRESH_START_MASK	0xFFFF
+#define MSS_RXQ_TRESH_STOP_MASK		(0xFFFF << MSS_RXQ_TRESH_STOP_OFFS)
+#define MSS_RXQ_TRESH_STOP_OFFS		16
+
+#define MSS_RXQ_ASS_BASE	0x80
+#define MSS_RXQ_ASS_OFFS	4
+#define MSS_RXQ_ASS_PER_REG	4
+#define MSS_RXQ_ASS_PER_OFFS	8
+#define MSS_RXQ_ASS_PORTID_OFFS	0
+#define MSS_RXQ_ASS_PORTID_MASK	0x3
+#define MSS_RXQ_ASS_HOSTID_OFFS	2
+#define MSS_RXQ_ASS_HOSTID_MASK	0x3F
+
+#define MSS_RXQ_ASS_Q_BASE(q, fq) ((((q) + (fq)) % MSS_RXQ_ASS_PER_REG)	 \
+				  * MSS_RXQ_ASS_PER_OFFS)
+#define MSS_RXQ_ASS_PQ_BASE(q, fq) ((((q) + (fq)) / MSS_RXQ_ASS_PER_REG) \
+				   * MSS_RXQ_ASS_OFFS)
+#define MSS_RXQ_ASS_REG(q, fq) (MSS_RXQ_ASS_BASE + MSS_RXQ_ASS_PQ_BASE(q, fq))
+
+#define MSS_THRESHOLD_STOP	768
+#define MSS_THRESHOLD_START	1024
 
 /* RX buffer constants */
 #define MVPP2_SKB_SHINFO_SIZE \
@@ -1026,6 +1053,9 @@  struct mvpp2 {
 
 	/* Global TX Flow Control config */
 	bool global_tx_fc;
+
+	/* Spinlocks for CM3 shared memory configuration */
+	spinlock_t mss_spinlock;
 };
 
 struct mvpp2_pcpu_stats {
@@ -1188,6 +1218,9 @@  struct mvpp2_port {
 	bool rx_hwtstamp;
 	enum hwtstamp_tx_types tx_hwtstamp_type;
 	struct mvpp2_hwtstamp_queue tx_hwtstamp_queue[2];
+
+	/* Firmware TX flow control */
+	bool tx_fc;
 };
 
 /* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 770f45a..d778ae1 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -742,6 +742,110 @@  static void *mvpp2_buf_alloc(struct mvpp2_port *port,
 	return data;
 }
 
+/* Routine enable flow control for RXQs condition */
+static void mvpp2_rxq_enable_fc(struct mvpp2_port *port)
+{
+	int val, cm3_state, host_id, q;
+	int fq = port->first_rxq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->priv->mss_spinlock, flags);
+
+	/* Remove Flow control enable bit to prevent race between FW and Kernel
+	 * If Flow control were enabled, it would be re-enabled.
+	 */
+	val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
+	cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);
+	val &= ~FLOW_CONTROL_ENABLE_BIT;
+	mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
+
+	/* Set same Flow control for all RXQs */
+	for (q = 0; q < port->nrxqs; q++) {
+		/* Set stop and start Flow control RXQ thresholds */
+		val = MSS_THRESHOLD_START;
+		val |= (MSS_THRESHOLD_STOP << MSS_RXQ_TRESH_STOP_OFFS);
+		mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);
+
+		val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));
+		/* Set RXQ port ID */
+		val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));
+		val |= (port->id << MSS_RXQ_ASS_Q_BASE(q, fq));
+		val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)
+			+ MSS_RXQ_ASS_HOSTID_OFFS));
+
+		/* Calculate RXQ host ID:
+		 * In Single queue mode: Host ID equal to Host ID used for
+		 *			 shared RX interrupt
+		 * In Multi queue mode: Host ID equal to number of
+		 *			RXQ ID / number of CoS queues
+		 * In Single resource mode: Host ID always equal to 0
+		 */
+		if (queue_mode == MVPP2_QDIST_SINGLE_MODE)
+			host_id = port->nqvecs;
+		else if (queue_mode == MVPP2_QDIST_MULTI_MODE)
+			host_id = q;
+		else
+			host_id = 0;
+
+		/* Set RXQ host ID */
+		val |= (host_id << (MSS_RXQ_ASS_Q_BASE(q, fq)
+			+ MSS_RXQ_ASS_HOSTID_OFFS));
+
+		mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);
+	}
+
+	/* Notify Firmware that Flow control config space ready for update */
+	val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
+	val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;
+	val |= cm3_state;
+	mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
+
+	spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
+}
+
+/* Routine disable flow control for RXQs condition */
+static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)
+{
+	int val, cm3_state, q;
+	unsigned long flags;
+	int fq = port->first_rxq;
+
+	spin_lock_irqsave(&port->priv->mss_spinlock, flags);
+
+	/* Remove Flow control enable bit to prevent race between FW and Kernel
+	 * If Flow control were enabled, it would be re-enabled.
+	 */
+	val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
+	cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);
+	val &= ~FLOW_CONTROL_ENABLE_BIT;
+	mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
+
+	/* Disable Flow control for all RXQs */
+	for (q = 0; q < port->nrxqs; q++) {
+		/* Set threshold 0 to disable Flow control */
+		val = 0;
+		val |= (0 << MSS_RXQ_TRESH_STOP_OFFS);
+		mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);
+
+		val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));
+
+		val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));
+
+		val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)
+			+ MSS_RXQ_ASS_HOSTID_OFFS));
+
+		mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);
+	}
+
+	/* Notify Firmware that Flow control config space ready for update */
+	val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
+	val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;
+	val |= cm3_state;
+	mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
+
+	spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
+}
+
 /* Release buffer to BM */
 static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
 				     dma_addr_t buf_dma_addr,
@@ -3006,6 +3110,9 @@  static void mvpp2_cleanup_rxqs(struct mvpp2_port *port)
 
 	for (queue = 0; queue < port->nrxqs; queue++)
 		mvpp2_rxq_deinit(port, port->rxqs[queue]);
+
+	if (port->tx_fc)
+		mvpp2_rxq_disable_fc(port);
 }
 
 /* Init all Rx queues for port */
@@ -3018,6 +3125,10 @@  static int mvpp2_setup_rxqs(struct mvpp2_port *port)
 		if (err)
 			goto err_cleanup;
 	}
+
+	if (port->tx_fc)
+		mvpp2_rxq_enable_fc(port);
+
 	return 0;
 
 err_cleanup:
@@ -4317,6 +4428,8 @@  static int mvpp2_check_ringparam_valid(struct net_device *dev,
 
 	if (ring->rx_pending > MVPP2_MAX_RXD_MAX)
 		new_rx_pending = MVPP2_MAX_RXD_MAX;
+	else if (ring->rx_pending < MSS_THRESHOLD_START)
+		new_rx_pending = MSS_THRESHOLD_START;
 	else if (!IS_ALIGNED(ring->rx_pending, 16))
 		new_rx_pending = ALIGN(ring->rx_pending, 16);
 
@@ -7170,6 +7283,9 @@  static int mvpp2_probe(struct platform_device *pdev)
 			priv->hw_version = MVPP23;
 	}
 
+	/* Init mss lock */
+	spin_lock_init(&priv->mss_spinlock);
+
 	/* Initialize network controller */
 	err = mvpp2_init(pdev, priv);
 	if (err < 0) {