lkml.org 
[lkml]   [2021]   [Feb]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 net-next 10/15] net: mvpp2: add RXQ flow control configurations
    Date
    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.
    + */
    + 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
    \
     
     \ /
      Last update: 2021-02-02 09:20    [W:3.402 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site