net/qede/base: add EEE support
- Base driver EEE (Energy efficient ethernet) support. - Provide supported-speed mask to driver though shared memory. - Read/use eee-supported capabilities value from the shared memory. - Update qed_fill_link() to advertise the EEE capabilities. Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
This commit is contained in:
parent
a064d7d28b
commit
3c6a3cf607
@ -3108,10 +3108,42 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
|
||||
NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
|
||||
link->loopback_mode = 0;
|
||||
|
||||
if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
|
||||
link_temp = ecore_rd(p_hwfn, p_ptt, port_cfg_addr +
|
||||
OFFSETOF(struct nvm_cfg1_port, ext_phy));
|
||||
link_temp &= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK;
|
||||
link_temp >>= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_OFFSET;
|
||||
p_caps->default_eee = ECORE_MCP_EEE_ENABLED;
|
||||
link->eee.enable = true;
|
||||
switch (link_temp) {
|
||||
case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_DISABLED:
|
||||
p_caps->default_eee = ECORE_MCP_EEE_DISABLED;
|
||||
link->eee.enable = false;
|
||||
break;
|
||||
case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_BALANCED:
|
||||
p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_BALANCED_TIME;
|
||||
break;
|
||||
case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_AGGRESSIVE:
|
||||
p_caps->eee_lpi_timer =
|
||||
EEE_TX_TIMER_USEC_AGGRESSIVE_TIME;
|
||||
break;
|
||||
case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_LOW_LATENCY:
|
||||
p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_LATENCY_TIME;
|
||||
break;
|
||||
}
|
||||
|
||||
link->eee.tx_lpi_timer = p_caps->eee_lpi_timer;
|
||||
link->eee.tx_lpi_enable = link->eee.enable;
|
||||
link->eee.adv_caps = ECORE_EEE_1G_ADV | ECORE_EEE_10G_ADV;
|
||||
} else {
|
||||
p_caps->default_eee = ECORE_MCP_EEE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
|
||||
"Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n",
|
||||
"Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n EEE: %02x [%08x usec]",
|
||||
link->speed.forced_speed, link->speed.advertised_speeds,
|
||||
link->speed.autoneg, link->pause.autoneg);
|
||||
link->speed.autoneg, link->pause.autoneg,
|
||||
p_caps->default_eee, p_caps->eee_lpi_timer);
|
||||
|
||||
/* Read Multi-function information from shmem */
|
||||
addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
|
||||
@ -3317,6 +3349,27 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
|
||||
ecore_hw_info_port_num_ah_e5(p_hwfn, p_ptt);
|
||||
}
|
||||
|
||||
static void ecore_mcp_get_eee_caps(struct ecore_hwfn *p_hwfn,
|
||||
struct ecore_ptt *p_ptt)
|
||||
{
|
||||
struct ecore_mcp_link_capabilities *p_caps;
|
||||
u32 eee_status;
|
||||
|
||||
p_caps = &p_hwfn->mcp_info->link_capabilities;
|
||||
if (p_caps->default_eee == ECORE_MCP_EEE_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
p_caps->eee_speed_caps = 0;
|
||||
eee_status = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
|
||||
OFFSETOF(struct public_port, eee_status));
|
||||
eee_status = (eee_status & EEE_SUPPORTED_SPEED_MASK) >>
|
||||
EEE_SUPPORTED_SPEED_OFFSET;
|
||||
if (eee_status & EEE_1G_SUPPORTED)
|
||||
p_caps->eee_speed_caps |= ECORE_EEE_1G_ADV;
|
||||
if (eee_status & EEE_10G_ADV)
|
||||
p_caps->eee_speed_caps |= ECORE_EEE_10G_ADV;
|
||||
}
|
||||
|
||||
static enum _ecore_status_t
|
||||
ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
|
||||
enum ecore_pci_personality personality,
|
||||
@ -3386,6 +3439,8 @@ ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
|
||||
p_hwfn->mcp_info->func_info.ovlan;
|
||||
|
||||
ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
|
||||
|
||||
ecore_mcp_get_eee_caps(p_hwfn, p_ptt);
|
||||
}
|
||||
|
||||
if (personality != ECORE_PCI_DEFAULT) {
|
||||
|
@ -1036,6 +1036,29 @@ static void ecore_mcp_handle_transceiver_change(struct ecore_hwfn *p_hwfn,
|
||||
DP_NOTICE(p_hwfn, false, "Transceiver is unplugged.\n");
|
||||
}
|
||||
|
||||
static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
|
||||
struct ecore_ptt *p_ptt,
|
||||
struct ecore_mcp_link_state *p_link)
|
||||
{
|
||||
u32 eee_status, val;
|
||||
|
||||
p_link->eee_adv_caps = 0;
|
||||
p_link->eee_lp_adv_caps = 0;
|
||||
eee_status = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
|
||||
OFFSETOF(struct public_port, eee_status));
|
||||
p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT);
|
||||
val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_SHIFT;
|
||||
if (val & EEE_1G_ADV)
|
||||
p_link->eee_adv_caps |= ECORE_EEE_1G_ADV;
|
||||
if (val & EEE_10G_ADV)
|
||||
p_link->eee_adv_caps |= ECORE_EEE_10G_ADV;
|
||||
val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_SHIFT;
|
||||
if (val & EEE_1G_ADV)
|
||||
p_link->eee_lp_adv_caps |= ECORE_EEE_1G_ADV;
|
||||
if (val & EEE_10G_ADV)
|
||||
p_link->eee_lp_adv_caps |= ECORE_EEE_10G_ADV;
|
||||
}
|
||||
|
||||
static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
|
||||
struct ecore_ptt *p_ptt,
|
||||
bool b_reset)
|
||||
@ -1170,6 +1193,9 @@ static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
|
||||
|
||||
p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
|
||||
|
||||
if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
|
||||
ecore_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
|
||||
|
||||
OSAL_LINK_UPDATE(p_hwfn);
|
||||
}
|
||||
|
||||
@ -1197,6 +1223,27 @@ enum _ecore_status_t ecore_mcp_set_link(struct ecore_hwfn *p_hwfn,
|
||||
phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0;
|
||||
phy_cfg.adv_speed = params->speed.advertised_speeds;
|
||||
phy_cfg.loopback_mode = params->loopback_mode;
|
||||
|
||||
/* There are MFWs that share this capability regardless of whether
|
||||
* this is feasible or not. And given that at the very least adv_caps
|
||||
* would be set internally by ecore, we want to make sure LFA would
|
||||
* still work.
|
||||
*/
|
||||
if ((p_hwfn->mcp_info->capabilities &
|
||||
FW_MB_PARAM_FEATURE_SUPPORT_EEE) &&
|
||||
params->eee.enable) {
|
||||
phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED;
|
||||
if (params->eee.tx_lpi_enable)
|
||||
phy_cfg.eee_cfg |= EEE_CFG_TX_LPI;
|
||||
if (params->eee.adv_caps & ECORE_EEE_1G_ADV)
|
||||
phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G;
|
||||
if (params->eee.adv_caps & ECORE_EEE_10G_ADV)
|
||||
phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G;
|
||||
phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer <<
|
||||
EEE_TX_TIMER_USEC_SHIFT) &
|
||||
EEE_TX_TIMER_USEC_MASK;
|
||||
}
|
||||
|
||||
p_hwfn->b_drv_link_init = b_up;
|
||||
|
||||
if (b_up)
|
||||
@ -3331,7 +3378,8 @@ enum _ecore_status_t ecore_mcp_set_capabilities(struct ecore_hwfn *p_hwfn,
|
||||
{
|
||||
u32 mcp_resp, mcp_param, features;
|
||||
|
||||
features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ;
|
||||
features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ |
|
||||
DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE;
|
||||
|
||||
return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
|
||||
features, &mcp_resp, &mcp_param);
|
||||
|
@ -23,16 +23,37 @@ struct ecore_mcp_link_pause_params {
|
||||
bool forced_tx;
|
||||
};
|
||||
|
||||
enum ecore_mcp_eee_mode {
|
||||
ECORE_MCP_EEE_DISABLED,
|
||||
ECORE_MCP_EEE_ENABLED,
|
||||
ECORE_MCP_EEE_UNSUPPORTED
|
||||
};
|
||||
|
||||
struct ecore_link_eee_params {
|
||||
u32 tx_lpi_timer;
|
||||
#define ECORE_EEE_1G_ADV (1 << 0)
|
||||
#define ECORE_EEE_10G_ADV (1 << 1)
|
||||
/* Capabilities are represented using ECORE_EEE_*_ADV values */
|
||||
u8 adv_caps;
|
||||
u8 lp_adv_caps;
|
||||
bool enable;
|
||||
bool tx_lpi_enable;
|
||||
};
|
||||
|
||||
struct ecore_mcp_link_params {
|
||||
struct ecore_mcp_link_speed_params speed;
|
||||
struct ecore_mcp_link_pause_params pause;
|
||||
u32 loopback_mode; /* in PMM_LOOPBACK values */
|
||||
struct ecore_link_eee_params eee;
|
||||
};
|
||||
|
||||
struct ecore_mcp_link_capabilities {
|
||||
u32 speed_capabilities;
|
||||
bool default_speed_autoneg; /* In Mb/s */
|
||||
u32 default_speed; /* In Mb/s */
|
||||
enum ecore_mcp_eee_mode default_eee;
|
||||
u32 eee_lpi_timer;
|
||||
u8 eee_speed_caps;
|
||||
};
|
||||
|
||||
struct ecore_mcp_link_state {
|
||||
@ -67,6 +88,10 @@ struct ecore_mcp_link_state {
|
||||
u8 partner_adv_pause;
|
||||
|
||||
bool sfp_tx_fault;
|
||||
|
||||
bool eee_active;
|
||||
u8 eee_adv_caps;
|
||||
u8 eee_lp_adv_caps;
|
||||
};
|
||||
|
||||
struct ecore_mcp_function_info {
|
||||
|
@ -792,6 +792,12 @@ struct public_port {
|
||||
#define EEE_LP_ADV_STATUS_MASK 0x00000f00
|
||||
#define EEE_LP_ADV_STATUS_SHIFT 8
|
||||
|
||||
/* Supported speeds for EEE */
|
||||
#define EEE_SUPPORTED_SPEED_MASK 0x0000f000
|
||||
#define EEE_SUPPORTED_SPEED_OFFSET 12
|
||||
#define EEE_1G_SUPPORTED (1 << 1)
|
||||
#define EEE_10G_SUPPORTED (1 << 2)
|
||||
|
||||
u32 eee_remote; /* Used for EEE in LLDP */
|
||||
#define EEE_REMOTE_TW_TX_MASK 0x0000ffff
|
||||
#define EEE_REMOTE_TW_TX_SHIFT 0
|
||||
|
@ -83,6 +83,7 @@ struct qed_link_params {
|
||||
#define QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS (1 << 1)
|
||||
#define QED_LINK_OVERRIDE_SPEED_FORCED_SPEED (1 << 2)
|
||||
#define QED_LINK_OVERRIDE_PAUSE_CONFIG (1 << 3)
|
||||
#define QED_LINK_OVERRIDE_EEE_CONFIG (1 << 5)
|
||||
uint32_t override_flags;
|
||||
bool autoneg;
|
||||
uint32_t adv_speeds;
|
||||
@ -91,6 +92,7 @@ struct qed_link_params {
|
||||
#define QED_LINK_PAUSE_RX_ENABLE (1 << 1)
|
||||
#define QED_LINK_PAUSE_TX_ENABLE (1 << 2)
|
||||
uint32_t pause_config;
|
||||
struct ecore_link_eee_params eee;
|
||||
};
|
||||
|
||||
struct qed_link_output {
|
||||
@ -104,6 +106,12 @@ struct qed_link_output {
|
||||
uint8_t port; /* In PORT defs */
|
||||
bool autoneg;
|
||||
uint32_t pause_config;
|
||||
|
||||
/* EEE - capability & param */
|
||||
bool eee_supported;
|
||||
bool eee_active;
|
||||
u8 sup_caps;
|
||||
struct ecore_link_eee_params eee;
|
||||
};
|
||||
|
||||
struct qed_slowpath_params {
|
||||
|
@ -539,6 +539,21 @@ static void qed_fill_link(struct ecore_hwfn *hwfn,
|
||||
|
||||
if (params.pause.forced_tx)
|
||||
if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
|
||||
|
||||
if (link_caps.default_eee == ECORE_MCP_EEE_UNSUPPORTED) {
|
||||
if_link->eee_supported = false;
|
||||
} else {
|
||||
if_link->eee_supported = true;
|
||||
if_link->eee_active = link.eee_active;
|
||||
if_link->sup_caps = link_caps.eee_speed_caps;
|
||||
/* MFW clears adv_caps on eee disable; use configured value */
|
||||
if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps :
|
||||
params.eee.adv_caps;
|
||||
if_link->eee.lp_adv_caps = link.eee_lp_adv_caps;
|
||||
if_link->eee.enable = params.eee.enable;
|
||||
if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable;
|
||||
if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -588,6 +603,10 @@ static int qed_set_link(struct ecore_dev *edev, struct qed_link_params *params)
|
||||
link_params->pause.forced_tx = false;
|
||||
}
|
||||
|
||||
if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG)
|
||||
memcpy(&link_params->eee, ¶ms->eee,
|
||||
sizeof(link_params->eee));
|
||||
|
||||
rc = ecore_mcp_set_link(hwfn, ptt, params->link_up);
|
||||
|
||||
ecore_ptt_release(hwfn, ptt);
|
||||
|
Loading…
x
Reference in New Issue
Block a user