Skip to content

Commit

Permalink
net: mvpp2: add RXQ flow control configurations
Browse files Browse the repository at this point in the history
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>
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 a59d354 commit 3bd17fd
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 1 deletion.
35 changes: 34 additions & 1 deletion drivers/net/ethernet/marvell/mvpp2/mvpp2.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,9 +765,36 @@
/* MSS Flow control */
#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 \
Expand Down Expand Up @@ -1022,6 +1049,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 {
Expand Down Expand Up @@ -1184,6 +1214,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
Expand Down
116 changes: 116 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,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 was 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 was 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,
Expand Down Expand Up @@ -3013,6 +3117,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 */
Expand All @@ -3025,6 +3132,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:
Expand Down Expand Up @@ -4324,6 +4435,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);

Expand Down Expand Up @@ -7156,6 +7269,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) {
Expand Down

0 comments on commit 3bd17fd

Please sign in to comment.