--- v2
+++ vrfc
@@ -1,188 +1,54 @@
From: Stefan Chulski <stefanc@marvell.com>
-This patch add ethtool flow control configuration support.
-
-Tx flow control retrieved correctly by ethtool get function.
-FW per port ethtool configuration capability added.
-
-Patch also takes care about mtu change procedure, if PPv2 switch
-BM pools during mtu change.
+This patch add RXQ flow control configurations.
+Patch do not enable flow control itself, flow control
+disabled by default.
Signed-off-by: Stefan Chulski <stefanc@marvell.com>
---
- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 13 +++
- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 106 ++++++++++++++++++++
- 2 files changed, 119 insertions(+)
+ drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 3 +++
+ drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 +++++++
+ 2 files changed, 10 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
-index ba57465..feac64c 100644
+index e6bab52..57f7bbc 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
-@@ -775,6 +775,19 @@
- #define MSS_RXQ_TRESH_REG(q, fq) (MSS_RXQ_TRESH_BASE + (((q) + (fq)) \
- * MSS_RXQ_TRESH_OFFS))
+@@ -1234,6 +1234,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;
+ };
-+#define MSS_BUF_POOL_BASE 0x40
-+#define MSS_BUF_POOL_OFFS 4
-+#define MSS_BUF_POOL_REG(id) (MSS_BUF_POOL_BASE \
-+ + (id) * MSS_BUF_POOL_OFFS)
-+
-+#define MSS_BUF_POOL_STOP_MASK 0xFFF
-+#define MSS_BUF_POOL_START_MASK (0xFFF << MSS_BUF_POOL_START_OFFS)
-+#define MSS_BUF_POOL_START_OFFS 12
-+#define MSS_BUF_POOL_PORTS_MASK (0xF << MSS_BUF_POOL_PORTS_OFFS)
-+#define MSS_BUF_POOL_PORTS_OFFS 24
-+#define MSS_BUF_POOL_PORT_OFFS(id) (0x1 << \
-+ ((id) + MSS_BUF_POOL_PORTS_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
+ /* 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 2407c52..20157b5 100644
+index b7ea94f..3b85aec 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
-@@ -848,6 +848,59 @@ static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)
- spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
+@@ -3176,6 +3176,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);
}
-+/* Routine disable/enable flow control for BM pool condition */
-+static void mvpp2_bm_pool_update_fc(struct mvpp2_port *port,
-+ struct mvpp2_bm_pool *pool,
-+ bool en)
-+{
-+ int val, cm3_state;
-+ unsigned long flags;
+ /* Init all Rx queues for port */
+@@ -3188,6 +3191,10 @@ static int mvpp2_setup_rxqs(struct mvpp2_port *port)
+ if (err)
+ goto err_cleanup;
+ }
+
-+ spin_lock_irqsave(&port->priv->mss_spinlock, flags);
++ if (port->tx_fc)
++ mvpp2_rxq_enable_fc(port);
+
-+ /* 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);
-+
-+ /* Check if BM pool should be enabled/disable */
-+ if (en) {
-+ /* Set BM pool start and stop thresholds per port */
-+ val = mvpp2_cm3_read(port->priv, MSS_BUF_POOL_REG(pool->id));
-+ val |= MSS_BUF_POOL_PORT_OFFS(port->id);
-+ val &= ~MSS_BUF_POOL_START_MASK;
-+ val |= (MSS_THRESHOLD_START << MSS_BUF_POOL_START_OFFS);
-+ val &= ~MSS_BUF_POOL_STOP_MASK;
-+ val |= MSS_THRESHOLD_STOP;
-+ mvpp2_cm3_write(port->priv, MSS_BUF_POOL_REG(pool->id), val);
-+ } else {
-+ /* Remove BM pool from the port */
-+ val = mvpp2_cm3_read(port->priv, MSS_BUF_POOL_REG(pool->id));
-+ val &= ~MSS_BUF_POOL_PORT_OFFS(port->id);
-+
-+ /* Zero BM pool start and stop thresholds to disable pool
-+ * flow control if pool empty (not used by any port)
-+ */
-+ if (!pool->buf_num) {
-+ val &= ~MSS_BUF_POOL_START_MASK;
-+ val &= ~MSS_BUF_POOL_STOP_MASK;
-+ }
-+
-+ mvpp2_cm3_write(port->priv, MSS_BUF_POOL_REG(pool->id), 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,
-@@ -1178,6 +1231,16 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
- new_long_pool = MVPP2_BM_LONG;
+ return 0;
- if (new_long_pool != port->pool_long->id) {
-+ if (port->tx_fc) {
-+ if (pkt_size > MVPP2_BM_LONG_PKT_SIZE)
-+ mvpp2_bm_pool_update_fc(port,
-+ port->pool_short,
-+ false);
-+ else
-+ mvpp2_bm_pool_update_fc(port, port->pool_long,
-+ false);
-+ }
-+
- /* Remove port from old short & long pool */
- port->pool_long = mvpp2_bm_pool_use(port, port->pool_long->id,
- port->pool_long->pkt_size);
-@@ -1195,6 +1258,25 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
- mvpp2_swf_bm_pool_init(port);
-
- mvpp2_set_hw_csum(port, new_long_pool);
-+
-+ if (port->tx_fc) {
-+ if (pkt_size > MVPP2_BM_LONG_PKT_SIZE)
-+ mvpp2_bm_pool_update_fc(port, port->pool_long,
-+ true);
-+ else
-+ mvpp2_bm_pool_update_fc(port, port->pool_short,
-+ true);
-+ }
-+
-+ /* Update L4 checksum when jumbo enable/disable on port */
-+ if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-+ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-+ dev->hw_features &= ~(NETIF_F_IP_CSUM |
-+ NETIF_F_IPV6_CSUM);
-+ } else {
-+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-+ dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-+ }
- }
-
- out_set:
-@@ -6357,6 +6439,7 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
- {
- struct mvpp2_port *port = mvpp2_phylink_to_port(config);
- u32 val;
-+ int i;
-
- if (mvpp2_is_xlg(interface)) {
- if (!phylink_autoneg_inband(mode)) {
-@@ -6407,6 +6490,29 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
- val);
- }
-
-+ if (tx_pause && port->priv->global_tx_fc) {
-+ port->tx_fc = true;
-+ mvpp2_rxq_enable_fc(port);
-+ if (port->priv->percpu_pools) {
-+ for (i = 0; i < port->nrxqs; i++)
-+ mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], true);
-+ } else {
-+ mvpp2_bm_pool_update_fc(port, port->pool_long, true);
-+ mvpp2_bm_pool_update_fc(port, port->pool_short, true);
-+ }
-+
-+ } else if (port->priv->global_tx_fc) {
-+ port->tx_fc = false;
-+ mvpp2_rxq_disable_fc(port);
-+ if (port->priv->percpu_pools) {
-+ for (i = 0; i < port->nrxqs; i++)
-+ mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], false);
-+ } else {
-+ mvpp2_bm_pool_update_fc(port, port->pool_long, false);
-+ mvpp2_bm_pool_update_fc(port, port->pool_short, false);
-+ }
-+ }
-+
- mvpp2_port_enable(port);
-
- mvpp2_egress_enable(port);
+ err_cleanup:
--
1.9.1