Commit cd6e7381 authored by Jitendra Kalsaria's avatar Jitendra Kalsaria Committed by David S. Miller

qlcnic: Update Link speed and port type info for 83xx adapter

o Update the port type information
o Advertise correct link modes and autonegotiation
o Add support to change link speed
Signed-off-by: default avatarJitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: default avatarShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 10c51b56
...@@ -35,6 +35,35 @@ static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *); ...@@ -35,6 +35,35 @@ static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *);
#define QLC_SKIP_INACTIVE_PCI_REGS 7 #define QLC_SKIP_INACTIVE_PCI_REGS 7
#define QLC_MAX_LEGACY_FUNC_SUPP 8 #define QLC_MAX_LEGACY_FUNC_SUPP 8
/* 83xx Module type */
#define QLC_83XX_MODULE_FIBRE_10GBASE_LRM 0x1 /* 10GBase-LRM */
#define QLC_83XX_MODULE_FIBRE_10GBASE_LR 0x2 /* 10GBase-LR */
#define QLC_83XX_MODULE_FIBRE_10GBASE_SR 0x3 /* 10GBase-SR */
#define QLC_83XX_MODULE_DA_10GE_PASSIVE_CP 0x4 /* 10GE passive
* copper(compliant)
*/
#define QLC_83XX_MODULE_DA_10GE_ACTIVE_CP 0x5 /* 10GE active limiting
* copper(compliant)
*/
#define QLC_83XX_MODULE_DA_10GE_LEGACY_CP 0x6 /* 10GE passive copper
* (legacy, best effort)
*/
#define QLC_83XX_MODULE_FIBRE_1000BASE_SX 0x7 /* 1000Base-SX */
#define QLC_83XX_MODULE_FIBRE_1000BASE_LX 0x8 /* 1000Base-LX */
#define QLC_83XX_MODULE_FIBRE_1000BASE_CX 0x9 /* 1000Base-CX */
#define QLC_83XX_MODULE_TP_1000BASE_T 0xa /* 1000Base-T*/
#define QLC_83XX_MODULE_DA_1GE_PASSIVE_CP 0xb /* 1GE passive copper
* (legacy, best effort)
*/
#define QLC_83XX_MODULE_UNKNOWN 0xf /* Unknown module type */
/* Port types */
#define QLC_83XX_10_CAPABLE BIT_8
#define QLC_83XX_100_CAPABLE BIT_9
#define QLC_83XX_1G_CAPABLE BIT_10
#define QLC_83XX_10G_CAPABLE BIT_11
#define QLC_83XX_AUTONEG_ENABLE BIT_15
static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1}, {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
{QLCNIC_CMD_CONFIG_INTRPT, 18, 34}, {QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
...@@ -667,6 +696,7 @@ void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf, ...@@ -667,6 +696,7 @@ void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
int status; int status;
status = qlcnic_83xx_get_port_config(adapter); status = qlcnic_83xx_get_port_config(adapter);
...@@ -674,13 +704,20 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) ...@@ -674,13 +704,20 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Get Port Info failed\n"); "Get Port Info failed\n");
} else { } else {
if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
adapter->ahw->port_type = QLCNIC_XGBE;
else
adapter->ahw->port_type = QLCNIC_GBE;
if (QLC_83XX_AUTONEG(adapter->ahw->port_config)) if (ahw->port_config & QLC_83XX_10G_CAPABLE) {
adapter->ahw->link_autoneg = AUTONEG_ENABLE; ahw->port_type = QLCNIC_XGBE;
} else if (ahw->port_config & QLC_83XX_10_CAPABLE ||
ahw->port_config & QLC_83XX_100_CAPABLE ||
ahw->port_config & QLC_83XX_1G_CAPABLE) {
ahw->port_type = QLCNIC_GBE;
} else {
ahw->port_type = QLCNIC_XGBE;
}
if (QLC_83XX_AUTONEG(ahw->port_config))
ahw->link_autoneg = AUTONEG_ENABLE;
} }
return status; return status;
} }
...@@ -3176,22 +3213,33 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) ...@@ -3176,22 +3213,33 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
break; break;
} }
config = cmd.rsp.arg[3]; config = cmd.rsp.arg[3];
if (QLC_83XX_SFP_PRESENT(config)) { switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
switch (ahw->module_type) { case QLC_83XX_MODULE_FIBRE_10GBASE_LRM:
case LINKEVENT_MODULE_OPTICAL_UNKNOWN: case QLC_83XX_MODULE_FIBRE_10GBASE_LR:
case LINKEVENT_MODULE_OPTICAL_SRLR: case QLC_83XX_MODULE_FIBRE_10GBASE_SR:
case LINKEVENT_MODULE_OPTICAL_LRM:
case LINKEVENT_MODULE_OPTICAL_SFP_1G:
ahw->supported_type = PORT_FIBRE; ahw->supported_type = PORT_FIBRE;
ahw->port_type = QLCNIC_XGBE;
break; break;
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
case LINKEVENT_MODULE_TWINAX: case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
ahw->supported_type = PORT_FIBRE;
ahw->port_type = QLCNIC_GBE;
break;
case QLC_83XX_MODULE_TP_1000BASE_T:
ahw->supported_type = PORT_TP; ahw->supported_type = PORT_TP;
ahw->port_type = QLCNIC_GBE;
break;
case QLC_83XX_MODULE_DA_10GE_PASSIVE_CP:
case QLC_83XX_MODULE_DA_10GE_ACTIVE_CP:
case QLC_83XX_MODULE_DA_10GE_LEGACY_CP:
case QLC_83XX_MODULE_DA_1GE_PASSIVE_CP:
ahw->supported_type = PORT_DA;
ahw->port_type = QLCNIC_XGBE;
break; break;
default: default:
ahw->supported_type = PORT_OTHER; ahw->supported_type = PORT_OTHER;
} ahw->port_type = QLCNIC_XGBE;
} }
if (config & 1) if (config & 1)
err = 1; err = 1;
...@@ -3204,9 +3252,9 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) ...@@ -3204,9 +3252,9 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd) struct ethtool_cmd *ecmd)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 config = 0; u32 config = 0;
int status = 0; int status = 0;
struct qlcnic_hardware_context *ahw = adapter->ahw;
if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) { if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
/* Get port configuration info */ /* Get port configuration info */
...@@ -3229,20 +3277,41 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, ...@@ -3229,20 +3277,41 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
ecmd->autoneg = AUTONEG_DISABLE; ecmd->autoneg = AUTONEG_DISABLE;
} }
if (ahw->port_type == QLCNIC_XGBE) { ecmd->supported = (SUPPORTED_10baseT_Full |
ecmd->supported = SUPPORTED_10000baseT_Full;
ecmd->advertising = ADVERTISED_10000baseT_Full;
} else {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
SUPPORTED_1000baseT_Full); SUPPORTED_10000baseT_Full |
ecmd->advertising = (ADVERTISED_100baseT_Half | SUPPORTED_Autoneg);
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Half | if (ecmd->autoneg == AUTONEG_ENABLE) {
ADVERTISED_1000baseT_Full); if (ahw->port_config & QLC_83XX_10_CAPABLE)
ecmd->advertising |= SUPPORTED_10baseT_Full;
if (ahw->port_config & QLC_83XX_100_CAPABLE)
ecmd->advertising |= SUPPORTED_100baseT_Full;
if (ahw->port_config & QLC_83XX_1G_CAPABLE)
ecmd->advertising |= SUPPORTED_1000baseT_Full;
if (ahw->port_config & QLC_83XX_10G_CAPABLE)
ecmd->advertising |= SUPPORTED_10000baseT_Full;
if (ahw->port_config & QLC_83XX_AUTONEG_ENABLE)
ecmd->advertising |= ADVERTISED_Autoneg;
} else {
switch (ahw->link_speed) {
case SPEED_10:
ecmd->advertising = SUPPORTED_10baseT_Full;
break;
case SPEED_100:
ecmd->advertising = SUPPORTED_100baseT_Full;
break;
case SPEED_1000:
ecmd->advertising = SUPPORTED_1000baseT_Full;
break;
case SPEED_10000:
ecmd->advertising = SUPPORTED_10000baseT_Full;
break;
default:
break;
}
} }
switch (ahw->supported_type) { switch (ahw->supported_type) {
...@@ -3258,6 +3327,12 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, ...@@ -3258,6 +3327,12 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
ecmd->port = PORT_TP; ecmd->port = PORT_TP;
ecmd->transceiver = XCVR_INTERNAL; ecmd->transceiver = XCVR_INTERNAL;
break; break;
case PORT_DA:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_DA;
ecmd->transceiver = XCVR_EXTERNAL;
break;
default: default:
ecmd->supported |= SUPPORTED_FIBRE; ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE;
...@@ -3272,35 +3347,60 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, ...@@ -3272,35 +3347,60 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter, int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd) struct ethtool_cmd *ecmd)
{ {
int status = 0; struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 config = adapter->ahw->port_config; u32 config = adapter->ahw->port_config;
int status = 0;
if (ecmd->autoneg) /* 83xx devices do not support Half duplex */
adapter->ahw->port_config |= BIT_15; if (ecmd->duplex == DUPLEX_HALF) {
netdev_info(adapter->netdev,
"Half duplex mode not supported\n");
return -EINVAL;
}
if (ecmd->autoneg) {
ahw->port_config |= QLC_83XX_AUTONEG_ENABLE;
ahw->port_config |= (QLC_83XX_100_CAPABLE |
QLC_83XX_1G_CAPABLE |
QLC_83XX_10G_CAPABLE);
} else { /* force speed */
ahw->port_config &= ~QLC_83XX_AUTONEG_ENABLE;
switch (ethtool_cmd_speed(ecmd)) { switch (ethtool_cmd_speed(ecmd)) {
case SPEED_10: case SPEED_10:
adapter->ahw->port_config |= BIT_8; ahw->port_config &= ~(QLC_83XX_100_CAPABLE |
QLC_83XX_1G_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_10_CAPABLE;
break; break;
case SPEED_100: case SPEED_100:
adapter->ahw->port_config |= BIT_9; ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_1G_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_100_CAPABLE;
break; break;
case SPEED_1000: case SPEED_1000:
adapter->ahw->port_config |= BIT_10; ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_100_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_1G_CAPABLE;
break; break;
case SPEED_10000: case SPEED_10000:
adapter->ahw->port_config |= BIT_11; ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_100_CAPABLE |
QLC_83XX_1G_CAPABLE);
ahw->port_config |= QLC_83XX_10G_CAPABLE;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
}
status = qlcnic_83xx_set_port_config(adapter); status = qlcnic_83xx_set_port_config(adapter);
if (status) { if (status) {
dev_info(&adapter->pdev->dev, netdev_info(adapter->netdev,
"Failed to Set Link Speed and autoneg.\n"); "Failed to Set Link Speed and autoneg.\n");
adapter->ahw->port_config = config; ahw->port_config = config;
} }
return status; return status;
} }
......
...@@ -360,7 +360,6 @@ enum qlcnic_83xx_states { ...@@ -360,7 +360,6 @@ enum qlcnic_83xx_states {
#define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F) #define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F)
#define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16)) #define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16))
#define QLC_83XX_SFP_TX_FAULT(data) ((data) & BIT_10) #define QLC_83XX_SFP_TX_FAULT(data) ((data) & BIT_10)
#define QLC_83XX_SFP_10G_CAPABLE(data) ((data) & BIT_11)
#define QLC_83XX_LINK_STATS(data) ((data) & BIT_0) #define QLC_83XX_LINK_STATS(data) ((data) & BIT_0)
#define QLC_83XX_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7) #define QLC_83XX_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7)
#define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3) #define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment