Skip to content

Commit 3bd17fd

Browse files
stefanchulskidavem330
authored andcommitted
net: mvpp2: add RXQ flow control configurations
This patch adds RXQ flow control configurations. Flow control disabled by default. Minimum ring size limited to 1024 descriptors. Signed-off-by: Stefan Chulski <[email protected]> Acked-by: Marcin Wojtas <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a59d354 commit 3bd17fd

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

drivers/net/ethernet/marvell/mvpp2/mvpp2.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,36 @@
765765
/* MSS Flow control */
766766
#define MSS_FC_COM_REG 0
767767
#define FLOW_CONTROL_ENABLE_BIT BIT(0)
768+
#define FLOW_CONTROL_UPDATE_COMMAND_BIT BIT(31)
768769
#define FC_QUANTA 0xFFFF
769770
#define FC_CLK_DIVIDER 100
770-
#define MSS_THRESHOLD_STOP 768
771+
772+
#define MSS_RXQ_TRESH_BASE 0x200
773+
#define MSS_RXQ_TRESH_OFFS 4
774+
#define MSS_RXQ_TRESH_REG(q, fq) (MSS_RXQ_TRESH_BASE + (((q) + (fq)) \
775+
* MSS_RXQ_TRESH_OFFS))
776+
777+
#define MSS_RXQ_TRESH_START_MASK 0xFFFF
778+
#define MSS_RXQ_TRESH_STOP_MASK (0xFFFF << MSS_RXQ_TRESH_STOP_OFFS)
779+
#define MSS_RXQ_TRESH_STOP_OFFS 16
780+
781+
#define MSS_RXQ_ASS_BASE 0x80
782+
#define MSS_RXQ_ASS_OFFS 4
783+
#define MSS_RXQ_ASS_PER_REG 4
784+
#define MSS_RXQ_ASS_PER_OFFS 8
785+
#define MSS_RXQ_ASS_PORTID_OFFS 0
786+
#define MSS_RXQ_ASS_PORTID_MASK 0x3
787+
#define MSS_RXQ_ASS_HOSTID_OFFS 2
788+
#define MSS_RXQ_ASS_HOSTID_MASK 0x3F
789+
790+
#define MSS_RXQ_ASS_Q_BASE(q, fq) ((((q) + (fq)) % MSS_RXQ_ASS_PER_REG) \
791+
* MSS_RXQ_ASS_PER_OFFS)
792+
#define MSS_RXQ_ASS_PQ_BASE(q, fq) ((((q) + (fq)) / MSS_RXQ_ASS_PER_REG) \
793+
* MSS_RXQ_ASS_OFFS)
794+
#define MSS_RXQ_ASS_REG(q, fq) (MSS_RXQ_ASS_BASE + MSS_RXQ_ASS_PQ_BASE(q, fq))
795+
796+
#define MSS_THRESHOLD_STOP 768
797+
#define MSS_THRESHOLD_START 1024
771798

772799
/* RX buffer constants */
773800
#define MVPP2_SKB_SHINFO_SIZE \
@@ -1022,6 +1049,9 @@ struct mvpp2 {
10221049

10231050
/* Global TX Flow Control config */
10241051
bool global_tx_fc;
1052+
1053+
/* Spinlocks for CM3 shared memory configuration */
1054+
spinlock_t mss_spinlock;
10251055
};
10261056

10271057
struct mvpp2_pcpu_stats {
@@ -1184,6 +1214,9 @@ struct mvpp2_port {
11841214
bool rx_hwtstamp;
11851215
enum hwtstamp_tx_types tx_hwtstamp_type;
11861216
struct mvpp2_hwtstamp_queue tx_hwtstamp_queue[2];
1217+
1218+
/* Firmware TX flow control */
1219+
bool tx_fc;
11871220
};
11881221

11891222
/* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the

drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,110 @@ static void *mvpp2_buf_alloc(struct mvpp2_port *port,
741741
return data;
742742
}
743743

744+
/* Routine enable flow control for RXQs condition */
745+
static void mvpp2_rxq_enable_fc(struct mvpp2_port *port)
746+
{
747+
int val, cm3_state, host_id, q;
748+
int fq = port->first_rxq;
749+
unsigned long flags;
750+
751+
spin_lock_irqsave(&port->priv->mss_spinlock, flags);
752+
753+
/* Remove Flow control enable bit to prevent race between FW and Kernel
754+
* If Flow control was enabled, it would be re-enabled.
755+
*/
756+
val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
757+
cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);
758+
val &= ~FLOW_CONTROL_ENABLE_BIT;
759+
mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
760+
761+
/* Set same Flow control for all RXQs */
762+
for (q = 0; q < port->nrxqs; q++) {
763+
/* Set stop and start Flow control RXQ thresholds */
764+
val = MSS_THRESHOLD_START;
765+
val |= (MSS_THRESHOLD_STOP << MSS_RXQ_TRESH_STOP_OFFS);
766+
mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);
767+
768+
val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));
769+
/* Set RXQ port ID */
770+
val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));
771+
val |= (port->id << MSS_RXQ_ASS_Q_BASE(q, fq));
772+
val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)
773+
+ MSS_RXQ_ASS_HOSTID_OFFS));
774+
775+
/* Calculate RXQ host ID:
776+
* In Single queue mode: Host ID equal to Host ID used for
777+
* shared RX interrupt
778+
* In Multi queue mode: Host ID equal to number of
779+
* RXQ ID / number of CoS queues
780+
* In Single resource mode: Host ID always equal to 0
781+
*/
782+
if (queue_mode == MVPP2_QDIST_SINGLE_MODE)
783+
host_id = port->nqvecs;
784+
else if (queue_mode == MVPP2_QDIST_MULTI_MODE)
785+
host_id = q;
786+
else
787+
host_id = 0;
788+
789+
/* Set RXQ host ID */
790+
val |= (host_id << (MSS_RXQ_ASS_Q_BASE(q, fq)
791+
+ MSS_RXQ_ASS_HOSTID_OFFS));
792+
793+
mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);
794+
}
795+
796+
/* Notify Firmware that Flow control config space ready for update */
797+
val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
798+
val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;
799+
val |= cm3_state;
800+
mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
801+
802+
spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
803+
}
804+
805+
/* Routine disable flow control for RXQs condition */
806+
static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)
807+
{
808+
int val, cm3_state, q;
809+
unsigned long flags;
810+
int fq = port->first_rxq;
811+
812+
spin_lock_irqsave(&port->priv->mss_spinlock, flags);
813+
814+
/* Remove Flow control enable bit to prevent race between FW and Kernel
815+
* If Flow control was enabled, it would be re-enabled.
816+
*/
817+
val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
818+
cm3_state = (val & FLOW_CONTROL_ENABLE_BIT);
819+
val &= ~FLOW_CONTROL_ENABLE_BIT;
820+
mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
821+
822+
/* Disable Flow control for all RXQs */
823+
for (q = 0; q < port->nrxqs; q++) {
824+
/* Set threshold 0 to disable Flow control */
825+
val = 0;
826+
val |= (0 << MSS_RXQ_TRESH_STOP_OFFS);
827+
mvpp2_cm3_write(port->priv, MSS_RXQ_TRESH_REG(q, fq), val);
828+
829+
val = mvpp2_cm3_read(port->priv, MSS_RXQ_ASS_REG(q, fq));
830+
831+
val &= ~(MSS_RXQ_ASS_PORTID_MASK << MSS_RXQ_ASS_Q_BASE(q, fq));
832+
833+
val &= ~(MSS_RXQ_ASS_HOSTID_MASK << (MSS_RXQ_ASS_Q_BASE(q, fq)
834+
+ MSS_RXQ_ASS_HOSTID_OFFS));
835+
836+
mvpp2_cm3_write(port->priv, MSS_RXQ_ASS_REG(q, fq), val);
837+
}
838+
839+
/* Notify Firmware that Flow control config space ready for update */
840+
val = mvpp2_cm3_read(port->priv, MSS_FC_COM_REG);
841+
val |= FLOW_CONTROL_UPDATE_COMMAND_BIT;
842+
val |= cm3_state;
843+
mvpp2_cm3_write(port->priv, MSS_FC_COM_REG, val);
844+
845+
spin_unlock_irqrestore(&port->priv->mss_spinlock, flags);
846+
}
847+
744848
/* Release buffer to BM */
745849
static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
746850
dma_addr_t buf_dma_addr,
@@ -3013,6 +3117,9 @@ static void mvpp2_cleanup_rxqs(struct mvpp2_port *port)
30133117

30143118
for (queue = 0; queue < port->nrxqs; queue++)
30153119
mvpp2_rxq_deinit(port, port->rxqs[queue]);
3120+
3121+
if (port->tx_fc)
3122+
mvpp2_rxq_disable_fc(port);
30163123
}
30173124

30183125
/* Init all Rx queues for port */
@@ -3025,6 +3132,10 @@ static int mvpp2_setup_rxqs(struct mvpp2_port *port)
30253132
if (err)
30263133
goto err_cleanup;
30273134
}
3135+
3136+
if (port->tx_fc)
3137+
mvpp2_rxq_enable_fc(port);
3138+
30283139
return 0;
30293140

30303141
err_cleanup:
@@ -4324,6 +4435,8 @@ static int mvpp2_check_ringparam_valid(struct net_device *dev,
43244435

43254436
if (ring->rx_pending > MVPP2_MAX_RXD_MAX)
43264437
new_rx_pending = MVPP2_MAX_RXD_MAX;
4438+
else if (ring->rx_pending < MSS_THRESHOLD_START)
4439+
new_rx_pending = MSS_THRESHOLD_START;
43274440
else if (!IS_ALIGNED(ring->rx_pending, 16))
43284441
new_rx_pending = ALIGN(ring->rx_pending, 16);
43294442

@@ -7156,6 +7269,9 @@ static int mvpp2_probe(struct platform_device *pdev)
71567269
priv->hw_version = MVPP23;
71577270
}
71587271

7272+
/* Init mss lock */
7273+
spin_lock_init(&priv->mss_spinlock);
7274+
71597275
/* Initialize network controller */
71607276
err = mvpp2_init(pdev, priv);
71617277
if (err < 0) {

0 commit comments

Comments
 (0)