@@ -845,6 +845,59 @@ static void mvpp2_rxq_disable_fc(struct mvpp2_port *port)
845
845
spin_unlock_irqrestore (& port -> priv -> mss_spinlock , flags );
846
846
}
847
847
848
+ /* Routine disable/enable flow control for BM pool condition */
849
+ static void mvpp2_bm_pool_update_fc (struct mvpp2_port * port ,
850
+ struct mvpp2_bm_pool * pool ,
851
+ bool en )
852
+ {
853
+ int val , cm3_state ;
854
+ unsigned long flags ;
855
+
856
+ spin_lock_irqsave (& port -> priv -> mss_spinlock , flags );
857
+
858
+ /* Remove Flow control enable bit to prevent race between FW and Kernel
859
+ * If Flow control were enabled, it would be re-enabled.
860
+ */
861
+ val = mvpp2_cm3_read (port -> priv , MSS_FC_COM_REG );
862
+ cm3_state = (val & FLOW_CONTROL_ENABLE_BIT );
863
+ val &= ~FLOW_CONTROL_ENABLE_BIT ;
864
+ mvpp2_cm3_write (port -> priv , MSS_FC_COM_REG , val );
865
+
866
+ /* Check if BM pool should be enabled/disable */
867
+ if (en ) {
868
+ /* Set BM pool start and stop thresholds per port */
869
+ val = mvpp2_cm3_read (port -> priv , MSS_BUF_POOL_REG (pool -> id ));
870
+ val |= MSS_BUF_POOL_PORT_OFFS (port -> id );
871
+ val &= ~MSS_BUF_POOL_START_MASK ;
872
+ val |= (MSS_THRESHOLD_START << MSS_BUF_POOL_START_OFFS );
873
+ val &= ~MSS_BUF_POOL_STOP_MASK ;
874
+ val |= MSS_THRESHOLD_STOP ;
875
+ mvpp2_cm3_write (port -> priv , MSS_BUF_POOL_REG (pool -> id ), val );
876
+ } else {
877
+ /* Remove BM pool from the port */
878
+ val = mvpp2_cm3_read (port -> priv , MSS_BUF_POOL_REG (pool -> id ));
879
+ val &= ~MSS_BUF_POOL_PORT_OFFS (port -> id );
880
+
881
+ /* Zero BM pool start and stop thresholds to disable pool
882
+ * flow control if pool empty (not used by any port)
883
+ */
884
+ if (!pool -> buf_num ) {
885
+ val &= ~MSS_BUF_POOL_START_MASK ;
886
+ val &= ~MSS_BUF_POOL_STOP_MASK ;
887
+ }
888
+
889
+ mvpp2_cm3_write (port -> priv , MSS_BUF_POOL_REG (pool -> id ), val );
890
+ }
891
+
892
+ /* Notify Firmware that Flow control config space ready for update */
893
+ val = mvpp2_cm3_read (port -> priv , MSS_FC_COM_REG );
894
+ val |= FLOW_CONTROL_UPDATE_COMMAND_BIT ;
895
+ val |= cm3_state ;
896
+ mvpp2_cm3_write (port -> priv , MSS_FC_COM_REG , val );
897
+
898
+ spin_unlock_irqrestore (& port -> priv -> mss_spinlock , flags );
899
+ }
900
+
848
901
/* Release buffer to BM */
849
902
static inline void mvpp2_bm_pool_put (struct mvpp2_port * port , int pool ,
850
903
dma_addr_t buf_dma_addr ,
@@ -1175,6 +1228,16 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
1175
1228
new_long_pool = MVPP2_BM_LONG ;
1176
1229
1177
1230
if (new_long_pool != port -> pool_long -> id ) {
1231
+ if (port -> tx_fc ) {
1232
+ if (pkt_size > MVPP2_BM_LONG_PKT_SIZE )
1233
+ mvpp2_bm_pool_update_fc (port ,
1234
+ port -> pool_short ,
1235
+ false);
1236
+ else
1237
+ mvpp2_bm_pool_update_fc (port , port -> pool_long ,
1238
+ false);
1239
+ }
1240
+
1178
1241
/* Remove port from old short & long pool */
1179
1242
port -> pool_long = mvpp2_bm_pool_use (port , port -> pool_long -> id ,
1180
1243
port -> pool_long -> pkt_size );
@@ -1192,6 +1255,25 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
1192
1255
mvpp2_swf_bm_pool_init (port );
1193
1256
1194
1257
mvpp2_set_hw_csum (port , new_long_pool );
1258
+
1259
+ if (port -> tx_fc ) {
1260
+ if (pkt_size > MVPP2_BM_LONG_PKT_SIZE )
1261
+ mvpp2_bm_pool_update_fc (port , port -> pool_long ,
1262
+ true);
1263
+ else
1264
+ mvpp2_bm_pool_update_fc (port , port -> pool_short ,
1265
+ true);
1266
+ }
1267
+
1268
+ /* Update L4 checksum when jumbo enable/disable on port */
1269
+ if (new_long_pool == MVPP2_BM_JUMBO && port -> id != 0 ) {
1270
+ dev -> features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM );
1271
+ dev -> hw_features &= ~(NETIF_F_IP_CSUM |
1272
+ NETIF_F_IPV6_CSUM );
1273
+ } else {
1274
+ dev -> features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM ;
1275
+ dev -> hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM ;
1276
+ }
1195
1277
}
1196
1278
1197
1279
out_set :
@@ -6365,6 +6447,7 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
6365
6447
{
6366
6448
struct mvpp2_port * port = mvpp2_phylink_to_port (config );
6367
6449
u32 val ;
6450
+ int i ;
6368
6451
6369
6452
if (mvpp2_is_xlg (interface )) {
6370
6453
if (!phylink_autoneg_inband (mode )) {
@@ -6415,6 +6498,21 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
6415
6498
val );
6416
6499
}
6417
6500
6501
+ if (port -> priv -> global_tx_fc ) {
6502
+ port -> tx_fc = tx_pause ;
6503
+ if (tx_pause )
6504
+ mvpp2_rxq_enable_fc (port );
6505
+ else
6506
+ mvpp2_rxq_disable_fc (port );
6507
+ if (port -> priv -> percpu_pools ) {
6508
+ for (i = 0 ; i < port -> nrxqs ; i ++ )
6509
+ mvpp2_bm_pool_update_fc (port , & port -> priv -> bm_pools [i ], tx_pause );
6510
+ } else {
6511
+ mvpp2_bm_pool_update_fc (port , port -> pool_long , tx_pause );
6512
+ mvpp2_bm_pool_update_fc (port , port -> pool_short , tx_pause );
6513
+ }
6514
+ }
6515
+
6418
6516
mvpp2_port_enable (port );
6419
6517
6420
6518
mvpp2_egress_enable (port );
0 commit comments