diff mbox

[net-next,mlxsw,3/4] mlxsw: pci: Allow to use CQEs of version 1 and version 2

Message ID 20180426082818.2671-4-jiri@resnulli.us (mailing list archive)
State Changes Requested
Delegated to: Ido Schimmel
Headers show

Commit Message

Jiri Pirko April 26, 2018, 8:28 a.m. UTC
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(-)

Comments

Ido Schimmel April 30, 2018, 11:24 a.m. UTC | #1
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
>
Jiri Pirko April 30, 2018, 2:05 p.m. UTC | #2
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 mbox

Patch

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);