Message ID | 20250108-qcom_ipq_ppe-v2-4-7394dbda7199@quicinc.com |
---|---|
State | New |
Headers | show |
Series | Add PPE driver for Qualcomm IPQ9574 SoC | expand |
On Wed, Jan 08, 2025 at 09:47:11PM +0800, Luo Jie wrote: > The BM (Buffer Management) config controls the pause frame generated > on the PPE port. There are maximum 15 BM ports and 4 groups supported, > all BM ports are assigned to group 0 by default. The number of hardware > buffers configured for the port influence the threshold of the flow > control for that port. > > Signed-off-by: Luo Jie <quic_luoj@quicinc.com> ... > diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c ... > +/* The buffer configurations per PPE port. There are 15 BM ports and > + * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, > + * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for > + * EIP port. > + */ > +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { > + { > + /* Buffer configuration for the BM port ID 0 of EDMA. */ > + .port_id_start = 0, > + .port_id_end = 0, > + .pre_alloc = 0, > + .in_fly_buf = 100, > + .ceil = 1146, > + .weight = 7, > + .resume_offset = 8, > + .resume_ceil = 0, > + .dynamic = true, > + }, > + { > + /* Buffer configuration for the BM port ID 1-7 of EDMA. */ > + .port_id_start = 1, > + .port_id_end = 7, > + .pre_alloc = 0, > + .in_fly_buf = 100, > + .ceil = 250, > + .weight = 4, > + .resume_offset = 36, > + .resume_ceil = 0, > + .dynamic = true, > + }, > + { > + /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ > + .port_id_start = 8, > + .port_id_end = 13, > + .pre_alloc = 0, > + .in_fly_buf = 128, > + .ceil = 250, > + .weight = 4, > + .resume_offset = 36, > + .resume_ceil = 0, > + .dynamic = true, > + }, > + { > + /* Buffer configuration for the BM port ID 14 of EIP. */ > + .port_id_start = 14, > + .port_id_end = 14, > + .pre_alloc = 0, > + .in_fly_buf = 40, > + .ceil = 250, > + .weight = 4, > + .resume_offset = 36, > + .resume_ceil = 0, > + .dynamic = true, > + }, > +}; > + > +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, > + struct ppe_bm_port_config port_cfg) > +{ > + u32 reg, val, bm_fc_val[2]; > + int ret; > + > + /* Configure BM flow control related threshold. */ > + PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); Hi Luo Jie, When compiling with W=1 for x86_32 and ARM (32bit) (but, curiously not x86_64 or arm64), gcc-14 complains that bm_fc_val is uninitialised, I believe due to the line above and similar lines below. In file included from drivers/net/ethernet/qualcomm/ppe/ppe_config.c:10: In function 'u32p_replace_bits', inlined from 'ppe_config_bm_threshold' at drivers/net/ethernet/qualcomm/ppe/ppe_config.c:112:2: ./include/linux/bitfield.h:189:15: warning: 'bm_fc_val' is used uninitialized [-Wuninitialized] 189 | *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ | ^~ ./include/linux/bitfield.h:198:9: note: in expansion of macro '____MAKE_OP' 198 | ____MAKE_OP(u##size,u##size,,) | ^~~~~~~~~~~ ./include/linux/bitfield.h:201:1: note: in expansion of macro '__MAKE_OP' 201 | __MAKE_OP(32) | ^~~~~~~~~ drivers/net/ethernet/qualcomm/ppe/ppe_config.c: In function 'ppe_config_bm_threshold': drivers/net/ethernet/qualcomm/ppe/ppe_config.c:108:23: note: 'bm_fc_val' declared here 108 | u32 reg, val, bm_fc_val[2]; | ^~~~~~~~~ > + PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); > + PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); > + PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); > + PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); > + PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); > + > + /* Configure low/high bits of the ceiling for the BM port. */ > + val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); The value of port_cfg.ceil is 250 or 1146, as set in ipq9574_ppe_bm_port_config. clang-19 W=1 builds complain that this value is too large for the field (3 bits). drivers/net/ethernet/qualcomm/ppe/ppe_config.c:120:8: error: call to '__compiletime_assert_925' declared with 'error' attribute: FIELD_PREP: value too large for the field 120 | val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); | ^ ./include/linux/bitfield.h:115:3: note: expanded from macro 'FIELD_PREP' 115 | __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ | ^ ./include/linux/bitfield.h:68:3: note: expanded from macro '__BF_FIELD_CHECK' 68 | BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ | ^ ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^ note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) ././include/linux/compiler_types.h:530:2: note: expanded from macro '_compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^ ././include/linux/compiler_types.h:523:4: note: expanded from macro '__compiletime_assert' 523 | prefix ## suffix(); \ | ^ <scratch space>:95:1: note: expanded from here 95 | __compiletime_assert_925 | ^ 1 error generated > + PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); > + val = FIELD_PREP(GENMASK(10, 3), port_cfg.ceil); > + PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); > + > + reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; > + ret = regmap_bulk_write(ppe_dev->regmap, reg, > + bm_fc_val, ARRAY_SIZE(bm_fc_val)); > + if (ret) > + return ret; > + > + /* Assign the default group ID 0 to the BM port. */ > + val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); > + reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; > + ret = regmap_update_bits(ppe_dev->regmap, reg, > + PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, > + val); > + if (ret) > + return ret; > + > + /* Enable BM port flow control. */ > + val = FIELD_PREP(PPE_BM_PORT_FC_MODE_EN, true); > + reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; > + > + return regmap_update_bits(ppe_dev->regmap, reg, > + PPE_BM_PORT_FC_MODE_EN, > + val); > +} ...
On Thu, Jan 09, 2025 at 05:27:14PM +0000, Simon Horman wrote: > On Wed, Jan 08, 2025 at 09:47:11PM +0800, Luo Jie wrote: > > The BM (Buffer Management) config controls the pause frame generated > > on the PPE port. There are maximum 15 BM ports and 4 groups supported, > > all BM ports are assigned to group 0 by default. The number of hardware > > buffers configured for the port influence the threshold of the flow > > control for that port. > > > > Signed-off-by: Luo Jie <quic_luoj@quicinc.com> > > ... > > > diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c > > ... > > > +/* The buffer configurations per PPE port. There are 15 BM ports and > > + * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, > > + * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for > > + * EIP port. > > + */ > > +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { > > + { > > + /* Buffer configuration for the BM port ID 0 of EDMA. */ > > + .port_id_start = 0, > > + .port_id_end = 0, > > + .pre_alloc = 0, > > + .in_fly_buf = 100, > > + .ceil = 1146, > > + .weight = 7, > > + .resume_offset = 8, > > + .resume_ceil = 0, > > + .dynamic = true, > > + }, > > + { > > + /* Buffer configuration for the BM port ID 1-7 of EDMA. */ > > + .port_id_start = 1, > > + .port_id_end = 7, > > + .pre_alloc = 0, > > + .in_fly_buf = 100, > > + .ceil = 250, > > + .weight = 4, > > + .resume_offset = 36, > > + .resume_ceil = 0, > > + .dynamic = true, > > + }, > > + { > > + /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ > > + .port_id_start = 8, > > + .port_id_end = 13, > > + .pre_alloc = 0, > > + .in_fly_buf = 128, > > + .ceil = 250, > > + .weight = 4, > > + .resume_offset = 36, > > + .resume_ceil = 0, > > + .dynamic = true, > > + }, > > + { > > + /* Buffer configuration for the BM port ID 14 of EIP. */ > > + .port_id_start = 14, > > + .port_id_end = 14, > > + .pre_alloc = 0, > > + .in_fly_buf = 40, > > + .ceil = 250, > > + .weight = 4, > > + .resume_offset = 36, > > + .resume_ceil = 0, > > + .dynamic = true, > > + }, > > +}; > > + > > +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, > > + struct ppe_bm_port_config port_cfg) > > +{ > > + u32 reg, val, bm_fc_val[2]; > > + int ret; > > + > > + /* Configure BM flow control related threshold. */ > > + PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); > > Hi Luo Jie, > > When compiling with W=1 for x86_32 and ARM (32bit) > (but, curiously not x86_64 or arm64), gcc-14 complains that > bm_fc_val is uninitialised, I believe due to the line above and > similar lines below. > > In file included from drivers/net/ethernet/qualcomm/ppe/ppe_config.c:10: > In function 'u32p_replace_bits', > inlined from 'ppe_config_bm_threshold' at drivers/net/ethernet/qualcomm/ppe/ppe_config.c:112:2: > ./include/linux/bitfield.h:189:15: warning: 'bm_fc_val' is used uninitialized [-Wuninitialized] > 189 | *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ > | ^~ > ./include/linux/bitfield.h:198:9: note: in expansion of macro '____MAKE_OP' > 198 | ____MAKE_OP(u##size,u##size,,) > | ^~~~~~~~~~~ > ./include/linux/bitfield.h:201:1: note: in expansion of macro '__MAKE_OP' > 201 | __MAKE_OP(32) > | ^~~~~~~~~ > drivers/net/ethernet/qualcomm/ppe/ppe_config.c: In function 'ppe_config_bm_threshold': > drivers/net/ethernet/qualcomm/ppe/ppe_config.c:108:23: note: 'bm_fc_val' declared here > 108 | u32 reg, val, bm_fc_val[2]; > | ^~~~~~~~~ > > > + PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); > > + PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); > > + PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); > > + PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); > > + PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); > > + > > + /* Configure low/high bits of the ceiling for the BM port. */ > > + val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); > > The value of port_cfg.ceil is 250 or 1146, as set in > ipq9574_ppe_bm_port_config. clang-19 W=1 builds complain that this > value is too large for the field (3 bits). > > drivers/net/ethernet/qualcomm/ppe/ppe_config.c:120:8: error: call to '__compiletime_assert_925' declared with 'error' attribute: FIELD_PREP: value too large for the field > 120 | val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); > | ^ > ./include/linux/bitfield.h:115:3: note: expanded from macro 'FIELD_PREP' > 115 | __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ > | ^ > ./include/linux/bitfield.h:68:3: note: expanded from macro '__BF_FIELD_CHECK' > 68 | BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ > | ^ > ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' > 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) > | ^ > note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) > ././include/linux/compiler_types.h:530:2: note: expanded from macro '_compiletime_assert' > 530 | __compiletime_assert(condition, msg, prefix, suffix) > | ^ > ././include/linux/compiler_types.h:523:4: note: expanded from macro '__compiletime_assert' > 523 | prefix ## suffix(); \ > | ^ > <scratch space>:95:1: note: expanded from here > 95 | __compiletime_assert_925 > | ^ > 1 error generated > > > + PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); > > + val = FIELD_PREP(GENMASK(10, 3), port_cfg.ceil); One more thing - I was pondering this over dinner. I believe that the above will write the bits 0-7 of port_cfg.ceil to bits 3-10 of val. I am guessing that the reverse mapping of bits is intended. > > + PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); > > + > > + reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; > > + ret = regmap_bulk_write(ppe_dev->regmap, reg, > > + bm_fc_val, ARRAY_SIZE(bm_fc_val)); > > + if (ret) > > + return ret; > > + > > + /* Assign the default group ID 0 to the BM port. */ > > + val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); > > + reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; > > + ret = regmap_update_bits(ppe_dev->regmap, reg, > > + PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, > > + val); > > + if (ret) > > + return ret; > > + > > + /* Enable BM port flow control. */ > > + val = FIELD_PREP(PPE_BM_PORT_FC_MODE_EN, true); > > + reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; > > + > > + return regmap_update_bits(ppe_dev->regmap, reg, > > + PPE_BM_PORT_FC_MODE_EN, > > + val); > > +} > > ... > > -- > pw-bot: changes-requested >
On 1/10/2025 4:11 AM, Simon Horman wrote: > On Thu, Jan 09, 2025 at 05:27:14PM +0000, Simon Horman wrote: >> On Wed, Jan 08, 2025 at 09:47:11PM +0800, Luo Jie wrote: >>> The BM (Buffer Management) config controls the pause frame generated >>> on the PPE port. There are maximum 15 BM ports and 4 groups supported, >>> all BM ports are assigned to group 0 by default. The number of hardware >>> buffers configured for the port influence the threshold of the flow >>> control for that port. >>> >>> Signed-off-by: Luo Jie <quic_luoj@quicinc.com> >> >> ... >> >>> diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c >> >> ... >> >>> +/* The buffer configurations per PPE port. There are 15 BM ports and >>> + * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, >>> + * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for >>> + * EIP port. >>> + */ >>> +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { >>> + { >>> + /* Buffer configuration for the BM port ID 0 of EDMA. */ >>> + .port_id_start = 0, >>> + .port_id_end = 0, >>> + .pre_alloc = 0, >>> + .in_fly_buf = 100, >>> + .ceil = 1146, >>> + .weight = 7, >>> + .resume_offset = 8, >>> + .resume_ceil = 0, >>> + .dynamic = true, >>> + }, >>> + { >>> + /* Buffer configuration for the BM port ID 1-7 of EDMA. */ >>> + .port_id_start = 1, >>> + .port_id_end = 7, >>> + .pre_alloc = 0, >>> + .in_fly_buf = 100, >>> + .ceil = 250, >>> + .weight = 4, >>> + .resume_offset = 36, >>> + .resume_ceil = 0, >>> + .dynamic = true, >>> + }, >>> + { >>> + /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ >>> + .port_id_start = 8, >>> + .port_id_end = 13, >>> + .pre_alloc = 0, >>> + .in_fly_buf = 128, >>> + .ceil = 250, >>> + .weight = 4, >>> + .resume_offset = 36, >>> + .resume_ceil = 0, >>> + .dynamic = true, >>> + }, >>> + { >>> + /* Buffer configuration for the BM port ID 14 of EIP. */ >>> + .port_id_start = 14, >>> + .port_id_end = 14, >>> + .pre_alloc = 0, >>> + .in_fly_buf = 40, >>> + .ceil = 250, >>> + .weight = 4, >>> + .resume_offset = 36, >>> + .resume_ceil = 0, >>> + .dynamic = true, >>> + }, >>> +}; >>> + >>> +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, >>> + struct ppe_bm_port_config port_cfg) >>> +{ >>> + u32 reg, val, bm_fc_val[2]; >>> + int ret; >>> + >>> + /* Configure BM flow control related threshold. */ >>> + PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); >> >> Hi Luo Jie, >> >> When compiling with W=1 for x86_32 and ARM (32bit) >> (but, curiously not x86_64 or arm64), gcc-14 complains that >> bm_fc_val is uninitialised, I believe due to the line above and >> similar lines below. >> >> In file included from drivers/net/ethernet/qualcomm/ppe/ppe_config.c:10: >> In function 'u32p_replace_bits', >> inlined from 'ppe_config_bm_threshold' at drivers/net/ethernet/qualcomm/ppe/ppe_config.c:112:2: >> ./include/linux/bitfield.h:189:15: warning: 'bm_fc_val' is used uninitialized [-Wuninitialized] >> 189 | *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ >> | ^~ >> ./include/linux/bitfield.h:198:9: note: in expansion of macro '____MAKE_OP' >> 198 | ____MAKE_OP(u##size,u##size,,) >> | ^~~~~~~~~~~ >> ./include/linux/bitfield.h:201:1: note: in expansion of macro '__MAKE_OP' >> 201 | __MAKE_OP(32) >> | ^~~~~~~~~ >> drivers/net/ethernet/qualcomm/ppe/ppe_config.c: In function 'ppe_config_bm_threshold': >> drivers/net/ethernet/qualcomm/ppe/ppe_config.c:108:23: note: 'bm_fc_val' declared here >> 108 | u32 reg, val, bm_fc_val[2]; >> | ^~~~~~~~~ >> >>> + PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); >>> + PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); >>> + PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); >>> + PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); >>> + PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); >>> + >>> + /* Configure low/high bits of the ceiling for the BM port. */ >>> + val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); >> >> The value of port_cfg.ceil is 250 or 1146, as set in >> ipq9574_ppe_bm_port_config. clang-19 W=1 builds complain that this >> value is too large for the field (3 bits). >> >> drivers/net/ethernet/qualcomm/ppe/ppe_config.c:120:8: error: call to '__compiletime_assert_925' declared with 'error' attribute: FIELD_PREP: value too large for the field >> 120 | val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); >> | ^ >> ./include/linux/bitfield.h:115:3: note: expanded from macro 'FIELD_PREP' >> 115 | __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ >> | ^ >> ./include/linux/bitfield.h:68:3: note: expanded from macro '__BF_FIELD_CHECK' >> 68 | BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ >> | ^ >> ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' >> 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) >> | ^ >> note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) >> ././include/linux/compiler_types.h:530:2: note: expanded from macro '_compiletime_assert' >> 530 | __compiletime_assert(condition, msg, prefix, suffix) >> | ^ >> ././include/linux/compiler_types.h:523:4: note: expanded from macro '__compiletime_assert' >> 523 | prefix ## suffix(); \ >> | ^ >> <scratch space>:95:1: note: expanded from here >> 95 | __compiletime_assert_925 >> | ^ >> 1 error generated >> >>> + PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); >>> + val = FIELD_PREP(GENMASK(10, 3), port_cfg.ceil); > > One more thing - I was pondering this over dinner. > > I believe that the above will write the bits 0-7 of port_cfg.ceil > to bits 3-10 of val. I am guessing that the reverse mapping of > bits is intended. > Thanks for catching this, yes, I will update this code. And also run the 32 bit ARCH check on the patches. >>> + PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); >>> + >>> + reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; >>> + ret = regmap_bulk_write(ppe_dev->regmap, reg, >>> + bm_fc_val, ARRAY_SIZE(bm_fc_val)); >>> + if (ret) >>> + return ret; >>> + >>> + /* Assign the default group ID 0 to the BM port. */ >>> + val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); >>> + reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; >>> + ret = regmap_update_bits(ppe_dev->regmap, reg, >>> + PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, >>> + val); >>> + if (ret) >>> + return ret; >>> + >>> + /* Enable BM port flow control. */ >>> + val = FIELD_PREP(PPE_BM_PORT_FC_MODE_EN, true); >>> + reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; >>> + >>> + return regmap_update_bits(ppe_dev->regmap, reg, >>> + PPE_BM_PORT_FC_MODE_EN, >>> + val); >>> +} >> >> ... >> >> -- >> pw-bot: changes-requested >>
diff --git a/drivers/net/ethernet/qualcomm/ppe/Makefile b/drivers/net/ethernet/qualcomm/ppe/Makefile index 63d50d3b4f2e..410a7bb54cfe 100644 --- a/drivers/net/ethernet/qualcomm/ppe/Makefile +++ b/drivers/net/ethernet/qualcomm/ppe/Makefile @@ -4,4 +4,4 @@ # obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o -qcom-ppe-objs := ppe.o +qcom-ppe-objs := ppe.o ppe_config.o diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c index 4d90fcb8fa43..e8aa4eabaa7f 100644 --- a/drivers/net/ethernet/qualcomm/ppe/ppe.c +++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c @@ -15,6 +15,7 @@ #include <linux/reset.h> #include "ppe.h" +#include "ppe_config.h" #define PPE_PORT_MAX 8 #define PPE_CLK_RATE 353000000 @@ -194,6 +195,10 @@ static int qcom_ppe_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "PPE clock config failed\n"); + ret = ppe_hw_config(ppe_dev); + if (ret) + return dev_err_probe(dev, ret, "PPE HW config failed\n"); + platform_set_drvdata(pdev, ppe_dev); return 0; diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c new file mode 100644 index 000000000000..848f65ef32ea --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/* PPE HW initialization configs such as BM(buffer management), + * QM(queue management) and scheduler configs. + */ + +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/device.h> +#include <linux/regmap.h> + +#include "ppe.h" +#include "ppe_config.h" +#include "ppe_regs.h" + +/** + * struct ppe_bm_port_config - PPE BM port configuration. + * @port_id_start: The fist BM port ID to configure. + * @port_id_end: The last BM port ID to configure. + * @pre_alloc: BM port dedicated buffer number. + * @in_fly_buf: Buffer number for receiving the packet after pause frame sent. + * @ceil: Ceil to generate the back pressure. + * @weight: Weight value. + * @resume_offset: Resume offset from the threshold value. + * @resume_ceil: Ceil to resume from the back pressure state. + * @dynamic: Dynamic threshold used or not. + * + * The is for configuring the threshold that impacts the port + * flow control. + */ +struct ppe_bm_port_config { + unsigned int port_id_start; + unsigned int port_id_end; + unsigned int pre_alloc; + unsigned int in_fly_buf; + unsigned int ceil; + unsigned int weight; + unsigned int resume_offset; + unsigned int resume_ceil; + bool dynamic; +}; + +/* Assign the share buffer number 1550 to group 0 by default. */ +static int ipq9574_ppe_bm_group_config = 1550; + +/* The buffer configurations per PPE port. There are 15 BM ports and + * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, + * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for + * EIP port. + */ +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { + { + /* Buffer configuration for the BM port ID 0 of EDMA. */ + .port_id_start = 0, + .port_id_end = 0, + .pre_alloc = 0, + .in_fly_buf = 100, + .ceil = 1146, + .weight = 7, + .resume_offset = 8, + .resume_ceil = 0, + .dynamic = true, + }, + { + /* Buffer configuration for the BM port ID 1-7 of EDMA. */ + .port_id_start = 1, + .port_id_end = 7, + .pre_alloc = 0, + .in_fly_buf = 100, + .ceil = 250, + .weight = 4, + .resume_offset = 36, + .resume_ceil = 0, + .dynamic = true, + }, + { + /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ + .port_id_start = 8, + .port_id_end = 13, + .pre_alloc = 0, + .in_fly_buf = 128, + .ceil = 250, + .weight = 4, + .resume_offset = 36, + .resume_ceil = 0, + .dynamic = true, + }, + { + /* Buffer configuration for the BM port ID 14 of EIP. */ + .port_id_start = 14, + .port_id_end = 14, + .pre_alloc = 0, + .in_fly_buf = 40, + .ceil = 250, + .weight = 4, + .resume_offset = 36, + .resume_ceil = 0, + .dynamic = true, + }, +}; + +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, + struct ppe_bm_port_config port_cfg) +{ + u32 reg, val, bm_fc_val[2]; + int ret; + + /* Configure BM flow control related threshold. */ + PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); + PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); + PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); + PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); + PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); + PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); + + /* Configure low/high bits of the ceiling for the BM port. */ + val = FIELD_PREP(GENMASK(2, 0), port_cfg.ceil); + PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); + val = FIELD_PREP(GENMASK(10, 3), port_cfg.ceil); + PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); + + reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; + ret = regmap_bulk_write(ppe_dev->regmap, reg, + bm_fc_val, ARRAY_SIZE(bm_fc_val)); + if (ret) + return ret; + + /* Assign the default group ID 0 to the BM port. */ + val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); + reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; + ret = regmap_update_bits(ppe_dev->regmap, reg, + PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, + val); + if (ret) + return ret; + + /* Enable BM port flow control. */ + val = FIELD_PREP(PPE_BM_PORT_FC_MODE_EN, true); + reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; + + return regmap_update_bits(ppe_dev->regmap, reg, + PPE_BM_PORT_FC_MODE_EN, + val); +} + +/* Configure the buffer threshold for the port flow control function. */ +static int ppe_config_bm(struct ppe_device *ppe_dev) +{ + unsigned int i, bm_port_id, port_cfg_cnt; + struct ppe_bm_port_config *port_cfg; + u32 reg, val; + int ret; + + /* Configure the allocated buffer number only for group 0. + * The buffer number of group 1-3 is already cleared to 0 + * after PPE reset during the probe of PPE driver. + */ + reg = PPE_BM_SHARED_GROUP_CFG_ADDR; + val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, + ipq9574_ppe_bm_group_config); + ret = regmap_update_bits(ppe_dev->regmap, reg, + PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, + val); + if (ret) + goto bm_config_fail; + + /* Configure buffer thresholds for the BM ports. */ + port_cfg = ipq9574_ppe_bm_port_config; + port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config); + for (i = 0; i < port_cfg_cnt; i++) { + for (bm_port_id = port_cfg[i].port_id_start; + bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) { + ret = ppe_config_bm_threshold(ppe_dev, bm_port_id, + port_cfg[i]); + if (ret) + goto bm_config_fail; + } + } + + return 0; + +bm_config_fail: + dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret); + return ret; +} + +int ppe_hw_config(struct ppe_device *ppe_dev) +{ + return ppe_config_bm(ppe_dev); +} diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h new file mode 100644 index 000000000000..7b2f6a71cd4c --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __PPE_CONFIG_H__ +#define __PPE_CONFIG_H__ + +#include "ppe.h" + +int ppe_hw_config(struct ppe_device *ppe_dev); +#endif diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h new file mode 100644 index 000000000000..b00f77ec45fe --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/* PPE hardware register and table declarations. */ +#ifndef __PPE_REGS_H__ +#define __PPE_REGS_H__ + +#include <linux/bitfield.h> + +/* There are 15 BM ports and 4 BM groups supported by PPE. + * BM port (0-7) is for EDMA port 0, BM port (8-13) is for + * PPE physical port 1-6 and BM port 14 is for EIP port. + */ +#define PPE_BM_PORT_FC_MODE_ADDR 0x600100 +#define PPE_BM_PORT_FC_MODE_ENTRIES 15 +#define PPE_BM_PORT_FC_MODE_INC 0x4 +#define PPE_BM_PORT_FC_MODE_EN BIT(0) + +#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180 +#define PPE_BM_PORT_GROUP_ID_ENTRIES 15 +#define PPE_BM_PORT_GROUP_ID_INC 0x4 +#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0) + +#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290 +#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4 +#define PPE_BM_SHARED_GROUP_CFG_INC 0x4 +#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0) + +#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000 +#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15 +#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10 +#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0) +#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9) +#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18) +#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29) +#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0) +#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8) +#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11) +#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12) + +#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \ + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_REACT_LIMIT) +#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \ + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_THRESHOLD) +#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \ + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_OFFSET) +#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \ + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_CEILING_LOW) +#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \ + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_CEILING_HIGH) +#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \ + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_WEIGHT) +#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \ + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC) +#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) +#endif
The BM (Buffer Management) config controls the pause frame generated on the PPE port. There are maximum 15 BM ports and 4 groups supported, all BM ports are assigned to group 0 by default. The number of hardware buffers configured for the port influence the threshold of the flow control for that port. Signed-off-by: Luo Jie <quic_luoj@quicinc.com> --- drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 + drivers/net/ethernet/qualcomm/ppe/ppe_config.c | 193 +++++++++++++++++++++++++ drivers/net/ethernet/qualcomm/ppe/ppe_config.h | 12 ++ drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 59 ++++++++ 5 files changed, 270 insertions(+), 1 deletion(-)