Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6809cee0 authored by Ravikumar Nelavelli's avatar Ravikumar Nelavelli Committed by David S. Miller
Browse files

be2net: fix port-type reporting in get_settings



Report the ethtool port-type/supported/advertising values based on the
cable_type for QSFP and SFP+ interfaces. The cable_type is parsed from
the transceiver data fetched from the FW.

Signed-off-by: default avatarRavikumar Nelavelli <ravikumar.nelavelli@emulex.com>
Signed-off-by: default avatarSuresh Reddy <Suresh.Reddy@emulex.com>
Signed-off-by: default avatarSathya Perla <sathya.perla@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e36edd9d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -407,9 +407,9 @@ struct phy_info {
	u16 auto_speeds_supported;
	u16 fixed_speeds_supported;
	int link_speed;
	u32 dac_cable_len;
	u32 advertising;
	u32 supported;
	u8 cable_type;
};

struct be_resources {
+25 −0
Original line number Diff line number Diff line
@@ -2296,6 +2296,31 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
	return status;
}

int be_cmd_query_cable_type(struct be_adapter *adapter)
{
	u8 page_data[PAGE_DATA_LEN];
	int status;

	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
						   page_data);
	if (!status) {
		switch (adapter->phy.interface_type) {
		case PHY_TYPE_QSFP:
			adapter->phy.cable_type =
				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
			break;
		case PHY_TYPE_SFP_PLUS_10GB:
			adapter->phy.cable_type =
				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
			break;
		default:
			adapter->phy.cable_type = 0;
			break;
		}
	}
	return status;
}

int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
{
	struct lancer_cmd_req_delete_object *req;
+14 −1
Original line number Diff line number Diff line
@@ -1014,8 +1014,16 @@ enum {
	TR_PAGE_A2 = 0xa2
};

/* From SFF-8436 QSFP+ spec */
#define	QSFP_PLUS_CABLE_TYPE_OFFSET	0x83
#define	QSFP_PLUS_CR4_CABLE		0x8
#define	QSFP_PLUS_SR4_CABLE		0x4
#define	QSFP_PLUS_LR4_CABLE		0x2

/* From SFF-8472 spec */
#define	SFP_PLUS_SFF_8472_COMP		0x5E
#define	SFP_PLUS_CABLE_TYPE_OFFSET	0x8
#define	SFP_PLUS_COPPER_CABLE		0x4

#define PAGE_DATA_LEN   256
struct be_cmd_resp_port_type {
@@ -1355,6 +1363,9 @@ enum {
	PHY_TYPE_BASET_1GB,
	PHY_TYPE_BASEX_1GB,
	PHY_TYPE_SGMII,
	PHY_TYPE_QSFP,
	PHY_TYPE_KR4_40GB,
	PHY_TYPE_KR2_20GB,
	PHY_TYPE_DISABLED = 255
};

@@ -1363,6 +1374,7 @@ enum {
#define BE_SUPPORTED_SPEED_100MBPS	2
#define BE_SUPPORTED_SPEED_1GBPS	4
#define BE_SUPPORTED_SPEED_10GBPS	8
#define BE_SUPPORTED_SPEED_40GBPS	0x20

#define BE_AN_EN			0x2
#define BE_PAUSE_SYM_EN			0x80
@@ -2056,6 +2068,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
			    u32 *state);
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
				      u8 page_num, u8 *data);
int be_cmd_query_cable_type(struct be_adapter *adapter);
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
			  u32 flash_oper, u32 flash_opcode, u32 buf_size);
int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
+33 −14
Original line number Diff line number Diff line
@@ -475,18 +475,27 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
	}
}

static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len)
static u32 be_get_port_type(struct be_adapter *adapter)
{
	u32 port;

	switch (phy_type) {
	switch (adapter->phy.interface_type) {
	case PHY_TYPE_BASET_1GB:
	case PHY_TYPE_BASEX_1GB:
	case PHY_TYPE_SGMII:
		port = PORT_TP;
		break;
	case PHY_TYPE_SFP_PLUS_10GB:
		port = dac_cable_len ? PORT_DA : PORT_FIBRE;
		if (adapter->phy.cable_type & SFP_PLUS_COPPER_CABLE)
			port = PORT_DA;
		else
			port = PORT_FIBRE;
		break;
	case PHY_TYPE_QSFP:
		if (adapter->phy.cable_type & QSFP_PLUS_CR4_CABLE)
			port = PORT_DA;
		else
			port = PORT_FIBRE;
		break;
	case PHY_TYPE_XFP_10GB:
	case PHY_TYPE_SFP_1GB:
@@ -502,11 +511,11 @@ static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len)
	return port;
}

static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
static u32 convert_to_et_setting(struct be_adapter *adapter, u32 if_speeds)
{
	u32 val = 0;

	switch (if_type) {
	switch (adapter->phy.interface_type) {
	case PHY_TYPE_BASET_1GB:
	case PHY_TYPE_BASEX_1GB:
	case PHY_TYPE_SGMII:
@@ -529,6 +538,20 @@ static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
		val |= SUPPORTED_Backplane |
				SUPPORTED_10000baseKR_Full;
		break;
	case PHY_TYPE_QSFP:
		if (if_speeds & BE_SUPPORTED_SPEED_40GBPS) {
			switch (adapter->phy.cable_type) {
			case QSFP_PLUS_CR4_CABLE:
				val |= SUPPORTED_40000baseCR4_Full;
				break;
			case QSFP_PLUS_LR4_CABLE:
				val |= SUPPORTED_40000baseLR4_Full;
				break;
			default:
				val |= SUPPORTED_40000baseSR4_Full;
				break;
			}
		}
	case PHY_TYPE_SFP_PLUS_10GB:
	case PHY_TYPE_XFP_10GB:
	case PHY_TYPE_SFP_1GB:
@@ -569,8 +592,6 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
	int status;
	u32 auto_speeds;
	u32 fixed_speeds;
	u32 dac_cable_len;
	u16 interface_type;

	if (adapter->phy.link_speed < 0) {
		status = be_cmd_link_status_query(adapter, &link_speed,
@@ -581,21 +602,19 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)

		status = be_cmd_get_phy_info(adapter);
		if (!status) {
			interface_type = adapter->phy.interface_type;
			auto_speeds = adapter->phy.auto_speeds_supported;
			fixed_speeds = adapter->phy.fixed_speeds_supported;
			dac_cable_len = adapter->phy.dac_cable_len;

			be_cmd_query_cable_type(adapter);

			ecmd->supported =
				convert_to_et_setting(interface_type,
				convert_to_et_setting(adapter,
						      auto_speeds |
						      fixed_speeds);
			ecmd->advertising =
				convert_to_et_setting(interface_type,
						      auto_speeds);
				convert_to_et_setting(adapter, auto_speeds);

			ecmd->port = be_get_port_type(interface_type,
						      dac_cable_len);
			ecmd->port = be_get_port_type(adapter);

			if (adapter->phy.auto_speeds_supported) {
				ecmd->supported |= SUPPORTED_Autoneg;