diff mbox series

[v3,net-next,5/7] octeontx2-af: advertised link modes support on cgx

Message ID 1612157084-101715-6-git-send-email-hkelam@marvell.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series ethtool support for fec and link configuration | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 199 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 17 this patch: 17
netdev/header_inline success Link
netdev/stable success Stable not CCed

Commit Message

Hariprasad Kelam Feb. 1, 2021, 5:24 a.m. UTC
From: Christina Jacob <cjacob@marvell.com>

CGX supports setting advertised link modes on physical link.
This patch adds support to derive cgx mode from ethtool
link mode and pass it to firmware to configure the same.

Signed-off-by: Christina Jacob <cjacob@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
---
 drivers/net/ethernet/marvell/octeontx2/af/cgx.c    | 114 ++++++++++++++++++++-
 .../net/ethernet/marvell/octeontx2/af/cgx_fw_if.h  |  32 +++++-
 drivers/net/ethernet/marvell/octeontx2/af/mbox.h   |   3 +-
 3 files changed, 146 insertions(+), 3 deletions(-)

Comments

Jesse Brandeburg Feb. 3, 2021, 12:45 a.m. UTC | #1
Hariprasad Kelam wrote:

> From: Christina Jacob <cjacob@marvell.com>
> 
> CGX supports setting advertised link modes on physical link.
> This patch adds support to derive cgx mode from ethtool
> link mode and pass it to firmware to configure the same.
> 
> Signed-off-by: Christina Jacob <cjacob@marvell.com>
> Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
> Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>

Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Chris Packham Dec. 1, 2022, 2:02 a.m. UTC | #2
Hi Hariprasad, Christina,

Sorry for poking an old thread but Richard and I were looking at some 
code and noticed something odd about it.

On 1/02/21 18:24, Hariprasad Kelam wrote:
> From: Christina Jacob <cjacob@marvell.com>
>
> CGX supports setting advertised link modes on physical link.
> This patch adds support to derive cgx mode from ethtool
> link mode and pass it to firmware to configure the same.
>
> Signed-off-by: Christina Jacob <cjacob@marvell.com>
> Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
> Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
> ---
>   drivers/net/ethernet/marvell/octeontx2/af/cgx.c    | 114 ++++++++++++++++++++-
>   .../net/ethernet/marvell/octeontx2/af/cgx_fw_if.h  |  32 +++++-
>   drivers/net/ethernet/marvell/octeontx2/af/mbox.h   |   3 +-
>   3 files changed, 146 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> index 5b7d858..9c62129 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> @@ -14,6 +14,7 @@
>   #include <linux/pci.h>
>   #include <linux/netdevice.h>
>   #include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
>   #include <linux/phy.h>
>   #include <linux/of.h>
>   #include <linux/of_mdio.h>
> @@ -646,6 +647,7 @@ static inline void cgx_link_usertable_init(void)
>   	cgx_speed_mbps[CGX_LINK_25G] = 25000;
>   	cgx_speed_mbps[CGX_LINK_40G] = 40000;
>   	cgx_speed_mbps[CGX_LINK_50G] = 50000;
> +	cgx_speed_mbps[CGX_LINK_80G] = 80000;
>   	cgx_speed_mbps[CGX_LINK_100G] = 100000;
>   
>   	cgx_lmactype_string[LMAC_MODE_SGMII] = "SGMII";
> @@ -693,6 +695,110 @@ static int cgx_link_usertable_index_map(int speed)
>   	return CGX_LINK_NONE;
>   }
>   
> +static void set_mod_args(struct cgx_set_link_mode_args *args,
> +			 u32 speed, u8 duplex, u8 autoneg, u64 mode)
> +{
> +	/* Fill default values incase of user did not pass
> +	 * valid parameters
> +	 */
> +	if (args->duplex == DUPLEX_UNKNOWN)
> +		args->duplex = duplex;
> +	if (args->speed == SPEED_UNKNOWN)
> +		args->speed = speed;
> +	if (args->an == AUTONEG_UNKNOWN)
> +		args->an = autoneg;
> +	args->mode = mode;
> +	args->ports = 0;
> +}
> +
> +static void otx2_map_ethtool_link_modes(u64 bitmask,
> +					struct cgx_set_link_mode_args *args)
> +{
> +	switch (bitmask) {
> +	case ETHTOOL_LINK_MODE_10baseT_Half_BIT:
> +		set_mod_args(args, 10, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10baseT_Full_BIT:
> +		set_mod_args(args, 10, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100baseT_Half_BIT:
> +		set_mod_args(args, 100, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100baseT_Full_BIT:
> +		set_mod_args(args, 100, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseT_Half_BIT:
> +		set_mod_args(args, 1000, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseT_Full_BIT:
> +		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseX_Full_BIT:
> +		set_mod_args(args, 1000, 0, 0, BIT_ULL(CGX_MODE_1000_BASEX));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseT_Full_BIT:
> +		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_QSGMII));

Here the speed is set to 1000 but it looks like this should be 10000. I 
would have sent a patch to fix that but the mode is also a bit 
confusing. Normally I'd expect QSGMII to be used for Quad SGMII (i.e. 
4x1G Ethernet ports multiplexed over a single SERDES). I don't see any 
other mode in enum CGX_MODE_ that is obviously for 10GBase-T so I 
thought I'd bring this to your attention. I'd still be happy to whip up 
a patch if you could confirm what the correct mode should be.

> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseSR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseLR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseKR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 1, BIT_ULL(CGX_MODE_10G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 0, BIT_ULL(CGX_MODE_25G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_CR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_CR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_KR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_CR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_CR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_KR4));
> +		break;
> +	default:
> +		set_mod_args(args, 0, 1, 0, BIT_ULL(CGX_MODE_MAX));
> +		break;
> +	}
> +}
> +
>   static inline void link_status_user_format(u64 lstat,
>   					   struct cgx_link_user_info *linfo,
>   					   struct cgx *cgx, u8 lmac_id)
> @@ -887,13 +993,19 @@ int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
>   	if (!cgx)
>   		return -ENODEV;
>   
> +	if (args.mode)
> +		otx2_map_ethtool_link_modes(args.mode, &args);
> +	if (!args.speed && args.duplex && !args.an)
> +		return -EINVAL;
> +
>   	req = FIELD_SET(CMDREG_ID, CGX_CMD_MODE_CHANGE, req);
>   	req = FIELD_SET(CMDMODECHANGE_SPEED,
>   			cgx_link_usertable_index_map(args.speed), req);
>   	req = FIELD_SET(CMDMODECHANGE_DUPLEX, args.duplex, req);
>   	req = FIELD_SET(CMDMODECHANGE_AN, args.an, req);
>   	req = FIELD_SET(CMDMODECHANGE_PORT, args.ports, req);
> -	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.flags, req);
> +	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.mode, req);
> +
>   	return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id);
>   }
>   int cgx_set_fec(u64 fec, int cgx_id, int lmac_id)
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> index 70610e7..dde2bd0 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> @@ -70,6 +70,36 @@ enum cgx_link_speed {
>   	CGX_LINK_SPEED_MAX,
>   };
>   
> +enum CGX_MODE_ {
> +	CGX_MODE_SGMII,
> +	CGX_MODE_1000_BASEX,
> +	CGX_MODE_QSGMII,
> +	CGX_MODE_10G_C2C,
> +	CGX_MODE_10G_C2M,
> +	CGX_MODE_10G_KR,
> +	CGX_MODE_20G_C2C,
> +	CGX_MODE_25G_C2C,
> +	CGX_MODE_25G_C2M,
> +	CGX_MODE_25G_2_C2C,
> +	CGX_MODE_25G_CR,
> +	CGX_MODE_25G_KR,
> +	CGX_MODE_40G_C2C,
> +	CGX_MODE_40G_C2M,
> +	CGX_MODE_40G_CR4,
> +	CGX_MODE_40G_KR4,
> +	CGX_MODE_40GAUI_C2C,
> +	CGX_MODE_50G_C2C,
> +	CGX_MODE_50G_C2M,
> +	CGX_MODE_50G_4_C2C,
> +	CGX_MODE_50G_CR,
> +	CGX_MODE_50G_KR,
> +	CGX_MODE_80GAUI_C2C,
> +	CGX_MODE_100G_C2C,
> +	CGX_MODE_100G_C2M,
> +	CGX_MODE_100G_CR4,
> +	CGX_MODE_100G_KR4,
> +	CGX_MODE_MAX /* = 29 */
> +};
>   /* REQUEST ID types. Input to firmware */
>   enum cgx_cmd_id {
>   	CGX_CMD_NONE,
> @@ -231,6 +261,6 @@ struct cgx_lnk_sts {
>   #define CMDMODECHANGE_DUPLEX		GENMASK_ULL(12, 12)
>   #define CMDMODECHANGE_AN		GENMASK_ULL(13, 13)
>   #define CMDMODECHANGE_PORT		GENMASK_ULL(21, 14)
> -#define CMDMODECHANGE_FLAGS		GENMASK_ULL(29, 22)
> +#define CMDMODECHANGE_FLAGS		GENMASK_ULL(63, 22)
>   
>   #endif /* __CGX_FW_INTF_H__ */
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> index a050902..05a6da2 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> @@ -462,10 +462,11 @@ struct cgx_set_link_mode_args {
>   	u8 duplex;
>   	u8 an;
>   	u8 ports;
> -	u8 flags;
> +	u64 mode;
>   };
>   
>   struct cgx_set_link_mode_req {
> +#define AUTONEG_UNKNOWN		0xff
>   	struct mbox_msghdr hdr;
>   	struct cgx_set_link_mode_args args;
>   };

Thanks,
Chris
Hariprasad Kelam Dec. 2, 2022, 7:56 a.m. UTC | #3
Hi Chris ,

See inline,

Hi Hariprasad, Christina,

Sorry for poking an old thread but Richard and I were looking at some code and noticed something odd about it.

On 1/02/21 18:24, Hariprasad Kelam wrote:
> From: Christina Jacob <cjacob@marvell.com>
>
> CGX supports setting advertised link modes on physical link.
> This patch adds support to derive cgx mode from ethtool link mode and 
> pass it to firmware to configure the same.
>
> Signed-off-by: Christina Jacob <cjacob@marvell.com>
> Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
> Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
> ---
>   drivers/net/ethernet/marvell/octeontx2/af/cgx.c    | 114 ++++++++++++++++++++-
>   .../net/ethernet/marvell/octeontx2/af/cgx_fw_if.h  |  32 +++++-
>   drivers/net/ethernet/marvell/octeontx2/af/mbox.h   |   3 +-
>   3 files changed, 146 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c 
> b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> index 5b7d858..9c62129 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
> @@ -14,6 +14,7 @@
>   #include <linux/pci.h>
>   #include <linux/netdevice.h>
>   #include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
>   #include <linux/phy.h>
>   #include <linux/of.h>
>   #include <linux/of_mdio.h>
> @@ -646,6 +647,7 @@ static inline void cgx_link_usertable_init(void)
>   	cgx_speed_mbps[CGX_LINK_25G] = 25000;
>   	cgx_speed_mbps[CGX_LINK_40G] = 40000;
>   	cgx_speed_mbps[CGX_LINK_50G] = 50000;
> +	cgx_speed_mbps[CGX_LINK_80G] = 80000;
>   	cgx_speed_mbps[CGX_LINK_100G] = 100000;
>   
>   	cgx_lmactype_string[LMAC_MODE_SGMII] = "SGMII"; @@ -693,6 +695,110 
> @@ static int cgx_link_usertable_index_map(int speed)
>   	return CGX_LINK_NONE;
>   }
>   
> +static void set_mod_args(struct cgx_set_link_mode_args *args,
> +			 u32 speed, u8 duplex, u8 autoneg, u64 mode) {
> +	/* Fill default values incase of user did not pass
> +	 * valid parameters
> +	 */
> +	if (args->duplex == DUPLEX_UNKNOWN)
> +		args->duplex = duplex;
> +	if (args->speed == SPEED_UNKNOWN)
> +		args->speed = speed;
> +	if (args->an == AUTONEG_UNKNOWN)
> +		args->an = autoneg;
> +	args->mode = mode;
> +	args->ports = 0;
> +}
> +
> +static void otx2_map_ethtool_link_modes(u64 bitmask,
> +					struct cgx_set_link_mode_args *args) {
> +	switch (bitmask) {
> +	case ETHTOOL_LINK_MODE_10baseT_Half_BIT:
> +		set_mod_args(args, 10, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10baseT_Full_BIT:
> +		set_mod_args(args, 10, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100baseT_Half_BIT:
> +		set_mod_args(args, 100, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100baseT_Full_BIT:
> +		set_mod_args(args, 100, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseT_Half_BIT:
> +		set_mod_args(args, 1000, 1, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseT_Full_BIT:
> +		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_SGMII));
> +		break;
> +	case  ETHTOOL_LINK_MODE_1000baseX_Full_BIT:
> +		set_mod_args(args, 1000, 0, 0, BIT_ULL(CGX_MODE_1000_BASEX));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseT_Full_BIT:
> +		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_QSGMII));

Here the speed is set to 1000 but it looks like this should be 10000. I would have sent a patch to fix that but the mode is also a bit confusing. Normally I'd expect QSGMII to be used for Quad SGMII (i.e. 
4x1G Ethernet ports multiplexed over a single SERDES). I don't see any other mode in enum CGX_MODE_ that is obviously for 10GBase-T so I thought I'd bring this to your attention. I'd still be happy to whip up a patch if you could confirm what the correct mode should be.

>>  10GBase-T to QSGMII mapping is wrong. To correct it, we need to map proper 
      ETHTOOL_LINK_MODEX to QSGMII keeping all other parameters the same.
       As transmit and receive data paths of QSGMII leverage the 1000BASE-X , we may use
        ETHTOOL_LINK_MODE_1000baseSX_Full_BIT.
      If there are no objections to the above mode, go ahead and submit the patch.

Thanks,
Hariprasad k
      

> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseSR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseLR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_10000baseKR_Full_BIT:
> +		set_mod_args(args, 10000, 0, 1, BIT_ULL(CGX_MODE_10G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 0, BIT_ULL(CGX_MODE_25G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_CR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
> +		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_CR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
> +		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_KR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_CR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
> +		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_KR));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2C));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2M));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_CR4));
> +		break;
> +	case  ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
> +		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_KR4));
> +		break;
> +	default:
> +		set_mod_args(args, 0, 1, 0, BIT_ULL(CGX_MODE_MAX));
> +		break;
> +	}
> +}
> +
>   static inline void link_status_user_format(u64 lstat,
>   					   struct cgx_link_user_info *linfo,
>   					   struct cgx *cgx, u8 lmac_id) @@ -887,13 +993,19 @@ int 
> cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
>   	if (!cgx)
>   		return -ENODEV;
>   
> +	if (args.mode)
> +		otx2_map_ethtool_link_modes(args.mode, &args);
> +	if (!args.speed && args.duplex && !args.an)
> +		return -EINVAL;
> +
>   	req = FIELD_SET(CMDREG_ID, CGX_CMD_MODE_CHANGE, req);
>   	req = FIELD_SET(CMDMODECHANGE_SPEED,
>   			cgx_link_usertable_index_map(args.speed), req);
>   	req = FIELD_SET(CMDMODECHANGE_DUPLEX, args.duplex, req);
>   	req = FIELD_SET(CMDMODECHANGE_AN, args.an, req);
>   	req = FIELD_SET(CMDMODECHANGE_PORT, args.ports, req);
> -	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.flags, req);
> +	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.mode, req);
> +
>   	return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id);
>   }
>   int cgx_set_fec(u64 fec, int cgx_id, int lmac_id) diff --git 
> a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h 
> b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> index 70610e7..dde2bd0 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
> @@ -70,6 +70,36 @@ enum cgx_link_speed {
>   	CGX_LINK_SPEED_MAX,
>   };
>   
> +enum CGX_MODE_ {
> +	CGX_MODE_SGMII,
> +	CGX_MODE_1000_BASEX,
> +	CGX_MODE_QSGMII,
> +	CGX_MODE_10G_C2C,
> +	CGX_MODE_10G_C2M,
> +	CGX_MODE_10G_KR,
> +	CGX_MODE_20G_C2C,
> +	CGX_MODE_25G_C2C,
> +	CGX_MODE_25G_C2M,
> +	CGX_MODE_25G_2_C2C,
> +	CGX_MODE_25G_CR,
> +	CGX_MODE_25G_KR,
> +	CGX_MODE_40G_C2C,
> +	CGX_MODE_40G_C2M,
> +	CGX_MODE_40G_CR4,
> +	CGX_MODE_40G_KR4,
> +	CGX_MODE_40GAUI_C2C,
> +	CGX_MODE_50G_C2C,
> +	CGX_MODE_50G_C2M,
> +	CGX_MODE_50G_4_C2C,
> +	CGX_MODE_50G_CR,
> +	CGX_MODE_50G_KR,
> +	CGX_MODE_80GAUI_C2C,
> +	CGX_MODE_100G_C2C,
> +	CGX_MODE_100G_C2M,
> +	CGX_MODE_100G_CR4,
> +	CGX_MODE_100G_KR4,
> +	CGX_MODE_MAX /* = 29 */
> +};
>   /* REQUEST ID types. Input to firmware */
>   enum cgx_cmd_id {
>   	CGX_CMD_NONE,
> @@ -231,6 +261,6 @@ struct cgx_lnk_sts {
>   #define CMDMODECHANGE_DUPLEX		GENMASK_ULL(12, 12)
>   #define CMDMODECHANGE_AN		GENMASK_ULL(13, 13)
>   #define CMDMODECHANGE_PORT		GENMASK_ULL(21, 14)
> -#define CMDMODECHANGE_FLAGS		GENMASK_ULL(29, 22)
> +#define CMDMODECHANGE_FLAGS		GENMASK_ULL(63, 22)
>   
>   #endif /* __CGX_FW_INTF_H__ */
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h 
> b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> index a050902..05a6da2 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> @@ -462,10 +462,11 @@ struct cgx_set_link_mode_args {
>   	u8 duplex;
>   	u8 an;
>   	u8 ports;
> -	u8 flags;
> +	u64 mode;
>   };
>   
>   struct cgx_set_link_mode_req {
> +#define AUTONEG_UNKNOWN		0xff
>   	struct mbox_msghdr hdr;
>   	struct cgx_set_link_mode_args args;
>   };

Thanks,
Chris
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 5b7d858..9c62129 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -14,6 +14,7 @@ 
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
 #include <linux/phy.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
@@ -646,6 +647,7 @@  static inline void cgx_link_usertable_init(void)
 	cgx_speed_mbps[CGX_LINK_25G] = 25000;
 	cgx_speed_mbps[CGX_LINK_40G] = 40000;
 	cgx_speed_mbps[CGX_LINK_50G] = 50000;
+	cgx_speed_mbps[CGX_LINK_80G] = 80000;
 	cgx_speed_mbps[CGX_LINK_100G] = 100000;
 
 	cgx_lmactype_string[LMAC_MODE_SGMII] = "SGMII";
@@ -693,6 +695,110 @@  static int cgx_link_usertable_index_map(int speed)
 	return CGX_LINK_NONE;
 }
 
+static void set_mod_args(struct cgx_set_link_mode_args *args,
+			 u32 speed, u8 duplex, u8 autoneg, u64 mode)
+{
+	/* Fill default values incase of user did not pass
+	 * valid parameters
+	 */
+	if (args->duplex == DUPLEX_UNKNOWN)
+		args->duplex = duplex;
+	if (args->speed == SPEED_UNKNOWN)
+		args->speed = speed;
+	if (args->an == AUTONEG_UNKNOWN)
+		args->an = autoneg;
+	args->mode = mode;
+	args->ports = 0;
+}
+
+static void otx2_map_ethtool_link_modes(u64 bitmask,
+					struct cgx_set_link_mode_args *args)
+{
+	switch (bitmask) {
+	case ETHTOOL_LINK_MODE_10baseT_Half_BIT:
+		set_mod_args(args, 10, 1, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_10baseT_Full_BIT:
+		set_mod_args(args, 10, 0, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_100baseT_Half_BIT:
+		set_mod_args(args, 100, 1, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_100baseT_Full_BIT:
+		set_mod_args(args, 100, 0, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_1000baseT_Half_BIT:
+		set_mod_args(args, 1000, 1, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_1000baseT_Full_BIT:
+		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_SGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_1000baseX_Full_BIT:
+		set_mod_args(args, 1000, 0, 0, BIT_ULL(CGX_MODE_1000_BASEX));
+		break;
+	case  ETHTOOL_LINK_MODE_10000baseT_Full_BIT:
+		set_mod_args(args, 1000, 0, 1, BIT_ULL(CGX_MODE_QSGMII));
+		break;
+	case  ETHTOOL_LINK_MODE_10000baseSR_Full_BIT:
+		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2C));
+		break;
+	case  ETHTOOL_LINK_MODE_10000baseLR_Full_BIT:
+		set_mod_args(args, 10000, 0, 0, BIT_ULL(CGX_MODE_10G_C2M));
+		break;
+	case  ETHTOOL_LINK_MODE_10000baseKR_Full_BIT:
+		set_mod_args(args, 10000, 0, 1, BIT_ULL(CGX_MODE_10G_KR));
+		break;
+	case  ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
+		set_mod_args(args, 25000, 0, 0, BIT_ULL(CGX_MODE_25G_C2C));
+		break;
+	case  ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
+		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_CR));
+		break;
+	case  ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
+		set_mod_args(args, 25000, 0, 1, BIT_ULL(CGX_MODE_25G_KR));
+		break;
+	case  ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
+		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2C));
+		break;
+	case  ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
+		set_mod_args(args, 40000, 0, 0, BIT_ULL(CGX_MODE_40G_C2M));
+		break;
+	case  ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
+		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_CR4));
+		break;
+	case  ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
+		set_mod_args(args, 40000, 0, 1, BIT_ULL(CGX_MODE_40G_KR4));
+		break;
+	case  ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
+		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2C));
+		break;
+	case  ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
+		set_mod_args(args, 50000, 0, 0, BIT_ULL(CGX_MODE_50G_C2M));
+		break;
+	case  ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
+		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_CR));
+		break;
+	case  ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
+		set_mod_args(args, 50000, 0, 1, BIT_ULL(CGX_MODE_50G_KR));
+		break;
+	case  ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
+		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2C));
+		break;
+	case  ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
+		set_mod_args(args, 100000, 0, 0, BIT_ULL(CGX_MODE_100G_C2M));
+		break;
+	case  ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
+		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_CR4));
+		break;
+	case  ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
+		set_mod_args(args, 100000, 0, 1, BIT_ULL(CGX_MODE_100G_KR4));
+		break;
+	default:
+		set_mod_args(args, 0, 1, 0, BIT_ULL(CGX_MODE_MAX));
+		break;
+	}
+}
+
 static inline void link_status_user_format(u64 lstat,
 					   struct cgx_link_user_info *linfo,
 					   struct cgx *cgx, u8 lmac_id)
@@ -887,13 +993,19 @@  int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
 	if (!cgx)
 		return -ENODEV;
 
+	if (args.mode)
+		otx2_map_ethtool_link_modes(args.mode, &args);
+	if (!args.speed && args.duplex && !args.an)
+		return -EINVAL;
+
 	req = FIELD_SET(CMDREG_ID, CGX_CMD_MODE_CHANGE, req);
 	req = FIELD_SET(CMDMODECHANGE_SPEED,
 			cgx_link_usertable_index_map(args.speed), req);
 	req = FIELD_SET(CMDMODECHANGE_DUPLEX, args.duplex, req);
 	req = FIELD_SET(CMDMODECHANGE_AN, args.an, req);
 	req = FIELD_SET(CMDMODECHANGE_PORT, args.ports, req);
-	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.flags, req);
+	req = FIELD_SET(CMDMODECHANGE_FLAGS, args.mode, req);
+
 	return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id);
 }
 int cgx_set_fec(u64 fec, int cgx_id, int lmac_id)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
index 70610e7..dde2bd0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx_fw_if.h
@@ -70,6 +70,36 @@  enum cgx_link_speed {
 	CGX_LINK_SPEED_MAX,
 };
 
+enum CGX_MODE_ {
+	CGX_MODE_SGMII,
+	CGX_MODE_1000_BASEX,
+	CGX_MODE_QSGMII,
+	CGX_MODE_10G_C2C,
+	CGX_MODE_10G_C2M,
+	CGX_MODE_10G_KR,
+	CGX_MODE_20G_C2C,
+	CGX_MODE_25G_C2C,
+	CGX_MODE_25G_C2M,
+	CGX_MODE_25G_2_C2C,
+	CGX_MODE_25G_CR,
+	CGX_MODE_25G_KR,
+	CGX_MODE_40G_C2C,
+	CGX_MODE_40G_C2M,
+	CGX_MODE_40G_CR4,
+	CGX_MODE_40G_KR4,
+	CGX_MODE_40GAUI_C2C,
+	CGX_MODE_50G_C2C,
+	CGX_MODE_50G_C2M,
+	CGX_MODE_50G_4_C2C,
+	CGX_MODE_50G_CR,
+	CGX_MODE_50G_KR,
+	CGX_MODE_80GAUI_C2C,
+	CGX_MODE_100G_C2C,
+	CGX_MODE_100G_C2M,
+	CGX_MODE_100G_CR4,
+	CGX_MODE_100G_KR4,
+	CGX_MODE_MAX /* = 29 */
+};
 /* REQUEST ID types. Input to firmware */
 enum cgx_cmd_id {
 	CGX_CMD_NONE,
@@ -231,6 +261,6 @@  struct cgx_lnk_sts {
 #define CMDMODECHANGE_DUPLEX		GENMASK_ULL(12, 12)
 #define CMDMODECHANGE_AN		GENMASK_ULL(13, 13)
 #define CMDMODECHANGE_PORT		GENMASK_ULL(21, 14)
-#define CMDMODECHANGE_FLAGS		GENMASK_ULL(29, 22)
+#define CMDMODECHANGE_FLAGS		GENMASK_ULL(63, 22)
 
 #endif /* __CGX_FW_INTF_H__ */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index a050902..05a6da2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -462,10 +462,11 @@  struct cgx_set_link_mode_args {
 	u8 duplex;
 	u8 an;
 	u8 ports;
-	u8 flags;
+	u64 mode;
 };
 
 struct cgx_set_link_mode_req {
+#define AUTONEG_UNKNOWN		0xff
 	struct mbox_msghdr hdr;
 	struct cgx_set_link_mode_args args;
 };