Hi, wt., 2 lut 2021 o 09:18 <stef...@marvell.com> napisaĆ(a): > > From: Stefan Chulski <stef...@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 <stef...@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 >