#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
        bnx2x_cl45_write(_bp, _phy, \
-               DEFAULT_PHY_DEV_ADDR, \
+               (_phy)->def_md_devad, \
                (_bank + (_addr & 0xf)), \
                _val)
 
 #define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
        bnx2x_cl45_read(_bp, _phy, \
-               DEFAULT_PHY_DEV_ADDR, \
+               (_phy)->def_md_devad, \
                (_bank + (_addr & 0xf)), \
                _val)
 
                                break;
                }
 
+               vars->flow_ctrl = 0;
                if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
                        vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
-               else
-                       vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
 
                if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
                        vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
-               else
-                       vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
 
-               if (vars->phy_flags & PHY_XGXS_FLAG) {
-                       if (vars->line_speed &&
-                           ((vars->line_speed == SPEED_10) ||
-                            (vars->line_speed == SPEED_100))) {
-                               vars->phy_flags |= PHY_SGMII_FLAG;
-                       } else {
-                               vars->phy_flags &= ~PHY_SGMII_FLAG;
-                       }
+               if (!vars->flow_ctrl)
+                       vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+               if (vars->line_speed &&
+                   ((vars->line_speed == SPEED_10) ||
+                    (vars->line_speed == SPEED_100))) {
+                       vars->phy_flags |= PHY_SGMII_FLAG;
+               } else {
+                       vars->phy_flags &= ~PHY_SGMII_FLAG;
                }
 
                /* anything 10 and over uses the bmac */
                              MDIO_REG_BANK_SERDES_DIGITAL,
                              MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
                              &control2);
-       if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+       if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
                control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
        else
                control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
-       DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n",
-               params->speed_cap_mask, control2);
+       DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
+               phy->speed_cap_mask, control2);
        CL45_WR_OVER_CL22(bp, phy,
                              MDIO_REG_BANK_SERDES_DIGITAL,
                              MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
                                              MDIO_REG_BANK_CL73_IEEEB1,
                                              MDIO_CL73_IEEEB1_AN_ADV2,
                                              ®_val);
-               if (params->speed_cap_mask &
+               if (phy->speed_cap_mask &
                    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
                        reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
-               if (params->speed_cap_mask &
+               if (phy->speed_cap_mask &
                    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
                        reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
 
        reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
                     MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
                     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
-       if (params->req_duplex == DUPLEX_FULL)
+       if (phy->req_duplex == DUPLEX_FULL)
                reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
        CL45_WR_OVER_CL22(bp, phy,
                              MDIO_REG_BANK_COMBO_IEEE0,
        /* configure the 48 bits for BAM AN */
 
        /* set extended capabilities */
-       if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
+       if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
                val |= MDIO_OVER_1G_UP1_2_5G;
-       if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+       if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
                val |= MDIO_OVER_1G_UP1_10G;
        CL45_WR_OVER_CL22(bp, phy,
                              MDIO_REG_BANK_OVER_1G,
        /* resolve pause mode and advertisement
         * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
 
-       switch (params->req_flow_ctrl) {
+       switch (phy->req_flow_ctrl) {
        case BNX2X_FLOW_CTRL_AUTO:
                if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
                        *ieee_fc |=
                }
 
                /* setting the full duplex */
-               if (params->req_duplex == DUPLEX_FULL)
+               if (phy->req_duplex == DUPLEX_FULL)
                        mii_control |=
                                MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
                CL45_WR_OVER_CL22(bp, phy,
        default:
                break;
        }
+       if (pause_result & (1<<0))
+               vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+       if (pause_result & (1<<1))
+               vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+
 }
 
 static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u16 ld_pause;           /* local */
        u16 lp_pause;           /* link partner */
-       u16 an_complete;        /* AN complete */
        u16 pause_result;
        u8 ret = 0;
        /* read twice */
 
-       bnx2x_cl45_read(bp, phy,
-                     MDIO_AN_DEVAD,
-                     MDIO_AN_REG_STATUS, &an_complete);
-       bnx2x_cl45_read(bp, phy,
-                     MDIO_AN_DEVAD,
-                     MDIO_AN_REG_STATUS, &an_complete);
+       vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 
-       if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
+       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+               vars->flow_ctrl = phy->req_flow_ctrl;
+       else if (phy->req_line_speed != SPEED_AUTO_NEG)
+               vars->flow_ctrl = params->req_fc_auto_adv;
+       else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
                ret = 1;
                bnx2x_cl45_read(bp, phy,
                              MDIO_AN_DEVAD,
                DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
                   pause_result);
                bnx2x_pause_resolve(vars, pause_result);
-               if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
-                    phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-                       bnx2x_cl45_read(bp, phy,
-                                     MDIO_AN_DEVAD,
-                                     MDIO_AN_REG_CL37_FC_LD, &ld_pause);
-
-                       bnx2x_cl45_read(bp, phy,
-                                     MDIO_AN_DEVAD,
-                                     MDIO_AN_REG_CL37_FC_LP, &lp_pause);
-                       pause_result = (ld_pause &
-                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
-                       pause_result |= (lp_pause &
-                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
-
-                       bnx2x_pause_resolve(vars, pause_result);
-                       DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
-                                pause_result);
-               }
        }
        return ret;
 }
 {
        struct bnx2x *bp = params->bp;
        u16 pd_10g, status2_1000x;
+       if (phy->req_line_speed != SPEED_AUTO_NEG)
+               return 0;
        CL45_RD_OVER_CL22(bp, phy,
                              MDIO_REG_BANK_SERDES_DIGITAL,
                              MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 
        /* resolve from gp_status in case of AN complete and not sgmii */
-       if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
-           (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
-           (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
-           (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
+       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+               vars->flow_ctrl = phy->req_flow_ctrl;
+       else if (phy->req_line_speed != SPEED_AUTO_NEG)
+               vars->flow_ctrl = params->req_fc_auto_adv;
+       else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
+                (!(vars->phy_flags & PHY_SGMII_FLAG))) {
                if (bnx2x_direct_parallel_detect_used(phy, params)) {
                        vars->flow_ctrl = params->req_fc_auto_adv;
                        return;
                                 pause_result);
                }
                bnx2x_pause_resolve(vars, pause_result);
-       } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
-                  (bnx2x_ext_phy_resolve_fc(phy, params, vars))) {
-               return;
-       } else {
-               if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
-                       vars->flow_ctrl = params->req_fc_auto_adv;
-               else
-                       vars->flow_ctrl = params->req_flow_ctrl;
        }
        DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
 }
        bnx2x_restart_autoneg(phy, params, 0);
        DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
 }
+
+static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
+                                 struct link_params *params,
+                                 struct link_vars *vars,
+                                 u32 gp_status)
+{
+       if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
+               vars->link_status |=
+                       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+       if (bnx2x_direct_parallel_detect_used(phy, params))
+               vars->link_status |=
+                       LINK_STATUS_PARALLEL_DETECTION_USED;
+}
+
 static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
                                     struct link_params *params,
                                     struct link_vars *vars)
                                MDIO_REG_BANK_GP_STATUS,
                                MDIO_GP_STATUS_TOP_AN_STATUS1,
                                &gp_status);
-
+       if (phy->req_line_speed == SPEED_AUTO_NEG)
+               vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
        if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
                DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
                         gp_status);
                else
                        vars->duplex = DUPLEX_HALF;
 
-               bnx2x_flow_ctrl_resolve(¶ms->phy[INT_PHY],
-                                       params, vars, gp_status);
+               if (SINGLE_MEDIA_DIRECT(params)) {
+                       bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+                       if (phy->req_line_speed == SPEED_AUTO_NEG)
+                               bnx2x_xgxs_an_resolve(phy, params, vars,
+                                                     gp_status);
+               }
 
                switch (gp_status & GP_STATUS_SPEED_MASK) {
                case GP_STATUS_10M:
                                LINK_STATUS_PARALLEL_DETECTION_USED;
 
                }
-               if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-                       vars->link_status |=
-                               LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
-
-               if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-                       vars->link_status |=
-                               LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
-
 
        } else { /* link_down */
                DP(NETIF_MSG_LINK, "phy link down\n");
        val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
 
        /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-
+       bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
        if ((vars->ieee_fc &
            MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
            MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
        return bnx2x_848xx_cmn_config_init(phy, params, vars);
 }
+
+
+static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
+                                      struct bnx2x_phy *phy,
+                                      struct link_vars *vars)
+{
+       u16 val;
+       bnx2x_cl45_read(bp, phy,
+                       MDIO_AN_DEVAD,
+                       MDIO_AN_REG_STATUS, &val);
+       bnx2x_cl45_read(bp, phy,
+                       MDIO_AN_DEVAD,
+                       MDIO_AN_REG_STATUS, &val);
+       if (val & (1<<5))
+               vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+       if ((val & (1<<0)) == 0)
+               vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
+}
 static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        return link_up;
 }
 
+static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
+                                 struct link_params *params,
+                                 struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       if (phy->req_line_speed == SPEED_10 ||
+           phy->req_line_speed == SPEED_100) {
+               vars->flow_ctrl = phy->req_flow_ctrl;
+               return;
+       }
+
+       if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
+           (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
+               u16 pause_result;
+               u16 ld_pause;           /* local */
+               u16 lp_pause;           /* link partner */
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_AN_DEVAD,
+                               MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_AN_DEVAD,
+                               MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+               pause_result = (ld_pause &
+                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
+               pause_result |= (lp_pause &
+                                MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
+
+               bnx2x_pause_resolve(vars, pause_result);
+               DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
+                          pause_result);
+       }
+}
+
 static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
                                 struct link_params *params,
                                 struct link_vars *vars)
                           params->port);
        }
 
+       if (link_up) {
+               bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+               bnx2x_8073_resolve_fc(phy, params, vars);
+       }
        return link_up;
 }
 
                vars->line_speed = SPEED_10000;
                DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
                           val2, (val2 & (1<<14)));
+               bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+               bnx2x_ext_phy_resolve_fc(phy, params, vars);
        }
        return link_up;
 }
        if (val2 & (1<<11)) {
                vars->line_speed = SPEED_10000;
                link_up = 1;
+               bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
        } else { /* Check Legacy speed link */
                u16 legacy_status, legacy_speed;
 
                                        LINK_STATUS_PARALLEL_DETECTION_USED;
                }
        }
+       if (link_up) {
+               DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
+                          vars->line_speed);
+               bnx2x_ext_phy_resolve_fc(phy, params, vars);
+       }
+
        return link_up;
 }
 static void bnx2x_link_int_enable(struct link_params *params)
        u8 rc = 0;
 
        vars->link_status |= LINK_STATUS_LINK_UP;
+       if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+               vars->link_status |=
+                       LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
+
+       if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+               vars->link_status |=
+                       LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
        if (link_10g) {
                bnx2x_bmac_enable(params, vars, 0);
                bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);