Skip to content

Commit

Permalink
net: mvpp2: add ethtool flow control configuration support
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Stefan Chulski <stefanc@marvell.com>
Acked-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Stefan Chulski authored and David S. Miller committed Feb 11, 2021
1 parent 3bd17fd commit 7605583
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
13 changes: 13 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,19 @@
#define MSS_RXQ_TRESH_REG(q, fq) (MSS_RXQ_TRESH_BASE + (((q) + (fq)) \
* MSS_RXQ_TRESH_OFFS))

#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
Expand Down
98 changes: 98 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,59 @@ static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)
spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
}

/* 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;

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);

/* 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,
Expand Down Expand Up @@ -1175,6 +1228,16 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
new_long_pool = MVPP2_BM_LONG;

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);
Expand All @@ -1192,6 +1255,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:
Expand Down Expand Up @@ -6365,6 +6447,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)) {
Expand Down Expand Up @@ -6415,6 +6498,21 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
val);
}

if (port->priv->global_tx_fc) {
port->tx_fc = tx_pause;
if (tx_pause)
mvpp2_rxq_enable_fc(port);
else
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], tx_pause);
} else {
mvpp2_bm_pool_update_fc(port, port->pool_long, tx_pause);
mvpp2_bm_pool_update_fc(port, port->pool_short, tx_pause);
}
}

mvpp2_port_enable(port);

mvpp2_egress_enable(port);
Expand Down

0 comments on commit 7605583

Please sign in to comment.