@@ -250,13 +250,84 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
250
250
return 0 ;
251
251
}
252
252
253
+ static void bcm_sf2_cfp_slice_ipv4 (struct bcm_sf2_priv * priv ,
254
+ struct ethtool_tcpip4_spec * v4_spec ,
255
+ unsigned int slice_num ,
256
+ bool mask )
257
+ {
258
+ u32 reg , offset ;
259
+
260
+ /* C-Tag [31:24]
261
+ * UDF_n_A8 [23:8]
262
+ * UDF_n_A7 [7:0]
263
+ */
264
+ reg = 0 ;
265
+ if (mask )
266
+ offset = CORE_CFP_MASK_PORT (4 );
267
+ else
268
+ offset = CORE_CFP_DATA_PORT (4 );
269
+ core_writel (priv , reg , offset );
270
+
271
+ /* UDF_n_A7 [31:24]
272
+ * UDF_n_A6 [23:8]
273
+ * UDF_n_A5 [7:0]
274
+ */
275
+ reg = be16_to_cpu (v4_spec -> pdst ) >> 8 ;
276
+ if (mask )
277
+ offset = CORE_CFP_MASK_PORT (3 );
278
+ else
279
+ offset = CORE_CFP_DATA_PORT (3 );
280
+ core_writel (priv , reg , offset );
281
+
282
+ /* UDF_n_A5 [31:24]
283
+ * UDF_n_A4 [23:8]
284
+ * UDF_n_A3 [7:0]
285
+ */
286
+ reg = (be16_to_cpu (v4_spec -> pdst ) & 0xff ) << 24 |
287
+ (u32 )be16_to_cpu (v4_spec -> psrc ) << 8 |
288
+ (be32_to_cpu (v4_spec -> ip4dst ) & 0x0000ff00 ) >> 8 ;
289
+ if (mask )
290
+ offset = CORE_CFP_MASK_PORT (2 );
291
+ else
292
+ offset = CORE_CFP_DATA_PORT (2 );
293
+ core_writel (priv , reg , offset );
294
+
295
+ /* UDF_n_A3 [31:24]
296
+ * UDF_n_A2 [23:8]
297
+ * UDF_n_A1 [7:0]
298
+ */
299
+ reg = (u32 )(be32_to_cpu (v4_spec -> ip4dst ) & 0xff ) << 24 |
300
+ (u32 )(be32_to_cpu (v4_spec -> ip4dst ) >> 16 ) << 8 |
301
+ (be32_to_cpu (v4_spec -> ip4src ) & 0x0000ff00 ) >> 8 ;
302
+ if (mask )
303
+ offset = CORE_CFP_MASK_PORT (1 );
304
+ else
305
+ offset = CORE_CFP_DATA_PORT (1 );
306
+ core_writel (priv , reg , offset );
307
+
308
+ /* UDF_n_A1 [31:24]
309
+ * UDF_n_A0 [23:8]
310
+ * Reserved [7:4]
311
+ * Slice ID [3:2]
312
+ * Slice valid [1:0]
313
+ */
314
+ reg = (u32 )(be32_to_cpu (v4_spec -> ip4src ) & 0xff ) << 24 |
315
+ (u32 )(be32_to_cpu (v4_spec -> ip4src ) >> 16 ) << 8 |
316
+ SLICE_NUM (slice_num ) | SLICE_VALID ;
317
+ if (mask )
318
+ offset = CORE_CFP_MASK_PORT (0 );
319
+ else
320
+ offset = CORE_CFP_DATA_PORT (0 );
321
+ core_writel (priv , reg , offset );
322
+ }
323
+
253
324
static int bcm_sf2_cfp_ipv4_rule_set (struct bcm_sf2_priv * priv , int port ,
254
325
unsigned int port_num ,
255
326
unsigned int queue_num ,
256
327
struct ethtool_rx_flow_spec * fs )
257
328
{
329
+ struct ethtool_tcpip4_spec * v4_spec , * v4_m_spec ;
258
330
const struct cfp_udf_layout * layout ;
259
- struct ethtool_tcpip4_spec * v4_spec ;
260
331
unsigned int slice_num , rule_index ;
261
332
u8 ip_proto , ip_frag ;
262
333
u8 num_udf ;
@@ -267,10 +338,12 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
267
338
case TCP_V4_FLOW :
268
339
ip_proto = IPPROTO_TCP ;
269
340
v4_spec = & fs -> h_u .tcp_ip4_spec ;
341
+ v4_m_spec = & fs -> m_u .tcp_ip4_spec ;
270
342
break ;
271
343
case UDP_V4_FLOW :
272
344
ip_proto = IPPROTO_UDP ;
273
345
v4_spec = & fs -> h_u .udp_ip4_spec ;
346
+ v4_m_spec = & fs -> m_u .udp_ip4_spec ;
274
347
break ;
275
348
default :
276
349
return - EINVAL ;
@@ -321,69 +394,22 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
321
394
udf_upper_bits (num_udf ),
322
395
CORE_CFP_DATA_PORT (6 ));
323
396
397
+ /* Mask with the specific layout for IPv4 packets */
398
+ core_writel (priv , layout -> udfs [slice_num ].mask_value |
399
+ udf_upper_bits (num_udf ), CORE_CFP_MASK_PORT (6 ));
400
+
324
401
/* UDF_Valid[7:0] [31:24]
325
402
* S-Tag [23:8]
326
403
* C-Tag [7:0]
327
404
*/
328
405
core_writel (priv , udf_lower_bits (num_udf ) << 24 , CORE_CFP_DATA_PORT (5 ));
329
406
330
- /* C-Tag [31:24]
331
- * UDF_n_A8 [23:8]
332
- * UDF_n_A7 [7:0]
333
- */
334
- core_writel (priv , 0 , CORE_CFP_DATA_PORT (4 ));
335
-
336
- /* UDF_n_A7 [31:24]
337
- * UDF_n_A6 [23:8]
338
- * UDF_n_A5 [7:0]
339
- */
340
- core_writel (priv , be16_to_cpu (v4_spec -> pdst ) >> 8 ,
341
- CORE_CFP_DATA_PORT (3 ));
342
-
343
- /* UDF_n_A5 [31:24]
344
- * UDF_n_A4 [23:8]
345
- * UDF_n_A3 [7:0]
346
- */
347
- reg = (be16_to_cpu (v4_spec -> pdst ) & 0xff ) << 24 |
348
- (u32 )be16_to_cpu (v4_spec -> psrc ) << 8 |
349
- (be32_to_cpu (v4_spec -> ip4dst ) & 0x0000ff00 ) >> 8 ;
350
- core_writel (priv , reg , CORE_CFP_DATA_PORT (2 ));
351
-
352
- /* UDF_n_A3 [31:24]
353
- * UDF_n_A2 [23:8]
354
- * UDF_n_A1 [7:0]
355
- */
356
- reg = (u32 )(be32_to_cpu (v4_spec -> ip4dst ) & 0xff ) << 24 |
357
- (u32 )(be32_to_cpu (v4_spec -> ip4dst ) >> 16 ) << 8 |
358
- (be32_to_cpu (v4_spec -> ip4src ) & 0x0000ff00 ) >> 8 ;
359
- core_writel (priv , reg , CORE_CFP_DATA_PORT (1 ));
360
-
361
- /* UDF_n_A1 [31:24]
362
- * UDF_n_A0 [23:8]
363
- * Reserved [7:4]
364
- * Slice ID [3:2]
365
- * Slice valid [1:0]
366
- */
367
- reg = (u32 )(be32_to_cpu (v4_spec -> ip4src ) & 0xff ) << 24 |
368
- (u32 )(be32_to_cpu (v4_spec -> ip4src ) >> 16 ) << 8 |
369
- SLICE_NUM (slice_num ) | SLICE_VALID ;
370
- core_writel (priv , reg , CORE_CFP_DATA_PORT (0 ));
371
-
372
- /* Mask with the specific layout for IPv4 packets */
373
- core_writel (priv , layout -> udfs [slice_num ].mask_value |
374
- udf_upper_bits (num_udf ), CORE_CFP_MASK_PORT (6 ));
375
-
376
407
/* Mask all but valid UDFs */
377
408
core_writel (priv , udf_lower_bits (num_udf ) << 24 , CORE_CFP_MASK_PORT (5 ));
378
409
379
- /* Mask all */
380
- core_writel (priv , 0 , CORE_CFP_MASK_PORT (4 ));
381
-
382
- /* All other UDFs should be matched with the filter */
383
- core_writel (priv , 0xff , CORE_CFP_MASK_PORT (3 ));
384
- core_writel (priv , 0xffffffff , CORE_CFP_MASK_PORT (2 ));
385
- core_writel (priv , 0xffffffff , CORE_CFP_MASK_PORT (1 ));
386
- core_writel (priv , 0xffffff0f , CORE_CFP_MASK_PORT (0 ));
410
+ /* Program the match and the mask */
411
+ bcm_sf2_cfp_slice_ipv4 (priv , v4_spec , slice_num , false);
412
+ bcm_sf2_cfp_slice_ipv4 (priv , v4_m_spec , SLICE_NUM_MASK , true);
387
413
388
414
/* Insert into TCAM now */
389
415
bcm_sf2_cfp_rule_addr_set (priv , rule_index );
@@ -802,73 +828,108 @@ static void bcm_sf2_invert_masks(struct ethtool_rx_flow_spec *flow)
802
828
flow -> m_ext .data [1 ] ^= cpu_to_be32 (~0 );
803
829
}
804
830
805
- static int bcm_sf2_cfp_ipv4_rule_get (struct bcm_sf2_priv * priv , int port ,
806
- struct ethtool_rx_flow_spec * fs )
831
+ static int bcm_sf2_cfp_unslice_ipv4 (struct bcm_sf2_priv * priv ,
832
+ struct ethtool_tcpip4_spec * v4_spec ,
833
+ bool mask )
807
834
{
808
- struct ethtool_tcpip4_spec * v4_spec = NULL , * v4_m_spec = NULL ;
835
+ u32 reg , offset , ipv4 ;
809
836
u16 src_dst_port ;
810
- u32 reg , ipv4 ;
811
-
812
- reg = core_readl (priv , CORE_CFP_DATA_PORT (6 ));
813
837
814
- switch ((reg & IPPROTO_MASK ) >> IPPROTO_SHIFT ) {
815
- case IPPROTO_TCP :
816
- fs -> flow_type = TCP_V4_FLOW ;
817
- v4_spec = & fs -> h_u .tcp_ip4_spec ;
818
- v4_m_spec = & fs -> m_u .tcp_ip4_spec ;
819
- break ;
820
- case IPPROTO_UDP :
821
- fs -> flow_type = UDP_V4_FLOW ;
822
- v4_spec = & fs -> h_u .udp_ip4_spec ;
823
- v4_m_spec = & fs -> m_u .udp_ip4_spec ;
824
- break ;
825
- default :
826
- return - EINVAL ;
827
- }
828
-
829
- fs -> m_ext .data [0 ] = cpu_to_be32 ((reg >> IP_FRAG_SHIFT ) & 1 );
830
- v4_spec -> tos = (reg >> IPTOS_SHIFT ) & IPTOS_MASK ;
838
+ if (mask )
839
+ offset = CORE_CFP_MASK_PORT (3 );
840
+ else
841
+ offset = CORE_CFP_DATA_PORT (3 );
831
842
832
- reg = core_readl (priv , CORE_CFP_DATA_PORT ( 3 ) );
843
+ reg = core_readl (priv , offset );
833
844
/* src port [15:8] */
834
845
src_dst_port = reg << 8 ;
835
846
836
- reg = core_readl (priv , CORE_CFP_DATA_PORT (2 ));
847
+ if (mask )
848
+ offset = CORE_CFP_MASK_PORT (2 );
849
+ else
850
+ offset = CORE_CFP_DATA_PORT (2 );
851
+
852
+ reg = core_readl (priv , offset );
837
853
/* src port [7:0] */
838
854
src_dst_port |= (reg >> 24 );
839
855
840
856
v4_spec -> pdst = cpu_to_be16 (src_dst_port );
841
- v4_m_spec -> pdst = cpu_to_be16 (~0 );
842
857
v4_spec -> psrc = cpu_to_be16 ((u16 )(reg >> 8 ));
843
- v4_m_spec -> psrc = cpu_to_be16 (~0 );
844
858
845
859
/* IPv4 dst [15:8] */
846
860
ipv4 = (reg & 0xff ) << 8 ;
847
- reg = core_readl (priv , CORE_CFP_DATA_PORT (1 ));
861
+
862
+ if (mask )
863
+ offset = CORE_CFP_MASK_PORT (1 );
864
+ else
865
+ offset = CORE_CFP_DATA_PORT (1 );
866
+
867
+ reg = core_readl (priv , offset );
848
868
/* IPv4 dst [31:16] */
849
869
ipv4 |= ((reg >> 8 ) & 0xffff ) << 16 ;
850
870
/* IPv4 dst [7:0] */
851
871
ipv4 |= (reg >> 24 ) & 0xff ;
852
872
v4_spec -> ip4dst = cpu_to_be32 (ipv4 );
853
- v4_m_spec -> ip4dst = cpu_to_be32 (~0 );
854
873
855
874
/* IPv4 src [15:8] */
856
875
ipv4 = (reg & 0xff ) << 8 ;
857
- reg = core_readl (priv , CORE_CFP_DATA_PORT (0 ));
858
876
859
- if (!(reg & SLICE_VALID ))
877
+ if (mask )
878
+ offset = CORE_CFP_MASK_PORT (0 );
879
+ else
880
+ offset = CORE_CFP_DATA_PORT (0 );
881
+ reg = core_readl (priv , offset );
882
+
883
+ /* Once the TCAM is programmed, the mask reflects the slice number
884
+ * being matched, don't bother checking it when reading back the
885
+ * mask spec
886
+ */
887
+ if (!mask && !(reg & SLICE_VALID ))
860
888
return - EINVAL ;
861
889
862
890
/* IPv4 src [7:0] */
863
891
ipv4 |= (reg >> 24 ) & 0xff ;
864
892
/* IPv4 src [31:16] */
865
893
ipv4 |= ((reg >> 8 ) & 0xffff ) << 16 ;
866
894
v4_spec -> ip4src = cpu_to_be32 (ipv4 );
867
- v4_m_spec -> ip4src = cpu_to_be32 (~0 );
868
895
869
896
return 0 ;
870
897
}
871
898
899
+ static int bcm_sf2_cfp_ipv4_rule_get (struct bcm_sf2_priv * priv , int port ,
900
+ struct ethtool_rx_flow_spec * fs )
901
+ {
902
+ struct ethtool_tcpip4_spec * v4_spec = NULL , * v4_m_spec = NULL ;
903
+ u32 reg ;
904
+ int ret ;
905
+
906
+ reg = core_readl (priv , CORE_CFP_DATA_PORT (6 ));
907
+
908
+ switch ((reg & IPPROTO_MASK ) >> IPPROTO_SHIFT ) {
909
+ case IPPROTO_TCP :
910
+ fs -> flow_type = TCP_V4_FLOW ;
911
+ v4_spec = & fs -> h_u .tcp_ip4_spec ;
912
+ v4_m_spec = & fs -> m_u .tcp_ip4_spec ;
913
+ break ;
914
+ case IPPROTO_UDP :
915
+ fs -> flow_type = UDP_V4_FLOW ;
916
+ v4_spec = & fs -> h_u .udp_ip4_spec ;
917
+ v4_m_spec = & fs -> m_u .udp_ip4_spec ;
918
+ break ;
919
+ default :
920
+ return - EINVAL ;
921
+ }
922
+
923
+ fs -> m_ext .data [0 ] = cpu_to_be32 ((reg >> IP_FRAG_SHIFT ) & 1 );
924
+ v4_spec -> tos = (reg >> IPTOS_SHIFT ) & IPTOS_MASK ;
925
+
926
+ ret = bcm_sf2_cfp_unslice_ipv4 (priv , v4_spec , false);
927
+ if (ret )
928
+ return ret ;
929
+
930
+ return bcm_sf2_cfp_unslice_ipv4 (priv , v4_m_spec , true);
931
+ }
932
+
872
933
static int bcm_sf2_cfp_unslice_ipv6 (struct bcm_sf2_priv * priv ,
873
934
__be32 * ip6_addr , __be16 * port ,
874
935
__be32 * ip6_mask , __be16 * port_mask )
0 commit comments