|
@@ -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,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+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,
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+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)
|
|
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 = {
|
|
|
|
|
|
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_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 = {
|
|
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 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;
|
|
|
|
- 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->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,
|
|
|
|
|
|
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)
|
|
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,
|
|
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,
|
|
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 @@ err_request_eq_irq:
|
|
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);
|