bnx2x: Add dual-media changes

Add required changes in order to support dual-media boards.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yaniv Rosner 2010-09-07 11:41:20 +00:00 committed by David S. Miller
parent de6eae1f42
commit a22f078867
9 changed files with 1073 additions and 375 deletions

View File

@ -566,13 +566,13 @@ struct bnx2x_common {
struct bnx2x_port {
u32 pmf;
u32 link_config;
u32 link_config[LINK_CONFIG_SIZE];
u32 supported;
u32 supported[LINK_CONFIG_SIZE];
/* link settings - missing defines */
#define SUPPORTED_2500baseX_Full (1 << 15)
u32 advertising;
u32 advertising[LINK_CONFIG_SIZE];
/* link settings - missing defines */
#define ADVERTISED_2500baseX_Full (1 << 15)
@ -931,7 +931,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
u32 bnx2x_fw_command(struct bnx2x *bp, u32 command);
u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
u32 addr, u32 len);
@ -939,7 +939,7 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp);
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
u32 data_hi, u32 data_lo, int common);
void bnx2x_update_coalesce(struct bnx2x *bp);
int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait)
{

View File

@ -1283,7 +1283,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
common blocks should be initialized, otherwise - not
*/
if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
@ -1322,9 +1322,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
goto load_error2;
}
@ -1339,7 +1339,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Send LOAD_DONE command to MCP */
if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
@ -1455,8 +1455,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
load_error3:
bnx2x_int_disable_sync(bp, 1);
if (!BP_NOMCP(bp)) {
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
}
bp->port.pmf = 0;
/* Free SKBs, SGEs, TPA pool and driver internals */

View File

@ -49,10 +49,11 @@ void bnx2x_link_set(struct bnx2x *bp);
* Query link status
*
* @param bp
* @param is_serdes
*
* @return 0 - link is UP
*/
u8 bnx2x_link_test(struct bnx2x *bp);
u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
/**
* Handles link status change

View File

@ -29,9 +29,12 @@
static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2x *bp = netdev_priv(dev);
cmd->supported = bp->port.supported;
cmd->advertising = bp->port.advertising;
int cfg_idx = bnx2x_get_link_cfg_idx(bp);
/* Dual Media boards present all available port types */
cmd->supported = bp->port.supported[cfg_idx] |
(bp->port.supported[cfg_idx ^ 1] &
(SUPPORTED_TP | SUPPORTED_FIBRE));
cmd->advertising = bp->port.advertising[cfg_idx];
if ((bp->state == BNX2X_STATE_OPEN) &&
!(bp->flags & MF_FUNC_DIS) &&
@ -48,22 +51,21 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->speed = vn_max_rate;
}
} else {
cmd->speed = -1;
cmd->duplex = -1;
cmd->speed = bp->link_params.req_line_speed[cfg_idx];
cmd->duplex = bp->link_params.req_duplex[cfg_idx];
}
if (bp->link_params.num_phys > 0) {
if (bp->link_params.phy[bp->link_params.num_phys - 1].
supported & SUPPORTED_FIBRE)
cmd->port = PORT_FIBRE;
else
cmd->port = PORT_TP;
} else
DP(NETIF_MSG_LINK, "No media found\n");
if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
cmd->port = PORT_TP;
else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
cmd->port = PORT_FIBRE;
else
BNX2X_ERR("XGXS PHY Failure detected\n");
cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL;
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG)
cmd->autoneg = AUTONEG_ENABLE;
else
cmd->autoneg = AUTONEG_DISABLE;
@ -85,7 +87,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2x *bp = netdev_priv(dev);
u32 advertising;
u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config;
if (IS_E1HMF(bp))
return 0;
@ -98,26 +100,81 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
cfg_idx = bnx2x_get_link_cfg_idx(bp);
old_multi_phy_config = bp->link_params.multi_phy_config;
switch (cmd->port) {
case PORT_TP:
if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
break; /* no port change */
if (!(bp->port.supported[0] & SUPPORTED_TP ||
bp->port.supported[1] & SUPPORTED_TP)) {
DP(NETIF_MSG_LINK, "Unsupported port type\n");
return -EINVAL;
}
bp->link_params.multi_phy_config &=
~PORT_HW_CFG_PHY_SELECTION_MASK;
if (bp->link_params.multi_phy_config &
PORT_HW_CFG_PHY_SWAPPED_ENABLED)
bp->link_params.multi_phy_config |=
PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
else
bp->link_params.multi_phy_config |=
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
break;
case PORT_FIBRE:
if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
break; /* no port change */
if (!(bp->port.supported[0] & SUPPORTED_FIBRE ||
bp->port.supported[1] & SUPPORTED_FIBRE)) {
DP(NETIF_MSG_LINK, "Unsupported port type\n");
return -EINVAL;
}
bp->link_params.multi_phy_config &=
~PORT_HW_CFG_PHY_SELECTION_MASK;
if (bp->link_params.multi_phy_config &
PORT_HW_CFG_PHY_SWAPPED_ENABLED)
bp->link_params.multi_phy_config |=
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
else
bp->link_params.multi_phy_config |=
PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
break;
default:
DP(NETIF_MSG_LINK, "Unsupported port type\n");
return -EINVAL;
}
/* Save new config in case command complete successuly */
new_multi_phy_config = bp->link_params.multi_phy_config;
/* Get the new cfg_idx */
cfg_idx = bnx2x_get_link_cfg_idx(bp);
/* Restore old config in case command failed */
bp->link_params.multi_phy_config = old_multi_phy_config;
DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
if (cmd->autoneg == AUTONEG_ENABLE) {
if (!(bp->port.supported & SUPPORTED_Autoneg)) {
if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "Autoneg not supported\n");
return -EINVAL;
}
/* advertise the requested speed and duplex if supported */
cmd->advertising &= bp->port.supported;
cmd->advertising &= bp->port.supported[cfg_idx];
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
bp->link_params.req_duplex = DUPLEX_FULL;
bp->port.advertising |= (ADVERTISED_Autoneg |
bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG;
bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL;
bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg |
cmd->advertising);
} else { /* forced speed */
/* advertise the requested speed and duplex if supported */
switch (cmd->speed) {
u32 speed = cmd->speed;
speed |= (cmd->speed_hi << 16);
switch (speed) {
case SPEED_10:
if (cmd->duplex == DUPLEX_FULL) {
if (!(bp->port.supported &
if (!(bp->port.supported[cfg_idx] &
SUPPORTED_10baseT_Full)) {
DP(NETIF_MSG_LINK,
"10M full not supported\n");
@ -127,7 +184,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising = (ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
if (!(bp->port.supported &
if (!(bp->port.supported[cfg_idx] &
SUPPORTED_10baseT_Half)) {
DP(NETIF_MSG_LINK,
"10M half not supported\n");
@ -141,7 +198,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
case SPEED_100:
if (cmd->duplex == DUPLEX_FULL) {
if (!(bp->port.supported &
if (!(bp->port.supported[cfg_idx] &
SUPPORTED_100baseT_Full)) {
DP(NETIF_MSG_LINK,
"100M full not supported\n");
@ -151,7 +208,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising = (ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
if (!(bp->port.supported &
if (!(bp->port.supported[cfg_idx] &
SUPPORTED_100baseT_Half)) {
DP(NETIF_MSG_LINK,
"100M half not supported\n");
@ -169,7 +226,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) {
if (!(bp->port.supported[cfg_idx] &
SUPPORTED_1000baseT_Full)) {
DP(NETIF_MSG_LINK, "1G full not supported\n");
return -EINVAL;
}
@ -185,7 +243,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) {
if (!(bp->port.supported[cfg_idx]
& SUPPORTED_2500baseX_Full)) {
DP(NETIF_MSG_LINK,
"2.5G full not supported\n");
return -EINVAL;
@ -201,7 +260,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) {
if (!(bp->port.supported[cfg_idx]
& SUPPORTED_10000baseT_Full)) {
DP(NETIF_MSG_LINK, "10G full not supported\n");
return -EINVAL;
}
@ -211,20 +271,23 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
break;
default:
DP(NETIF_MSG_LINK, "Unsupported speed\n");
DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed);
return -EINVAL;
}
bp->link_params.req_line_speed = cmd->speed;
bp->link_params.req_duplex = cmd->duplex;
bp->port.advertising = advertising;
bp->link_params.req_line_speed[cfg_idx] = speed;
bp->link_params.req_duplex[cfg_idx] = cmd->duplex;
bp->port.advertising[cfg_idx] = advertising;
}
DP(NETIF_MSG_LINK, "req_line_speed %d\n"
DP_LEVEL " req_duplex %d advertising 0x%x\n",
bp->link_params.req_line_speed, bp->link_params.req_duplex,
bp->port.advertising);
bp->link_params.req_line_speed[cfg_idx],
bp->link_params.req_duplex[cfg_idx],
bp->port.advertising[cfg_idx]);
/* Set new config */
bp->link_params.multi_phy_config = new_multi_phy_config;
if (netif_running(dev)) {
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
bnx2x_link_set(bp);
@ -937,10 +1000,9 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
struct bnx2x *bp = netdev_priv(dev);
epause->autoneg = (bp->link_params.req_flow_ctrl ==
BNX2X_FLOW_CTRL_AUTO) &&
(bp->link_params.req_line_speed == SPEED_AUTO_NEG);
int cfg_idx = bnx2x_get_link_cfg_idx(bp);
epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
BNX2X_FLOW_CTRL_AUTO);
epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
BNX2X_FLOW_CTRL_RX);
@ -956,7 +1018,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
struct bnx2x *bp = netdev_priv(dev);
u32 cfg_idx = bnx2x_get_link_cfg_idx(bp);
if (IS_E1HMF(bp))
return 0;
@ -964,29 +1026,31 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
if (epause->rx_pause)
bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX;
bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX;
if (epause->tx_pause)
bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX;
bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX;
if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO)
bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE;
if (epause->autoneg) {
if (!(bp->port.supported & SUPPORTED_Autoneg)) {
if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "autoneg not supported\n");
return -EINVAL;
}
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) {
bp->link_params.req_flow_ctrl[cfg_idx] =
BNX2X_FLOW_CTRL_AUTO;
}
}
DP(NETIF_MSG_LINK,
"req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl);
"req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]);
if (netif_running(dev)) {
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@ -1250,12 +1314,12 @@ static int bnx2x_test_memory(struct bnx2x *bp)
return rc;
}
static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up)
static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
{
int cnt = 1000;
if (link_up)
while (bnx2x_link_test(bp) && cnt--)
while (bnx2x_link_test(bp, is_serdes) && cnt--)
msleep(10);
}
@ -1527,7 +1591,7 @@ static void bnx2x_self_test(struct net_device *dev,
struct ethtool_test *etest, u64 *buf)
{
struct bnx2x *bp = netdev_priv(dev);
u8 is_serdes;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
printk(KERN_ERR "Handling parity error recovery. Try again later\n");
etest->flags |= ETH_TEST_FL_FAILED;
@ -1542,6 +1606,7 @@ static void bnx2x_self_test(struct net_device *dev,
/* offline tests are not supported in MF mode */
if (IS_E1HMF(bp))
etest->flags &= ~ETH_TEST_FL_OFFLINE;
is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0;
if (etest->flags & ETH_TEST_FL_OFFLINE) {
int port = BP_PORT(bp);
@ -1553,11 +1618,12 @@ static void bnx2x_self_test(struct net_device *dev,
/* disable input for TX port IF */
REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
link_up = (bnx2x_link_test(bp) == 0);
link_up = bp->link_vars.link_up;
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
/* wait until link state is restored */
bnx2x_wait_for_link(bp, link_up);
bnx2x_wait_for_link(bp, link_up, is_serdes);
if (bnx2x_test_registers(bp) != 0) {
buf[0] = 1;
@ -1578,7 +1644,7 @@ static void bnx2x_self_test(struct net_device *dev,
bnx2x_nic_load(bp, LOAD_NORMAL);
/* wait until link state is restored */
bnx2x_wait_for_link(bp, link_up);
bnx2x_wait_for_link(bp, link_up, is_serdes);
}
if (bnx2x_test_nvram(bp) != 0) {
buf[3] = 1;
@ -1589,7 +1655,7 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED;
}
if (bp->port.pmf)
if (bnx2x_link_test(bp) != 0) {
if (bnx2x_link_test(bp, is_serdes) != 0) {
buf[5] = 1;
etest->flags |= ETH_TEST_FL_FAILED;
}

View File

@ -238,7 +238,88 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u16 xgxs_config_tx[4]; /* 0x1A0 */
u32 Reserved1[64]; /* 0x1A8 */
u32 Reserved1[57]; /* 0x1A8 */
u32 speed_capability_mask2; /* 0x28C */
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G 0x00000080
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G 0x00000100
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G 0x00000200
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G 0x00000400
#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G 0x00000800
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G 0x00800000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G 0x01000000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G 0x02000000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G 0x04000000
#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G 0x08000000
/* In the case where two media types (e.g. copper and fiber) are
present and electrically active at the same time, PHY Selection
will determine which of the two PHYs will be designated as the
Active PHY and used for a connection to the network. */
u32 multi_phy_config; /* 0x290 */
#define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
#define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
/* When enabled, all second phy nvram parameters will be swapped
with the first phy parameters */
#define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
#define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
#define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
#define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
/* Address of the second external phy */
u32 external_phy_config2; /* 0x294 */
#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
/* The second XGXS external PHY type */
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
/* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
8706, 8726 and 8727) not all 4 values are needed. */
u16 xgxs_config2_rx[4]; /* 0x296 */
u16 xgxs_config2_tx[4]; /* 0x2A0 */
u32 lane_config;
#define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
@ -532,10 +613,17 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
#define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
/* The default for MCP link configuration,
uses the same defines as link_config */
uses the same defines as link_config */
u32 mfw_wol_link_cfg;
/* The default for the driver of the second external phy,
uses the same defines as link_config */
u32 link_config2; /* 0x47C */
u32 reserved[19];
/* The default for MCP of the second external phy,
uses the same defines as link_config */
u32 mfw_wol_link_cfg2; /* 0x480 */
u32 Reserved2[17]; /* 0x484 */
};
@ -703,8 +791,14 @@ struct drv_func_mb {
* The optic module verification commands require bootcode
* v5.0.6 or later
*/
#define DRV_MSG_CODE_VRFY_OPT_MDL 0xa0000000
#define REQ_BC_VER_4_VRFY_OPT_MDL 0x00050006
#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
/*
* The specific optic module verification command requires bootcode
* v5.2.12 or later
*/
#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
@ -939,7 +1033,12 @@ struct shmem2_region {
#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
#define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE
u32 ext_phy_fw_version2[PORT_MAX];
/*
* For backwards compatibility, if the mf_cfg_addr does not exist
* (the size filed is smaller than 0xc) the mf_cfg resides at the
* end of struct shmem_region
*/
};

File diff suppressed because it is too large Load Diff

View File

@ -59,13 +59,18 @@
#define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1)
/* Single Media board contains single external phy */
#define SINGLE_MEDIA(params) (params->num_phys == 2)
/* Dual Media board contains two external phy with different media */
#define DUAL_MEDIA(params) (params->num_phys == 3)
#define FW_PARAM_MDIO_CTRL_OFFSET 16
#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
/***********************************************************/
/* Structs */
/***********************************************************/
#define INT_PHY 0
#define EXT_PHY1 1
#define MAX_PHYS 2
#define EXT_PHY2 2
#define MAX_PHYS 3
/* Same configuration is shared between the XGXS and the first external phy */
#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
@ -91,6 +96,8 @@ typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
struct link_params *params, u8 mode);
typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
struct link_params *params, u32 action);
struct bnx2x_phy {
u32 type;
@ -106,7 +113,9 @@ struct bnx2x_phy {
/* Fan failure detection required */
#define FLAGS_FAN_FAILURE_DET_REQ (1<<2)
/* Initialize first the XGXS and only then the phy itself */
#define FLAGS_INIT_XGXS_FIRST (1<<3)
#define FLAGS_INIT_XGXS_FIRST (1<<3)
#define FLAGS_REARM_LATCH_SIGNAL (1<<6)
#define FLAGS_SFP_NOT_APPROVED (1<<7)
u8 def_md_devad;
u8 reserved;
@ -161,6 +170,11 @@ struct bnx2x_phy {
/* Set link led mode (on/off/oper)*/
set_link_led_t set_link_led;
/* PHY Specific tasks */
phy_specific_func_t phy_specific_func;
#define DISABLE_TX 1
#define ENABLE_TX 2
};
/* Inputs parameters to the CLC */
@ -177,18 +191,18 @@ struct link_params {
#define LOOPBACK_EXT_PHY 4
#define LOOPBACK_EXT 5
u16 req_duplex;
u16 req_flow_ctrl;
u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
req_flow_ctrl is set to AUTO */
u16 req_line_speed; /* Also determine AutoNeg */
/* Device parameters */
u8 mac_addr[6];
u16 req_duplex[LINK_CONFIG_SIZE];
u16 req_flow_ctrl[LINK_CONFIG_SIZE];
u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */
/* shmem parameters */
u32 shmem_base;
u32 speed_cap_mask;
u32 shmem2_base;
u32 speed_cap_mask[LINK_CONFIG_SIZE];
u32 switch_cfg;
#define SWITCH_CFG_1G PORT_FEATURE_CON_SWITCH_1G_SWITCH
#define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH
@ -202,6 +216,7 @@ struct link_params {
u32 feature_config_flags;
#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
/* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS];
@ -210,9 +225,12 @@ struct link_params {
u8 rsrv;
u16 hw_led_mode; /* part of the hw_config read from the shmem */
u32 multi_phy_config;
/* Device pointer passed to all callback functions */
struct bnx2x *bp;
u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
req_flow_ctrl is set to AUTO */
};
/* Output parameters */
@ -233,12 +251,6 @@ struct link_vars {
u16 flow_ctrl;
u16 ieee_fc;
u32 autoneg;
#define AUTO_NEG_DISABLED 0x0
#define AUTO_NEG_ENABLED 0x1
#define AUTO_NEG_COMPLETE 0x2
#define AUTO_NEG_PARALLEL_DETECTION_USED 0x3
/* The same definitions as the shmem parameter */
u32 link_status;
};
@ -246,8 +258,6 @@ struct link_vars {
/***********************************************************/
/* Functions */
/***********************************************************/
/* Initialize the phy */
u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
/* Reset the link. Should be called when driver or interface goes down
@ -298,10 +308,11 @@ void bnx2x_handle_module_detect_int(struct link_params *params);
/* Get the actual link status. In case it returns 0, link is up,
otherwise link is down*/
u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
u8 is_serdes);
/* One-time initialization for external phy after power up */
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base);
/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
@ -316,12 +327,19 @@ u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
void bnx2x_hw_reset_phy(struct link_params *params);
/* Checks if HW lock is required for this phy/board type */
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base);
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base);
/* Returns the aggregative supported attributes of the phys on board */
u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx);
/* Check swap bit and adjust PHY order */
u32 bnx2x_phy_selection(struct link_params *params);
/* Probe the phys on board, and populate them in "params" */
u8 bnx2x_phy_probe(struct link_params *params);
/* Checks if fan failure detection is required on one of the phys on board */
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, u8 port);
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 port);
#endif /* BNX2X_LINK_H */

View File

@ -1227,26 +1227,66 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
return 0;
}
int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
{
u32 sel_phy_idx = 0;
if (bp->link_vars.link_up) {
sel_phy_idx = EXT_PHY1;
/* In case link is SERDES, check if the EXT_PHY2 is the one */
if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
(bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
sel_phy_idx = EXT_PHY2;
} else {
switch (bnx2x_phy_selection(&bp->link_params)) {
case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
sel_phy_idx = EXT_PHY1;
break;
case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
sel_phy_idx = EXT_PHY2;
break;
}
}
/*
* The selected actived PHY is always after swapping (in case PHY
* swapping is enabled). So when swapping is enabled, we need to reverse
* the configuration
*/
if (bp->link_params.multi_phy_config &
PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
if (sel_phy_idx == EXT_PHY1)
sel_phy_idx = EXT_PHY2;
else if (sel_phy_idx == EXT_PHY2)
sel_phy_idx = EXT_PHY1;
}
return LINK_CONFIG_IDX(sel_phy_idx);
}
void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
switch (bp->link_vars.ieee_fc &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
bp->port.advertising |= (ADVERTISED_Asym_Pause |
bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
bp->port.advertising |= ADVERTISED_Asym_Pause;
bp->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause;
break;
default:
bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
}
@ -1257,7 +1297,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
{
if (!BP_NOMCP(bp)) {
u8 rc;
int cfx_idx = bnx2x_get_link_cfg_idx(bp);
u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
/* Initialize link parameters structure variables */
/* It is recommended to turn off RX FC for jumbo frames
for better performance */
@ -1268,8 +1309,10 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
bnx2x_acquire_phy_lock(bp);
if (load_mode == LOAD_DIAG)
if (load_mode == LOAD_DIAG) {
bp->link_params.loopback_mode = LOOPBACK_XGXS;
bp->link_params.req_line_speed[cfx_idx] = SPEED_10000;
}
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
@ -1281,7 +1324,7 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
bnx2x_link_report(bp);
}
bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
return rc;
}
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
@ -1311,13 +1354,14 @@ static void bnx2x__link_reset(struct bnx2x *bp)
BNX2X_ERR("Bootcode is missing - can not reset link\n");
}
u8 bnx2x_link_test(struct bnx2x *bp)
u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
{
u8 rc = 0;
if (!BP_NOMCP(bp)) {
bnx2x_acquire_phy_lock(bp);
rc = bnx2x_test_link(&bp->link_params, &bp->link_vars);
rc = bnx2x_test_link(&bp->link_params, &bp->link_vars,
is_serdes);
bnx2x_release_phy_lock(bp);
} else
BNX2X_ERR("Bootcode is missing - can not test link\n");
@ -1586,7 +1630,7 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
*/
/* send the MCP a request, block until there is a reply */
u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
{
int func = BP_FUNC(bp);
u32 seq = ++bp->fw_seq;
@ -1595,6 +1639,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
mutex_lock(&bp->fw_mb_mutex);
SHMEM_WR(bp, func_mb[func].drv_mb_param, param);
SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
@ -1716,9 +1761,9 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
/* Report results to MCP */
if (dcc_event)
bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE);
bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE, 0);
else
bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK, 0);
}
/* must be called under the spq lock */
@ -3848,6 +3893,7 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
bnx2x_fan_failure_det_req(
bp,
bp->common.shmem_base,
bp->common.shmem2_base,
port);
}
@ -4116,7 +4162,8 @@ static int bnx2x_init_common(struct bnx2x *bp)
}
bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
bp->common.shmem_base);
bp->common.shmem_base,
bp->common.shmem2_base);
bnx2x_setup_fan_failure_detection(bp);
@ -4129,7 +4176,8 @@ static int bnx2x_init_common(struct bnx2x *bp)
if (!BP_NOMCP(bp)) {
bnx2x_acquire_phy_lock(bp);
bnx2x_common_init_phy(bp, bp->common.shmem_base);
bnx2x_common_init_phy(bp, bp->common.shmem_base,
bp->common.shmem2_base);
bnx2x_release_phy_lock(bp);
} else
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
@ -4265,10 +4313,10 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, MCP_BLOCK, init_stage);
bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
bp->common.shmem_base);
bp->common.shmem_base,
bp->common.shmem2_base);
if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
port)) {
bp->common.shmem2_base, port)) {
u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
val = REG_RD(bp, reg_addr);
@ -5226,7 +5274,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
unload_error:
if (!BP_NOMCP(bp))
reset_code = bnx2x_fw_command(bp, reset_code);
reset_code = bnx2x_fw_command(bp, reset_code, 0);
else {
DP(NETIF_MSG_IFDOWN, "NO MCP - load counts %d, %d, %d\n",
load_count[0], load_count[1], load_count[2]);
@ -5251,7 +5299,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
/* Report UNLOAD_DONE to MCP */
if (!BP_NOMCP(bp))
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
}
@ -5816,13 +5864,14 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
bp->fw_seq =
(SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
reset_code = bnx2x_fw_command(bp, reset_code);
reset_code = bnx2x_fw_command(bp, reset_code, 0);
/* if UNDI is loaded on the other port */
if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
/* send "DONE" for previous unload */
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
bnx2x_fw_command(bp,
DRV_MSG_CODE_UNLOAD_DONE, 0);
/* unload UNDI on port 1 */
bp->func = 1;
@ -5831,7 +5880,7 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
DRV_MSG_SEQ_NUMBER_MASK);
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
bnx2x_fw_command(bp, reset_code);
bnx2x_fw_command(bp, reset_code, 0);
}
/* now it's safe to release the lock */
@ -5873,7 +5922,7 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
/* send unload done to the MCP */
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
/* restore our func and fw_seq */
bp->func = func;
@ -5921,6 +5970,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0);
bp->link_params.shmem_base = bp->common.shmem_base;
bp->link_params.shmem2_base = bp->common.shmem2_base;
BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n",
bp->common.shmem_base, bp->common.shmem2_base);
@ -5963,8 +6013,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
"please upgrade BC\n", BNX2X_BC_VER, val);
}
bp->link_params.feature_config_flags |=
(val >= REQ_BC_VER_4_VRFY_OPT_MDL) ?
(val >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL) ?
FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
bp->link_params.feature_config_flags |=
(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
if (BP_E1HVN(bp) == 0) {
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
@ -5988,22 +6041,44 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
u32 switch_cfg)
{
int port = BP_PORT(bp);
bp->port.supported = 0;
int cfg_size = 0, idx, port = BP_PORT(bp);
/* Aggregation of supported attributes of all external phys */
bp->port.supported[0] = 0;
bp->port.supported[1] = 0;
switch (bp->link_params.num_phys) {
case 1:
bp->port.supported = bp->link_params.phy[INT_PHY].supported;
break;
bp->port.supported[0] = bp->link_params.phy[INT_PHY].supported;
cfg_size = 1;
break;
case 2:
bp->port.supported = bp->link_params.phy[EXT_PHY1].supported;
break;
bp->port.supported[0] = bp->link_params.phy[EXT_PHY1].supported;
cfg_size = 1;
break;
case 3:
if (bp->link_params.multi_phy_config &
PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
bp->port.supported[1] =
bp->link_params.phy[EXT_PHY1].supported;
bp->port.supported[0] =
bp->link_params.phy[EXT_PHY2].supported;
} else {
bp->port.supported[0] =
bp->link_params.phy[EXT_PHY1].supported;
bp->port.supported[1] =
bp->link_params.phy[EXT_PHY2].supported;
}
cfg_size = 2;
break;
}
if (!(bp->port.supported)) {
if (!(bp->port.supported[0] || bp->port.supported[1])) {
BNX2X_ERR("NVRAM config error. BAD phy config."
"PHY1 config 0x%x\n",
"PHY1 config 0x%x, PHY2 config 0x%x\n",
SHMEM_RD(bp,
dev_info.port_hw_config[port].external_phy_config));
dev_info.port_hw_config[port].external_phy_config),
SHMEM_RD(bp,
dev_info.port_hw_config[port].external_phy_config2));
return;
}
@ -6023,147 +6098,183 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
default:
BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
bp->port.link_config);
bp->port.link_config[0]);
return;
}
/* mask what we support according to speed_cap_mask */
if (!(bp->link_params.speed_cap_mask &
/* mask what we support according to speed_cap_mask per configuration */
for (idx = 0; idx < cfg_size; idx++) {
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
bp->port.supported &= ~SUPPORTED_10baseT_Half;
bp->port.supported[idx] &= ~SUPPORTED_10baseT_Half;
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
bp->port.supported &= ~SUPPORTED_10baseT_Full;
bp->port.supported[idx] &= ~SUPPORTED_10baseT_Full;
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
bp->port.supported &= ~SUPPORTED_100baseT_Half;
bp->port.supported[idx] &= ~SUPPORTED_100baseT_Half;
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
bp->port.supported &= ~SUPPORTED_100baseT_Full;
bp->port.supported[idx] &= ~SUPPORTED_100baseT_Full;
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
bp->port.supported &= ~(SUPPORTED_1000baseT_Half |
bp->port.supported[idx] &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
bp->port.supported &= ~SUPPORTED_2500baseX_Full;
bp->port.supported[idx] &= ~SUPPORTED_2500baseX_Full;
if (!(bp->link_params.speed_cap_mask &
if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
bp->port.supported &= ~SUPPORTED_10000baseT_Full;
bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full;
BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported);
}
BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0],
bp->port.supported[1]);
}
static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
{
bp->link_params.req_duplex = DUPLEX_FULL;
switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) {
u32 link_config, idx, cfg_size = 0;
bp->port.advertising[0] = 0;
bp->port.advertising[1] = 0;
switch (bp->link_params.num_phys) {
case 1:
case 2:
cfg_size = 1;
break;
case 3:
cfg_size = 2;
break;
}
for (idx = 0; idx < cfg_size; idx++) {
bp->link_params.req_duplex[idx] = DUPLEX_FULL;
link_config = bp->port.link_config[idx];
switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
case PORT_FEATURE_LINK_SPEED_AUTO:
if (bp->port.supported & SUPPORTED_Autoneg) {
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
bp->port.advertising = bp->port.supported;
if (bp->port.supported[idx] & SUPPORTED_Autoneg) {
bp->link_params.req_line_speed[idx] =
SPEED_AUTO_NEG;
bp->port.advertising[idx] |=
bp->port.supported[idx];
} else {
/* force 10G, no AN */
bp->link_params.req_line_speed = SPEED_10000;
bp->port.advertising = (ADVERTISED_10000baseT_Full |
/* force 10G, no AN */
bp->link_params.req_line_speed[idx] =
SPEED_10000;
bp->port.advertising[idx] |=
(ADVERTISED_10000baseT_Full |
ADVERTISED_FIBRE);
continue;
}
break;
case PORT_FEATURE_LINK_SPEED_10M_FULL:
if (bp->port.supported & SUPPORTED_10baseT_Full) {
bp->link_params.req_line_speed = SPEED_10;
bp->port.advertising = (ADVERTISED_10baseT_Full |
if (bp->port.supported[idx] & SUPPORTED_10baseT_Full) {
bp->link_params.req_line_speed[idx] =
SPEED_10;
bp->port.advertising[idx] |=
(ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_10M_HALF:
if (bp->port.supported & SUPPORTED_10baseT_Half) {
bp->link_params.req_line_speed = SPEED_10;
bp->link_params.req_duplex = DUPLEX_HALF;
bp->port.advertising = (ADVERTISED_10baseT_Half |
if (bp->port.supported[idx] & SUPPORTED_10baseT_Half) {
bp->link_params.req_line_speed[idx] =
SPEED_10;
bp->link_params.req_duplex[idx] =
DUPLEX_HALF;
bp->port.advertising[idx] |=
(ADVERTISED_10baseT_Half |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_100M_FULL:
if (bp->port.supported & SUPPORTED_100baseT_Full) {
bp->link_params.req_line_speed = SPEED_100;
bp->port.advertising = (ADVERTISED_100baseT_Full |
if (bp->port.supported[idx] & SUPPORTED_100baseT_Full) {
bp->link_params.req_line_speed[idx] =
SPEED_100;
bp->port.advertising[idx] |=
(ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_100M_HALF:
if (bp->port.supported & SUPPORTED_100baseT_Half) {
bp->link_params.req_line_speed = SPEED_100;
bp->link_params.req_duplex = DUPLEX_HALF;
bp->port.advertising = (ADVERTISED_100baseT_Half |
if (bp->port.supported[idx] & SUPPORTED_100baseT_Half) {
bp->link_params.req_line_speed[idx] = SPEED_100;
bp->link_params.req_duplex[idx] = DUPLEX_HALF;
bp->port.advertising[idx] |=
(ADVERTISED_100baseT_Half |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_1G:
if (bp->port.supported & SUPPORTED_1000baseT_Full) {
bp->link_params.req_line_speed = SPEED_1000;
bp->port.advertising = (ADVERTISED_1000baseT_Full |
if (bp->port.supported[idx] &
SUPPORTED_1000baseT_Full) {
bp->link_params.req_line_speed[idx] =
SPEED_1000;
bp->port.advertising[idx] |=
(ADVERTISED_1000baseT_Full |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_2_5G:
if (bp->port.supported & SUPPORTED_2500baseX_Full) {
bp->link_params.req_line_speed = SPEED_2500;
bp->port.advertising = (ADVERTISED_2500baseX_Full |
if (bp->port.supported[idx] &
SUPPORTED_2500baseX_Full) {
bp->link_params.req_line_speed[idx] =
SPEED_2500;
bp->port.advertising[idx] |=
(ADVERTISED_2500baseX_Full |
ADVERTISED_TP);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
@ -6171,16 +6282,19 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
case PORT_FEATURE_LINK_SPEED_10G_CX4:
case PORT_FEATURE_LINK_SPEED_10G_KX4:
case PORT_FEATURE_LINK_SPEED_10G_KR:
if (bp->port.supported & SUPPORTED_10000baseT_Full) {
bp->link_params.req_line_speed = SPEED_10000;
bp->port.advertising = (ADVERTISED_10000baseT_Full |
if (bp->port.supported[idx] &
SUPPORTED_10000baseT_Full) {
bp->link_params.req_line_speed[idx] =
SPEED_10000;
bp->port.advertising[idx] |=
(ADVERTISED_10000baseT_Full |
ADVERTISED_FIBRE);
} else {
BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
bp->port.link_config,
bp->link_params.speed_cap_mask);
link_config,
bp->link_params.speed_cap_mask[idx]);
return;
}
break;
@ -6188,23 +6302,28 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
default:
BNX2X_ERROR("NVRAM config error. "
"BAD link speed link_config 0x%x\n",
bp->port.link_config);
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
bp->port.advertising = bp->port.supported;
link_config);
bp->link_params.req_line_speed[idx] = SPEED_AUTO_NEG;
bp->port.advertising[idx] = bp->port.supported[idx];
break;
}
bp->link_params.req_flow_ctrl = (bp->port.link_config &
bp->link_params.req_flow_ctrl[idx] = (link_config &
PORT_FEATURE_FLOW_CONTROL_MASK);
if ((bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
!(bp->port.supported & SUPPORTED_Autoneg))
bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
if ((bp->link_params.req_flow_ctrl[idx] ==
BNX2X_FLOW_CTRL_AUTO) &&
!(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
bp->link_params.req_flow_ctrl[idx] =
BNX2X_FLOW_CTRL_NONE;
}
BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x"
" advertising 0x%x\n",
bp->link_params.req_line_speed,
bp->link_params.req_duplex,
bp->link_params.req_flow_ctrl, bp->port.advertising);
BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl"
" 0x%x advertising 0x%x\n",
bp->link_params.req_line_speed[idx],
bp->link_params.req_duplex[idx],
bp->link_params.req_flow_ctrl[idx],
bp->port.advertising[idx]);
}
}
static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
@ -6228,14 +6347,20 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->link_params.lane_config =
SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
bp->link_params.speed_cap_mask =
bp->link_params.speed_cap_mask[0] =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask);
bp->port.link_config =
bp->link_params.speed_cap_mask[1] =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask2);
bp->port.link_config[0] =
SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
bp->port.link_config[1] =
SHMEM_RD(bp, dev_info.port_feature_config[port].link_config2);
bp->link_params.multi_phy_config =
SHMEM_RD(bp, dev_info.port_hw_config[port].multi_phy_config);
/* If the device is capable of WoL, set the default state according
* to the HW
*/
@ -6244,11 +6369,12 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
(config & PORT_FEATURE_WOL_ENABLED));
BNX2X_DEV_INFO("lane_config 0x%08x"
" speed_cap_mask 0x%08x link_config 0x%08x\n",
"speed_cap_mask0 0x%08x link_config0 0x%08x\n",
bp->link_params.lane_config,
bp->link_params.speed_cap_mask, bp->port.link_config);
bp->link_params.speed_cap_mask[0],
bp->port.link_config[0]);
bp->link_params.switch_cfg |= (bp->port.link_config &
bp->link_params.switch_cfg = (bp->port.link_config[0] &
PORT_FEATURE_CONNECTED_SWITCH_MASK);
bnx2x_phy_probe(&bp->link_params);
bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);

View File

@ -4964,6 +4964,8 @@
#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN 0x0001
#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 0x0040
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1 0x14
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII 0x0001
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK 0x0002
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX 0x0004
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK 0x0018
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 3
@ -5192,6 +5194,8 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_XS_8706_REG_BANK_RX3 0x80ec
#define MDIO_XS_8706_REG_BANK_RXA 0x80fc
#define MDIO_XS_REG_8073_RX_CTRL_PCIE 0x80FA
#define MDIO_AN_DEVAD 0x7
/*ieee*/
#define MDIO_AN_REG_CTRL 0x0000
@ -5227,6 +5231,27 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_AN_REG_8481_AUX_CTRL 0xfff8
#define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc
/* BCM84823 only */
#define MDIO_CTL_DEVAD 0x1e
#define MDIO_CTL_REG_84823_MEDIA 0x401a
#define MDIO_CTL_REG_84823_MEDIA_MAC_MASK 0x0018
/* These pins configure the BCM84823 interface to MAC after reset. */
#define MDIO_CTL_REG_84823_CTRL_MAC_XFI 0x0008
#define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M 0x0010
/* These pins configure the BCM84823 interface to Line after reset. */
#define MDIO_CTL_REG_84823_MEDIA_LINE_MASK 0x0060
#define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L 0x0020
#define MDIO_CTL_REG_84823_MEDIA_LINE_XFI 0x0040
/* When this pin is active high during reset, 10GBASE-T core is power
* down, When it is active low the 10GBASE-T is power up
*/
#define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN 0x0080
#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK 0x0100
#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER 0x0000
#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER 0x0100
#define MDIO_CTL_REG_84823_MEDIA_FIBER_1G 0x1000
#define IGU_FUNC_BASE 0x0400
#define IGU_ADDR_MSIX 0x0000