Commit 8404f6f2 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

mlxsw: pci: Allow to use CQEs of version 1 and version 2

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: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b76550bb
...@@ -662,6 +662,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1); ...@@ -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); 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 /* cmd_mbox_config_profile_max_vepa_channels
* Maximum number of VEPA channels per port (0 through 16) * Maximum number of VEPA channels per port (0 through 16)
* 0 - multi-channel VEPA is disabled * 0 - multi-channel VEPA is disabled
...@@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type, ...@@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type,
MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties, MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties,
0x60, 0, 8, 0x08, 0x00, false); 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 /* ACCESS_REG - Access EMAD Supported Register
* ---------------------------------- * ----------------------------------
* OpMod == 0 (N/A), INMmod == 0 (N/A) * OpMod == 0 (N/A), INMmod == 0 (N/A)
...@@ -1032,11 +1046,15 @@ static inline int mlxsw_cmd_sw2hw_cq(struct mlxsw_core *mlxsw_core, ...@@ -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); 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. * 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 /* cmd_mbox_sw2hw_cq_c_eqn
* Event Queue this CQ reports completion events to. * Event Queue this CQ reports completion events to.
......
...@@ -156,6 +156,8 @@ struct mlxsw_pci { ...@@ -156,6 +156,8 @@ struct mlxsw_pci {
} cmd; } cmd;
struct mlxsw_bus_info bus_info; struct mlxsw_bus_info bus_info;
const struct pci_device_id *id; 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) 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, ...@@ -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, static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
struct mlxsw_pci_queue *q) struct mlxsw_pci_queue *q)
{ {
...@@ -491,7 +504,13 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, ...@@ -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_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_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM);
mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0); mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0);
mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count)); 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) ...@@ -643,6 +662,18 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
} }
} }
static u16 mlxsw_pci_cq_elem_count(const 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(const 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, static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
struct mlxsw_pci_queue *q) struct mlxsw_pci_queue *q)
{ {
...@@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) ...@@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data)
struct mlxsw_pci_queue_ops { struct mlxsw_pci_queue_ops {
const char *name; const char *name;
enum mlxsw_pci_queue_type type; 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, int (*init)(struct mlxsw_pci *mlxsw_pci, char *mbox,
struct mlxsw_pci_queue *q); struct mlxsw_pci_queue *q);
void (*fini)(struct mlxsw_pci *mlxsw_pci, void (*fini)(struct mlxsw_pci *mlxsw_pci,
struct mlxsw_pci_queue *q); struct mlxsw_pci_queue *q);
void (*tasklet)(unsigned long data); void (*tasklet)(unsigned long data);
u16 (*elem_count_f)(const struct mlxsw_pci_queue *q);
u8 (*elem_size_f)(const struct mlxsw_pci_queue *q);
u16 elem_count; u16 elem_count;
u8 elem_size; u8 elem_size;
}; };
...@@ -782,11 +817,12 @@ static const struct mlxsw_pci_queue_ops mlxsw_pci_rdq_ops = { ...@@ -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 = { static const struct mlxsw_pci_queue_ops mlxsw_pci_cq_ops = {
.type = MLXSW_PCI_QUEUE_TYPE_CQ, .type = MLXSW_PCI_QUEUE_TYPE_CQ,
.pre_init = mlxsw_pci_cq_pre_init,
.init = mlxsw_pci_cq_init, .init = mlxsw_pci_cq_init,
.fini = mlxsw_pci_cq_fini, .fini = mlxsw_pci_cq_fini,
.tasklet = mlxsw_pci_cq_tasklet, .tasklet = mlxsw_pci_cq_tasklet,
.elem_count = MLXSW_PCI_CQE01_COUNT, .elem_count_f = mlxsw_pci_cq_elem_count,
.elem_size = MLXSW_PCI_CQE01_SIZE .elem_size_f = mlxsw_pci_cq_elem_size
}; };
static const struct mlxsw_pci_queue_ops mlxsw_pci_eq_ops = { 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, ...@@ -806,12 +842,15 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
int i; int i;
int err; 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); spin_lock_init(&q->lock);
q->num = q_num; q->count = q_ops->elem_count_f ? q_ops->elem_count_f(q) :
q->count = q_ops->elem_count; q_ops->elem_count;
q->elem_size = q_ops->elem_size; q->elem_size = q_ops->elem_size_f ? q_ops->elem_size_f(q) :
q_ops->elem_size;
q->type = q_ops->type; q->type = q_ops->type;
q->pci = mlxsw_pci; q->pci = mlxsw_pci;
...@@ -840,7 +879,7 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox, ...@@ -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 = mlxsw_pci_queue_elem_info_get(q, i);
elem_info->elem = 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); mlxsw_cmd_mbox_zero(mbox);
...@@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) ...@@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox)
return -EINVAL; return -EINVAL;
} }
mlxsw_pci->num_sdq_cqs = num_sdqs;
err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops, err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops,
num_eqs); num_eqs);
if (err) { if (err) {
...@@ -1192,6 +1233,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, ...@@ -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, mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i,
&profile->swid_config[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); 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, ...@@ -1386,6 +1432,21 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
if (err) if (err)
goto err_query_resources; 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); err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res);
if (err) if (err)
goto err_config_profile; goto err_config_profile;
...@@ -1408,6 +1469,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ...@@ -1408,6 +1469,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
mlxsw_pci_aqs_fini(mlxsw_pci); mlxsw_pci_aqs_fini(mlxsw_pci);
err_aqs_init: err_aqs_init:
err_config_profile: err_config_profile:
err_cqe_v_check:
err_query_resources: err_query_resources:
err_boardinfo: err_boardinfo:
mlxsw_pci_fw_area_fini(mlxsw_pci); mlxsw_pci_fw_area_fini(mlxsw_pci);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment