Skip to content

Commit 5d80bcb

Browse files
ffainellidavem330
authored andcommitted
net: dsa: bcm_sf2: Make UDF slices more configurable
In preparation for introducing IPv6 rules support, make the cfp_udf_layout more flexible and match more accurately how the HW is designed: we have 3 + 1 slices per protocol, but we may not be using all of them and we are relative to a particular base offset (slice A for IPv4 for instance). Also populate the slice number that should be used (slice 1 for IPv4) based on the lookup function. Finally, we introduce two helper functions: udf_upper_bits() and udf_lower_bits() to help setting the UDF_n_* valid bits based on the number of UDFs valid within a slice. Update the IPv4 rule setting to make use of it to be more robust wrt. change in number of User Defined Fields being programmed. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3306145 commit 5d80bcb

File tree

2 files changed

+76
-32
lines changed

2 files changed

+76
-32
lines changed

drivers/net/dsa/bcm_sf2_cfp.c

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,53 +20,91 @@
2020
#include "bcm_sf2.h"
2121
#include "bcm_sf2_regs.h"
2222

23-
struct cfp_udf_layout {
24-
u8 slices[UDF_NUM_SLICES];
23+
struct cfp_udf_slice_layout {
24+
u8 slices[UDFS_PER_SLICE];
2525
u32 mask_value;
26+
u32 base_offset;
27+
};
2628

29+
struct cfp_udf_layout {
30+
struct cfp_udf_slice_layout udfs[UDF_NUM_SLICES];
2731
};
2832

33+
static const u8 zero_slice[UDFS_PER_SLICE] = { };
34+
2935
/* UDF slices layout for a TCPv4/UDPv4 specification */
3036
static const struct cfp_udf_layout udf_tcpip4_layout = {
31-
.slices = {
32-
/* End of L2, byte offset 12, src IP[0:15] */
33-
CFG_UDF_EOL2 | 6,
34-
/* End of L2, byte offset 14, src IP[16:31] */
35-
CFG_UDF_EOL2 | 7,
36-
/* End of L2, byte offset 16, dst IP[0:15] */
37-
CFG_UDF_EOL2 | 8,
38-
/* End of L2, byte offset 18, dst IP[16:31] */
39-
CFG_UDF_EOL2 | 9,
40-
/* End of L3, byte offset 0, src port */
41-
CFG_UDF_EOL3 | 0,
42-
/* End of L3, byte offset 2, dst port */
43-
CFG_UDF_EOL3 | 1,
44-
0, 0, 0
37+
.udfs = {
38+
[1] = {
39+
.slices = {
40+
/* End of L2, byte offset 12, src IP[0:15] */
41+
CFG_UDF_EOL2 | 6,
42+
/* End of L2, byte offset 14, src IP[16:31] */
43+
CFG_UDF_EOL2 | 7,
44+
/* End of L2, byte offset 16, dst IP[0:15] */
45+
CFG_UDF_EOL2 | 8,
46+
/* End of L2, byte offset 18, dst IP[16:31] */
47+
CFG_UDF_EOL2 | 9,
48+
/* End of L3, byte offset 0, src port */
49+
CFG_UDF_EOL3 | 0,
50+
/* End of L3, byte offset 2, dst port */
51+
CFG_UDF_EOL3 | 1,
52+
0, 0, 0
53+
},
54+
.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
55+
.base_offset = CORE_UDF_0_A_0_8_PORT_0 + UDF_SLICE_OFFSET,
56+
},
4557
},
46-
.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
4758
};
4859

4960
static inline unsigned int bcm_sf2_get_num_udf_slices(const u8 *layout)
5061
{
5162
unsigned int i, count = 0;
5263

53-
for (i = 0; i < UDF_NUM_SLICES; i++) {
64+
for (i = 0; i < UDFS_PER_SLICE; i++) {
5465
if (layout[i] != 0)
5566
count++;
5667
}
5768

5869
return count;
5970
}
6071

72+
static inline u32 udf_upper_bits(unsigned int num_udf)
73+
{
74+
return GENMASK(num_udf - 1, 0) >> (UDFS_PER_SLICE - 1);
75+
}
76+
77+
static inline u32 udf_lower_bits(unsigned int num_udf)
78+
{
79+
return (u8)GENMASK(num_udf - 1, 0);
80+
}
81+
82+
static unsigned int bcm_sf2_get_slice_number(const struct cfp_udf_layout *l,
83+
unsigned int start)
84+
{
85+
const struct cfp_udf_slice_layout *slice_layout;
86+
unsigned int slice_idx;
87+
88+
for (slice_idx = start; slice_idx < UDF_NUM_SLICES; slice_idx++) {
89+
slice_layout = &l->udfs[slice_idx];
90+
if (memcmp(slice_layout->slices, zero_slice,
91+
sizeof(zero_slice)))
92+
break;
93+
}
94+
95+
return slice_idx;
96+
}
97+
6198
static void bcm_sf2_cfp_udf_set(struct bcm_sf2_priv *priv,
62-
unsigned int slice_num,
63-
const u8 *layout)
99+
const struct cfp_udf_layout *layout,
100+
unsigned int slice_num)
64101
{
65-
u32 offset = CORE_UDF_0_A_0_8_PORT_0 + slice_num * UDF_SLICE_OFFSET;
102+
u32 offset = layout->udfs[slice_num].base_offset;
66103
unsigned int i;
67104

68-
for (i = 0; i < UDF_NUM_SLICES; i++)
69-
core_writel(priv, layout[i], offset + i * 4);
105+
for (i = 0; i < UDFS_PER_SLICE; i++)
106+
core_writel(priv, layout->udfs[slice_num].slices[i],
107+
offset + i * 4);
70108
}
71109

72110
static int bcm_sf2_cfp_op(struct bcm_sf2_priv *priv, unsigned int op)
@@ -189,13 +227,16 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
189227
else
190228
rule_index = fs->location;
191229

192-
/* We only use one UDF slice for now */
193-
slice_num = 1;
194230
layout = &udf_tcpip4_layout;
195-
num_udf = bcm_sf2_get_num_udf_slices(layout->slices);
231+
/* We only use one UDF slice for now */
232+
slice_num = bcm_sf2_get_slice_number(layout, 0);
233+
if (slice_num == UDF_NUM_SLICES)
234+
return -EINVAL;
235+
236+
num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
196237

197238
/* Apply the UDF layout for this filter */
198-
bcm_sf2_cfp_udf_set(priv, slice_num, layout->slices);
239+
bcm_sf2_cfp_udf_set(priv, layout, slice_num);
199240

200241
/* Apply to all packets received through this port */
201242
core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7));
@@ -218,14 +259,15 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
218259
* UDF_Valid[8] [0]
219260
*/
220261
core_writel(priv, v4_spec->tos << IPTOS_SHIFT |
221-
ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT,
262+
ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
263+
udf_upper_bits(num_udf),
222264
CORE_CFP_DATA_PORT(6));
223265

224266
/* UDF_Valid[7:0] [31:24]
225267
* S-Tag [23:8]
226268
* C-Tag [7:0]
227269
*/
228-
core_writel(priv, GENMASK(num_udf - 1, 0) << 24, CORE_CFP_DATA_PORT(5));
270+
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_DATA_PORT(5));
229271

230272
/* C-Tag [31:24]
231273
* UDF_n_A8 [23:8]
@@ -270,10 +312,11 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
270312
core_writel(priv, reg, CORE_CFP_DATA_PORT(0));
271313

272314
/* Mask with the specific layout for IPv4 packets */
273-
core_writel(priv, layout->mask_value, CORE_CFP_MASK_PORT(6));
315+
core_writel(priv, layout->udfs[slice_num].mask_value |
316+
udf_upper_bits(num_udf), CORE_CFP_MASK_PORT(6));
274317

275318
/* Mask all but valid UDFs */
276-
core_writel(priv, GENMASK(num_udf - 1, 0) << 24, CORE_CFP_MASK_PORT(5));
319+
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
277320

278321
/* Mask all */
279322
core_writel(priv, 0, CORE_CFP_MASK_PORT(4));

drivers/net/dsa/bcm_sf2_regs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ enum bcm_sf2_reg_offs {
409409
#define CFG_UDF_EOL3 (3 << CFG_UDF_OFFSET_BASE_SHIFT)
410410

411411
/* Number of slices for IPv4, IPv6 and non-IP */
412-
#define UDF_NUM_SLICES 9
412+
#define UDF_NUM_SLICES 4
413+
#define UDFS_PER_SLICE 9
413414

414415
/* Spacing between different slices */
415416
#define UDF_SLICE_OFFSET 0x40

0 commit comments

Comments
 (0)