Message ID | 20180426082818.2671-4-jiri@resnulli.us (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Ido Schimmel |
Headers | show |
On Thu, Apr 26, 2018 at 10:28:17AM +0200, Jiri Pirko wrote: > From: Jiri Pirko <jiri@mellanox.com> > > Use previously added resources to query FW support for multiple versions > of CQEs. Use the biggest version supported. For SDQs, it has no sense to > use version 2 as it does not introduce any new features, but it is > twice the size of CQE version 1. > > Signed-off-by: Jiri Pirko <jiri@mellanox.com> > --- > drivers/net/ethernet/mellanox/mlxsw/cmd.h | 24 ++++++++-- > drivers/net/ethernet/mellanox/mlxsw/pci.c | 78 +++++++++++++++++++++++++++---- > 2 files changed, 91 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h > index 479511cf79bc..669226b0759c 100644 > --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h > +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h > @@ -662,6 +662,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1); > */ > MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1); > > +/* cmd_mbox_config_set_cqe_version > + * Capability bit. Setting a bit to 1 configures the profile > + * according to the mailbox contents. > + */ > +MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1); > + > /* cmd_mbox_config_profile_max_vepa_channels > * Maximum number of VEPA channels per port (0 through 16) > * 0 - multi-channel VEPA is disabled > @@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type, > MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties, > 0x60, 0, 8, 0x08, 0x00, false); > > +/* cmd_mbox_config_profile_cqe_version > + * CQE version: > + * 0: CQE version is 0 > + * 1: CQE version is either 1 or 2 > + * CQE ver 1 or 2 is configured by Completion Queue Context field cqe_ver. > + */ > +MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8); It's correct, but I wonder why it's 8 bits in PRM :) > + > /* ACCESS_REG - Access EMAD Supported Register > * ---------------------------------- > * OpMod == 0 (N/A), INMmod == 0 (N/A) > @@ -1032,11 +1046,15 @@ static inline int mlxsw_cmd_sw2hw_cq(struct mlxsw_core *mlxsw_core, > 0, cq_number, in_mbox, MLXSW_CMD_MBOX_SIZE); > } > > -/* cmd_mbox_sw2hw_cq_cv > +enum mlxsw_cmd_mbox_sw2hw_cq_cqe_ver { > + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1, > + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2, > +}; > + > +/* cmd_mbox_sw2hw_cq_cqe_ver > * CQE Version. > - * 0 - CQE Version 0, 1 - CQE Version 1 > */ > -MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cv, 0x00, 28, 4); > +MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cqe_ver, 0x00, 28, 4); Very weird API... v0 vs. v1/v2 is set in config_profile and v1 vs. v2 is set in queue context. > > /* cmd_mbox_sw2hw_cq_c_eqn > * Event Queue this CQ reports completion events to. > diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c > index 99196dbafef2..7308be317032 100644 > --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c > +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c > @@ -156,6 +156,8 @@ struct mlxsw_pci { > } cmd; > struct mlxsw_bus_info bus_info; > const struct pci_device_id *id; > + enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */ > + u8 num_sdq_cqs; /* Number of CQs used for SDQs */ > }; > > static void mlxsw_pci_queue_tasklet_schedule(struct mlxsw_pci_queue *q) > @@ -477,6 +479,17 @@ static void mlxsw_pci_rdq_fini(struct mlxsw_pci *mlxsw_pci, > } > } > > +static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci, > + struct mlxsw_pci_queue *q) > +{ > + q->u.cq.v = mlxsw_pci->max_cqe_ver; > + > + /* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */ > + if (q->u.cq.v == MLXSW_PCI_CQE_V2 && > + q->num < mlxsw_pci->num_sdq_cqs) > + q->u.cq.v = MLXSW_PCI_CQE_V1; > +} > + > static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, > struct mlxsw_pci_queue *q) > { > @@ -491,7 +504,13 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, > mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1); > } > > - mlxsw_cmd_mbox_sw2hw_cq_cv_set(mbox, 0); /* CQE ver 0 */ > + if (q->u.cq.v == MLXSW_PCI_CQE_V1) > + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, > + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1); > + else if (q->u.cq.v == MLXSW_PCI_CQE_V2) > + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, > + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2); > + > mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM); > mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0); > mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count)); > @@ -643,6 +662,18 @@ static void mlxsw_pci_cq_tasklet(unsigned long data) > } > } > > +static u16 mlxsw_pci_cq_elem_count(struct mlxsw_pci_queue *q) const > +{ > + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_COUNT : > + MLXSW_PCI_CQE01_COUNT; > +} > + > +static u8 mlxsw_pci_cq_elem_size(struct mlxsw_pci_queue *q) const > +{ > + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_SIZE : > + MLXSW_PCI_CQE01_SIZE; > +} > + > static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, > struct mlxsw_pci_queue *q) > { > @@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) > struct mlxsw_pci_queue_ops { > const char *name; > enum mlxsw_pci_queue_type type; > + void (*pre_init)(struct mlxsw_pci *mlxsw_pci, > + struct mlxsw_pci_queue *q); > int (*init)(struct mlxsw_pci *mlxsw_pci, char *mbox, > struct mlxsw_pci_queue *q); > void (*fini)(struct mlxsw_pci *mlxsw_pci, > struct mlxsw_pci_queue *q); > void (*tasklet)(unsigned long data); > + u16 (*elem_count_f)(struct mlxsw_pci_queue *q); > + u8 (*elem_size_f)(struct mlxsw_pci_queue *q); > u16 elem_count; > u8 elem_size; > }; > @@ -782,11 +817,12 @@ static const struct mlxsw_pci_queue_ops mlxsw_pci_rdq_ops = { > > static const struct mlxsw_pci_queue_ops mlxsw_pci_cq_ops = { > .type = MLXSW_PCI_QUEUE_TYPE_CQ, > + .pre_init = mlxsw_pci_cq_pre_init, > .init = mlxsw_pci_cq_init, > .fini = mlxsw_pci_cq_fini, > .tasklet = mlxsw_pci_cq_tasklet, > - .elem_count = MLXSW_PCI_CQE01_COUNT, > - .elem_size = MLXSW_PCI_CQE01_SIZE > + .elem_count_f = mlxsw_pci_cq_elem_count, > + .elem_size_f = mlxsw_pci_cq_elem_size > }; > > static const struct mlxsw_pci_queue_ops mlxsw_pci_eq_ops = { > @@ -806,12 +842,15 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, > int i; > int err; > > - q->u.cq.v = MLXSW_PCI_CQE_V0; > + q->num = q_num; > + if (q_ops->pre_init) > + q_ops->pre_init(mlxsw_pci, q); > > spin_lock_init(&q->lock); > - q->num = q_num; > - q->count = q_ops->elem_count; > - q->elem_size = q_ops->elem_size; > + q->count = q_ops->elem_count_f ? q_ops->elem_count_f(q) : > + q_ops->elem_count; > + q->elem_size = q_ops->elem_size_f ? q_ops->elem_size_f(q) : > + q_ops->elem_size; > q->type = q_ops->type; > q->pci = mlxsw_pci; > > @@ -840,7 +879,7 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, > > elem_info = mlxsw_pci_queue_elem_info_get(q, i); > elem_info->elem = > - __mlxsw_pci_queue_elem_get(q, q_ops->elem_size, i); > + __mlxsw_pci_queue_elem_get(q, q->elem_size, i); > } > > mlxsw_cmd_mbox_zero(mbox); > @@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) > return -EINVAL; > } > > + mlxsw_pci->num_sdq_cqs = num_sdqs; > + > err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops, > num_eqs); > if (err) { > @@ -1192,6 +1233,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, > mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i, > &profile->swid_config[i]); > > + if (mlxsw_pci->max_cqe_ver > MLXSW_PCI_CQE_V0) { > + mlxsw_cmd_mbox_config_profile_set_cqe_version_set(mbox, 1); > + mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1); > + } > + > return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); > } > > @@ -1386,6 +1432,21 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, > if (err) > goto err_query_resources; > > + if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V2) && > + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V2)) > + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V2; > + else if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V1) && > + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V1)) > + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V1; > + else if ((MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0) && > + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V0)) || > + !MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0)) { This is for SwitchX-2, right? > + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V0; > + } else { > + dev_err(&pdev->dev, "Invalid supported CQE version combination reported\n"); > + goto err_cqe_v_check; > + } > + > err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res); > if (err) > goto err_config_profile; > @@ -1408,6 +1469,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, > mlxsw_pci_aqs_fini(mlxsw_pci); > err_aqs_init: > err_config_profile: > +err_cqe_v_check: > err_query_resources: > err_boardinfo: > mlxsw_pci_fw_area_fini(mlxsw_pci); > -- > 2.14.3 >
Mon, Apr 30, 2018 at 01:24:17PM CEST, idosch@mellanox.com wrote: >On Thu, Apr 26, 2018 at 10:28:17AM +0200, Jiri Pirko wrote: >> From: Jiri Pirko <jiri@mellanox.com> >> >> Use previously added resources to query FW support for multiple versions >> of CQEs. Use the biggest version supported. For SDQs, it has no sense to >> use version 2 as it does not introduce any new features, but it is >> twice the size of CQE version 1. >> >> Signed-off-by: Jiri Pirko <jiri@mellanox.com> >> --- >> drivers/net/ethernet/mellanox/mlxsw/cmd.h | 24 ++++++++-- >> drivers/net/ethernet/mellanox/mlxsw/pci.c | 78 +++++++++++++++++++++++++++---- >> 2 files changed, 91 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h >> index 479511cf79bc..669226b0759c 100644 >> --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h >> +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h >> @@ -662,6 +662,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1); >> */ >> MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1); >> >> +/* cmd_mbox_config_set_cqe_version >> + * Capability bit. Setting a bit to 1 configures the profile >> + * according to the mailbox contents. >> + */ >> +MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1); >> + >> /* cmd_mbox_config_profile_max_vepa_channels >> * Maximum number of VEPA channels per port (0 through 16) >> * 0 - multi-channel VEPA is disabled >> @@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type, >> MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties, >> 0x60, 0, 8, 0x08, 0x00, false); >> >> +/* cmd_mbox_config_profile_cqe_version >> + * CQE version: >> + * 0: CQE version is 0 >> + * 1: CQE version is either 1 or 2 >> + * CQE ver 1 or 2 is configured by Completion Queue Context field cqe_ver. >> + */ >> +MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8); > >It's correct, but I wonder why it's 8 bits in PRM :) Yeah > >> + >> /* ACCESS_REG - Access EMAD Supported Register >> * ---------------------------------- >> * OpMod == 0 (N/A), INMmod == 0 (N/A) >> @@ -1032,11 +1046,15 @@ static inline int mlxsw_cmd_sw2hw_cq(struct mlxsw_core *mlxsw_core, >> 0, cq_number, in_mbox, MLXSW_CMD_MBOX_SIZE); >> } >> >> -/* cmd_mbox_sw2hw_cq_cv >> +enum mlxsw_cmd_mbox_sw2hw_cq_cqe_ver { >> + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1, >> + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2, >> +}; >> + >> +/* cmd_mbox_sw2hw_cq_cqe_ver >> * CQE Version. >> - * 0 - CQE Version 0, 1 - CQE Version 1 >> */ >> -MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cv, 0x00, 28, 4); >> +MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cqe_ver, 0x00, 28, 4); > >Very weird API... v0 vs. v1/v2 is set in config_profile and v1 vs. v2 is >set in queue context. Indeed :) > >> >> /* cmd_mbox_sw2hw_cq_c_eqn >> * Event Queue this CQ reports completion events to. >> diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c >> index 99196dbafef2..7308be317032 100644 >> --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c >> +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c >> @@ -156,6 +156,8 @@ struct mlxsw_pci { >> } cmd; >> struct mlxsw_bus_info bus_info; >> const struct pci_device_id *id; >> + enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */ >> + u8 num_sdq_cqs; /* Number of CQs used for SDQs */ >> }; >> >> static void mlxsw_pci_queue_tasklet_schedule(struct mlxsw_pci_queue *q) >> @@ -477,6 +479,17 @@ static void mlxsw_pci_rdq_fini(struct mlxsw_pci *mlxsw_pci, >> } >> } >> >> +static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci, >> + struct mlxsw_pci_queue *q) >> +{ >> + q->u.cq.v = mlxsw_pci->max_cqe_ver; >> + >> + /* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */ >> + if (q->u.cq.v == MLXSW_PCI_CQE_V2 && >> + q->num < mlxsw_pci->num_sdq_cqs) >> + q->u.cq.v = MLXSW_PCI_CQE_V1; >> +} >> + >> static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, >> struct mlxsw_pci_queue *q) >> { >> @@ -491,7 +504,13 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, >> mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1); >> } >> >> - mlxsw_cmd_mbox_sw2hw_cq_cv_set(mbox, 0); /* CQE ver 0 */ >> + if (q->u.cq.v == MLXSW_PCI_CQE_V1) >> + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, >> + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1); >> + else if (q->u.cq.v == MLXSW_PCI_CQE_V2) >> + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, >> + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2); >> + >> mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM); >> mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0); >> mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count)); >> @@ -643,6 +662,18 @@ static void mlxsw_pci_cq_tasklet(unsigned long data) >> } >> } >> >> +static u16 mlxsw_pci_cq_elem_count(struct mlxsw_pci_queue *q) > >const > >> +{ >> + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_COUNT : >> + MLXSW_PCI_CQE01_COUNT; >> +} >> + >> +static u8 mlxsw_pci_cq_elem_size(struct mlxsw_pci_queue *q) > >const Both fixed > >> +{ >> + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_SIZE : >> + MLXSW_PCI_CQE01_SIZE; >> +} >> + >> static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, >> struct mlxsw_pci_queue *q) >> { >> @@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) >> struct mlxsw_pci_queue_ops { >> const char *name; >> enum mlxsw_pci_queue_type type; >> + void (*pre_init)(struct mlxsw_pci *mlxsw_pci, >> + struct mlxsw_pci_queue *q); >> int (*init)(struct mlxsw_pci *mlxsw_pci, char *mbox, >> struct mlxsw_pci_queue *q); >> void (*fini)(struct mlxsw_pci *mlxsw_pci, >> struct mlxsw_pci_queue *q); >> void (*tasklet)(unsigned long data); >> + u16 (*elem_count_f)(struct mlxsw_pci_queue *q); >> + u8 (*elem_size_f)(struct mlxsw_pci_queue *q); >> u16 elem_count; >> u8 elem_size; >> }; >> @@ -782,11 +817,12 @@ static const struct mlxsw_pci_queue_ops mlxsw_pci_rdq_ops = { >> >> static const struct mlxsw_pci_queue_ops mlxsw_pci_cq_ops = { >> .type = MLXSW_PCI_QUEUE_TYPE_CQ, >> + .pre_init = mlxsw_pci_cq_pre_init, >> .init = mlxsw_pci_cq_init, >> .fini = mlxsw_pci_cq_fini, >> .tasklet = mlxsw_pci_cq_tasklet, >> - .elem_count = MLXSW_PCI_CQE01_COUNT, >> - .elem_size = MLXSW_PCI_CQE01_SIZE >> + .elem_count_f = mlxsw_pci_cq_elem_count, >> + .elem_size_f = mlxsw_pci_cq_elem_size >> }; >> >> static const struct mlxsw_pci_queue_ops mlxsw_pci_eq_ops = { >> @@ -806,12 +842,15 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, >> int i; >> int err; >> >> - q->u.cq.v = MLXSW_PCI_CQE_V0; >> + q->num = q_num; >> + if (q_ops->pre_init) >> + q_ops->pre_init(mlxsw_pci, q); >> >> spin_lock_init(&q->lock); >> - q->num = q_num; >> - q->count = q_ops->elem_count; >> - q->elem_size = q_ops->elem_size; >> + q->count = q_ops->elem_count_f ? q_ops->elem_count_f(q) : >> + q_ops->elem_count; >> + q->elem_size = q_ops->elem_size_f ? q_ops->elem_size_f(q) : >> + q_ops->elem_size; >> q->type = q_ops->type; >> q->pci = mlxsw_pci; >> >> @@ -840,7 +879,7 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, >> >> elem_info = mlxsw_pci_queue_elem_info_get(q, i); >> elem_info->elem = >> - __mlxsw_pci_queue_elem_get(q, q_ops->elem_size, i); >> + __mlxsw_pci_queue_elem_get(q, q->elem_size, i); >> } >> >> mlxsw_cmd_mbox_zero(mbox); >> @@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) >> return -EINVAL; >> } >> >> + mlxsw_pci->num_sdq_cqs = num_sdqs; >> + >> err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops, >> num_eqs); >> if (err) { >> @@ -1192,6 +1233,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, >> mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i, >> &profile->swid_config[i]); >> >> + if (mlxsw_pci->max_cqe_ver > MLXSW_PCI_CQE_V0) { >> + mlxsw_cmd_mbox_config_profile_set_cqe_version_set(mbox, 1); >> + mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1); >> + } >> + >> return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); >> } >> >> @@ -1386,6 +1432,21 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, >> if (err) >> goto err_query_resources; >> >> + if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V2) && >> + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V2)) >> + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V2; >> + else if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V1) && >> + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V1)) >> + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V1; >> + else if ((MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0) && >> + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V0)) || >> + !MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0)) { > >This is for SwitchX-2, right? Yes. > >> + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V0; >> + } else { >> + dev_err(&pdev->dev, "Invalid supported CQE version combination reported\n"); >> + goto err_cqe_v_check; >> + } >> + >> err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res); >> if (err) >> goto err_config_profile; >> @@ -1408,6 +1469,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, >> mlxsw_pci_aqs_fini(mlxsw_pci); >> err_aqs_init: >> err_config_profile: >> +err_cqe_v_check: >> err_query_resources: >> err_boardinfo: >> mlxsw_pci_fw_area_fini(mlxsw_pci); >> -- >> 2.14.3 >>
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 479511cf79bc..669226b0759c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -662,6 +662,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1); */ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1); +/* cmd_mbox_config_set_cqe_version + * Capability bit. Setting a bit to 1 configures the profile + * according to the mailbox contents. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1); + /* cmd_mbox_config_profile_max_vepa_channels * Maximum number of VEPA channels per port (0 through 16) * 0 - multi-channel VEPA is disabled @@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type, MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties, 0x60, 0, 8, 0x08, 0x00, false); +/* cmd_mbox_config_profile_cqe_version + * CQE version: + * 0: CQE version is 0 + * 1: CQE version is either 1 or 2 + * CQE ver 1 or 2 is configured by Completion Queue Context field cqe_ver. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8); + /* ACCESS_REG - Access EMAD Supported Register * ---------------------------------- * OpMod == 0 (N/A), INMmod == 0 (N/A) @@ -1032,11 +1046,15 @@ static inline int mlxsw_cmd_sw2hw_cq(struct mlxsw_core *mlxsw_core, 0, cq_number, in_mbox, MLXSW_CMD_MBOX_SIZE); } -/* cmd_mbox_sw2hw_cq_cv +enum mlxsw_cmd_mbox_sw2hw_cq_cqe_ver { + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1, + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2, +}; + +/* cmd_mbox_sw2hw_cq_cqe_ver * CQE Version. - * 0 - CQE Version 0, 1 - CQE Version 1 */ -MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cv, 0x00, 28, 4); +MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cqe_ver, 0x00, 28, 4); /* cmd_mbox_sw2hw_cq_c_eqn * Event Queue this CQ reports completion events to. diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 99196dbafef2..7308be317032 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -156,6 +156,8 @@ struct mlxsw_pci { } cmd; struct mlxsw_bus_info bus_info; const struct pci_device_id *id; + enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */ + u8 num_sdq_cqs; /* Number of CQs used for SDQs */ }; static void mlxsw_pci_queue_tasklet_schedule(struct mlxsw_pci_queue *q) @@ -477,6 +479,17 @@ static void mlxsw_pci_rdq_fini(struct mlxsw_pci *mlxsw_pci, } } +static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci, + struct mlxsw_pci_queue *q) +{ + q->u.cq.v = mlxsw_pci->max_cqe_ver; + + /* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */ + if (q->u.cq.v == MLXSW_PCI_CQE_V2 && + q->num < mlxsw_pci->num_sdq_cqs) + q->u.cq.v = MLXSW_PCI_CQE_V1; +} + static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { @@ -491,7 +504,13 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1); } - mlxsw_cmd_mbox_sw2hw_cq_cv_set(mbox, 0); /* CQE ver 0 */ + if (q->u.cq.v == MLXSW_PCI_CQE_V1) + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1); + else if (q->u.cq.v == MLXSW_PCI_CQE_V2) + mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, + MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2); + mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM); mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0); mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count)); @@ -643,6 +662,18 @@ static void mlxsw_pci_cq_tasklet(unsigned long data) } } +static u16 mlxsw_pci_cq_elem_count(struct mlxsw_pci_queue *q) +{ + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_COUNT : + MLXSW_PCI_CQE01_COUNT; +} + +static u8 mlxsw_pci_cq_elem_size(struct mlxsw_pci_queue *q) +{ + return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_SIZE : + MLXSW_PCI_CQE01_SIZE; +} + static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { @@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) struct mlxsw_pci_queue_ops { const char *name; enum mlxsw_pci_queue_type type; + void (*pre_init)(struct mlxsw_pci *mlxsw_pci, + struct mlxsw_pci_queue *q); int (*init)(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q); void (*fini)(struct mlxsw_pci *mlxsw_pci, struct mlxsw_pci_queue *q); void (*tasklet)(unsigned long data); + u16 (*elem_count_f)(struct mlxsw_pci_queue *q); + u8 (*elem_size_f)(struct mlxsw_pci_queue *q); u16 elem_count; u8 elem_size; }; @@ -782,11 +817,12 @@ static const struct mlxsw_pci_queue_ops mlxsw_pci_rdq_ops = { static const struct mlxsw_pci_queue_ops mlxsw_pci_cq_ops = { .type = MLXSW_PCI_QUEUE_TYPE_CQ, + .pre_init = mlxsw_pci_cq_pre_init, .init = mlxsw_pci_cq_init, .fini = mlxsw_pci_cq_fini, .tasklet = mlxsw_pci_cq_tasklet, - .elem_count = MLXSW_PCI_CQE01_COUNT, - .elem_size = MLXSW_PCI_CQE01_SIZE + .elem_count_f = mlxsw_pci_cq_elem_count, + .elem_size_f = mlxsw_pci_cq_elem_size }; static const struct mlxsw_pci_queue_ops mlxsw_pci_eq_ops = { @@ -806,12 +842,15 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, int i; int err; - q->u.cq.v = MLXSW_PCI_CQE_V0; + q->num = q_num; + if (q_ops->pre_init) + q_ops->pre_init(mlxsw_pci, q); spin_lock_init(&q->lock); - q->num = q_num; - q->count = q_ops->elem_count; - q->elem_size = q_ops->elem_size; + q->count = q_ops->elem_count_f ? q_ops->elem_count_f(q) : + q_ops->elem_count; + q->elem_size = q_ops->elem_size_f ? q_ops->elem_size_f(q) : + q_ops->elem_size; q->type = q_ops->type; q->pci = mlxsw_pci; @@ -840,7 +879,7 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, elem_info = mlxsw_pci_queue_elem_info_get(q, i); elem_info->elem = - __mlxsw_pci_queue_elem_get(q, q_ops->elem_size, i); + __mlxsw_pci_queue_elem_get(q, q->elem_size, i); } mlxsw_cmd_mbox_zero(mbox); @@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) return -EINVAL; } + mlxsw_pci->num_sdq_cqs = num_sdqs; + err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops, num_eqs); if (err) { @@ -1192,6 +1233,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i, &profile->swid_config[i]); + if (mlxsw_pci->max_cqe_ver > MLXSW_PCI_CQE_V0) { + mlxsw_cmd_mbox_config_profile_set_cqe_version_set(mbox, 1); + mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1); + } + return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); } @@ -1386,6 +1432,21 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, if (err) goto err_query_resources; + if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V2) && + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V2)) + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V2; + else if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V1) && + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V1)) + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V1; + else if ((MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0) && + MLXSW_CORE_RES_GET(mlxsw_core, CQE_V0)) || + !MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0)) { + mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V0; + } else { + dev_err(&pdev->dev, "Invalid supported CQE version combination reported\n"); + goto err_cqe_v_check; + } + err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res); if (err) goto err_config_profile; @@ -1408,6 +1469,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, mlxsw_pci_aqs_fini(mlxsw_pci); err_aqs_init: err_config_profile: +err_cqe_v_check: err_query_resources: err_boardinfo: mlxsw_pci_fw_area_fini(mlxsw_pci);