提交 cd6e7381 编写于 作者: J Jitendra Kalsaria 提交者: 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: NJitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: NShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 10c51b56
......@@ -35,6 +35,35 @@ static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *);
#define QLC_SKIP_INACTIVE_PCI_REGS 7
#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[] = {
{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
{QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
......@@ -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)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
int status;
status = qlcnic_83xx_get_port_config(adapter);
......@@ -674,13 +704,20 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
dev_err(&adapter->pdev->dev,
"Get Port Info failed\n");
} 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))
adapter->ahw->link_autoneg = AUTONEG_ENABLE;
if (ahw->port_config & QLC_83XX_10G_CAPABLE) {
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;
}
......@@ -3176,22 +3213,33 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
break;
}
config = cmd.rsp.arg[3];
if (QLC_83XX_SFP_PRESENT(config)) {
switch (ahw->module_type) {
case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
case LINKEVENT_MODULE_OPTICAL_SRLR:
case LINKEVENT_MODULE_OPTICAL_LRM:
case LINKEVENT_MODULE_OPTICAL_SFP_1G:
ahw->supported_type = PORT_FIBRE;
break;
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
case LINKEVENT_MODULE_TWINAX:
ahw->supported_type = PORT_TP;
break;
default:
ahw->supported_type = PORT_OTHER;
}
switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
case QLC_83XX_MODULE_FIBRE_10GBASE_LRM:
case QLC_83XX_MODULE_FIBRE_10GBASE_LR:
case QLC_83XX_MODULE_FIBRE_10GBASE_SR:
ahw->supported_type = PORT_FIBRE;
ahw->port_type = QLCNIC_XGBE;
break;
case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
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->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;
default:
ahw->supported_type = PORT_OTHER;
ahw->port_type = QLCNIC_XGBE;
}
if (config & 1)
err = 1;
......@@ -3204,9 +3252,9 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 config = 0;
int status = 0;
struct qlcnic_hardware_context *ahw = adapter->ahw;
if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
/* Get port configuration info */
......@@ -3229,20 +3277,41 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
ecmd->autoneg = AUTONEG_DISABLE;
}
if (ahw->port_type == QLCNIC_XGBE) {
ecmd->supported = SUPPORTED_10000baseT_Full;
ecmd->advertising = ADVERTISED_10000baseT_Full;
ecmd->supported = (SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_10000baseT_Full |
SUPPORTED_Autoneg);
if (ecmd->autoneg == AUTONEG_ENABLE) {
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 {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
ecmd->advertising = (ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full);
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) {
......@@ -3258,6 +3327,12 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
ecmd->port = PORT_TP;
ecmd->transceiver = XCVR_INTERNAL;
break;
case PORT_DA:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_DA;
ecmd->transceiver = XCVR_EXTERNAL;
break;
default:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
......@@ -3272,35 +3347,60 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd)
{
int status = 0;
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 config = adapter->ahw->port_config;
int status = 0;
if (ecmd->autoneg)
adapter->ahw->port_config |= BIT_15;
switch (ethtool_cmd_speed(ecmd)) {
case SPEED_10:
adapter->ahw->port_config |= BIT_8;
break;
case SPEED_100:
adapter->ahw->port_config |= BIT_9;
break;
case SPEED_1000:
adapter->ahw->port_config |= BIT_10;
break;
case SPEED_10000:
adapter->ahw->port_config |= BIT_11;
break;
default:
return -EINVAL;
/* 83xx devices do not support Half duplex */
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)) {
case SPEED_10:
ahw->port_config &= ~(QLC_83XX_100_CAPABLE |
QLC_83XX_1G_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_10_CAPABLE;
break;
case SPEED_100:
ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_1G_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_100_CAPABLE;
break;
case SPEED_1000:
ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_100_CAPABLE |
QLC_83XX_10G_CAPABLE);
ahw->port_config |= QLC_83XX_1G_CAPABLE;
break;
case SPEED_10000:
ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
QLC_83XX_100_CAPABLE |
QLC_83XX_1G_CAPABLE);
ahw->port_config |= QLC_83XX_10G_CAPABLE;
break;
default:
return -EINVAL;
}
}
status = qlcnic_83xx_set_port_config(adapter);
if (status) {
dev_info(&adapter->pdev->dev,
"Failed to Set Link Speed and autoneg.\n");
adapter->ahw->port_config = config;
netdev_info(adapter->netdev,
"Failed to Set Link Speed and autoneg.\n");
ahw->port_config = config;
}
return status;
}
......
......@@ -360,7 +360,6 @@ enum qlcnic_83xx_states {
#define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F)
#define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16))
#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_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7)
#define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册