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: Ravikumar Nelavelli <ravikumar.nelavelli@emulex.com> Signed-off-by: Suresh Reddy <Suresh.Reddy@emulex.com> Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e36edd9d26
commit
6809cee0ca
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue