bnx2x: Fix port type display
authorYaniv Rosner <yanivr@broadcom.com>
Tue, 31 May 2011 21:26:11 +0000 (21:26 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 Jun 2011 20:10:55 +0000 (13:10 -0700)
Display the current media type connected to the port in ethtool.

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>
drivers/net/bnx2x/bnx2x.h
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bnx2x/bnx2x_cmn.h
drivers/net/bnx2x/bnx2x_ethtool.c
drivers/net/bnx2x/bnx2x_hsi.h
drivers/net/bnx2x/bnx2x_link.c
drivers/net/bnx2x/bnx2x_link.h
drivers/net/bnx2x/bnx2x_main.c

index 668a578c49e9bf5f00fa723703fd73e9fda58744..480e02df86eed6413bbac6c3bd190d2b67b8ae5f 100644 (file)
@@ -1492,7 +1492,7 @@ void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
 void bnx2x_invalidate_uc_list(struct bnx2x *bp);
 
 void bnx2x_update_coalesce(struct bnx2x *bp);
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
 
 static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
                           int wait)
index 289044332ed8127f27990341114777dfd1376344..9b248348c0e6aa3a9fff94d4fd7c6e9677b11821 100644 (file)
@@ -2803,6 +2803,55 @@ static int bnx2x_reload_if_running(struct net_device *dev)
        return bnx2x_nic_load(bp, LOAD_NORMAL);
 }
 
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
+{
+       u32 sel_phy_idx = 0;
+       if (bp->link_params.num_phys <= 1)
+               return INT_PHY;
+
+       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;
+               }
+       }
+
+       return sel_phy_idx;
+
+}
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+       u32 sel_phy_idx = bnx2x_get_cur_phy_idx(bp);
+       /*
+        * 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);
+}
+
 /* called with rtnl_lock */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 {
index 1a3545bd8a929df5fd1a28b8fac03b21be8bc79c..19f8638ed516e0b4c39632e8cfd22fcf6d023ca9 100644 (file)
@@ -1063,6 +1063,8 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
 }
 #endif
 
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+
 static inline void __storm_memset_struct(struct bnx2x *bp,
                                         u32 addr, size_t size, u32 *data)
 {
index 727fe89ff37f5c970aaee4df2d1d069b31357828..2957353f7c2c20fe4c700432eb63d35110011ca1 100644 (file)
@@ -162,6 +162,33 @@ static const struct {
 };
 
 #define BNX2X_NUM_STATS                ARRAY_SIZE(bnx2x_stats_arr)
+static int bnx2x_get_port_type(struct bnx2x *bp)
+{
+       int port_type;
+       u32 phy_idx = bnx2x_get_cur_phy_idx(bp);
+       switch (bp->link_params.phy[phy_idx].media_type) {
+       case ETH_PHY_SFP_FIBER:
+       case ETH_PHY_XFP_FIBER:
+       case ETH_PHY_KR:
+       case ETH_PHY_CX4:
+               port_type = PORT_FIBRE;
+               break;
+       case ETH_PHY_DA_TWINAX:
+               port_type = PORT_DA;
+               break;
+       case ETH_PHY_BASE_T:
+               port_type = PORT_TP;
+               break;
+       case ETH_PHY_NOT_PRESENT:
+               port_type = PORT_NONE;
+               break;
+       case ETH_PHY_UNSPECIFIED:
+       default:
+               port_type = PORT_OTHER;
+               break;
+       }
+       return port_type;
+}
 
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -188,12 +215,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (IS_MF(bp))
                ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
 
-       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->port = bnx2x_get_port_type(bp);
 
        cmd->phy_address = bp->mdio.prtad;
        cmd->transceiver = XCVR_INTERNAL;
index 6ee6160ce95d20fedb67bf8e8667c979fbdabb42..5bfdbcc94a7c0338cfd363ef7495db66e2bece9c 100644 (file)
@@ -263,7 +263,17 @@ struct port_hw_cfg {                           /* port 0: 0x12c  port 1: 0x2bc */
 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2                   0x00000200
 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3                   0x00000300
 #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED                0x00000400
-       u32 Reserved01[12];                                 /* 0x158 */
+       u32 Reserved01[11];                                 /* 0x158 */
+
+       u32 media_type;                                 /* 0x194 */
+#define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK                     0x000000FF
+#define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT                    0
+
+#define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK                     0x0000FF00
+#define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT                    8
+
+#define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK                     0x00FF0000
+#define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT                    16
        /*  for external PHY, or forced mode or during AN */
        u16 xgxs_config_rx[4];                              /* 0x198 */
 
index 56b5ed8f63425d6b54ad3b634af7ad8546ff45a6..8a7d7d6b1ddf20f6322d6f3b1bcf3e8901fcc232 100644 (file)
@@ -1618,7 +1618,7 @@ void bnx2x_link_status_update(struct link_params *params,
        struct bnx2x *bp = params->bp;
        u8 link_10g;
        u8 port = params->port;
-
+       u32 sync_offset, media_types;
        vars->link_status = REG_RD(bp, params->shmem_base +
                                   offsetof(struct shmem_region,
                                            port_mb[port].link_status));
@@ -1731,6 +1731,23 @@ void bnx2x_link_status_update(struct link_params *params,
                vars->mac_type = MAC_TYPE_NONE;
        }
 
+       /* Sync media type */
+       sync_offset = params->shmem_base +
+                       offsetof(struct shmem_region,
+                                dev_info.port_hw_config[port].media_type);
+       media_types = REG_RD(bp, sync_offset);
+
+       params->phy[INT_PHY].media_type =
+               (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
+               PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
+       params->phy[EXT_PHY1].media_type =
+               (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
+               PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
+       params->phy[EXT_PHY2].media_type =
+               (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
+               PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
+       DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
+
        DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
                 vars->link_status, vars->phy_link_up);
        DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
@@ -3247,7 +3264,9 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
                        serdes_phy_type = ((params->phy[phy_index].media_type ==
                                            ETH_PHY_SFP_FIBER) ||
                                           (params->phy[phy_index].media_type ==
-                                           ETH_PHY_XFP_FIBER));
+                                           ETH_PHY_XFP_FIBER) ||
+                                          (params->phy[phy_index].media_type ==
+                                           ETH_PHY_DA_TWINAX));
 
                        if (is_serdes != serdes_phy_type)
                                continue;
@@ -4679,9 +4698,11 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                             u16 *edc_mode)
 {
        struct bnx2x *bp = params->bp;
+       u32 sync_offset = 0, phy_idx, media_types;
        u8 val, check_limiting_mode = 0;
        *edc_mode = EDC_MODE_LIMITING;
 
+       phy->media_type = ETH_PHY_UNSPECIFIED;
        /* First check for copper cable */
        if (bnx2x_read_sfp_module_eeprom(phy,
                                         params,
@@ -4696,7 +4717,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
        case SFP_EEPROM_CON_TYPE_VAL_COPPER:
        {
                u8 copper_module_type;
-
+               phy->media_type = ETH_PHY_DA_TWINAX;
                /*
                 * Check if its active cable (includes SFP+ module)
                 * of passive cable
@@ -4731,6 +4752,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                break;
        }
        case SFP_EEPROM_CON_TYPE_VAL_LC:
+               phy->media_type = ETH_PHY_SFP_FIBER;
                DP(NETIF_MSG_LINK, "Optic module detected\n");
                check_limiting_mode = 1;
                break;
@@ -4739,7 +4761,22 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                         val);
                return -EINVAL;
        }
-
+       sync_offset = params->shmem_base +
+               offsetof(struct shmem_region,
+                        dev_info.port_hw_config[params->port].media_type);
+       media_types = REG_RD(bp, sync_offset);
+       /* Update media type for non-PMF sync */
+       for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+               if (&(params->phy[phy_idx]) == phy) {
+                       media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+                               (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+                       media_types |= ((phy->media_type &
+                                       PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+                               (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+                       break;
+               }
+       }
+       REG_WR(bp, sync_offset, media_types);
        if (check_limiting_mode) {
                u8 options[SFP_EEPROM_OPTIONS_SIZE];
                if (bnx2x_read_sfp_module_eeprom(phy,
@@ -5156,6 +5193,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                 * Module was plugged out.
                 * Disable transmit for this module
                 */
+               phy->media_type = ETH_PHY_NOT_PRESENT;
                if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
                        bnx2x_sfp_set_transmitter(params, phy, 0);
@@ -5764,7 +5802,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
                /* Module is absent */
                DP(NETIF_MSG_LINK, "MOD_ABS indication "
                            "show module is absent\n");
-
+               phy->media_type = ETH_PHY_NOT_PRESENT;
                /*
                 * 1. Set mod_abs to detect next module
                 *    presence event
@@ -6877,7 +6915,7 @@ static struct bnx2x_phy phy_serdes = {
                           SUPPORTED_Autoneg |
                           SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
-       .media_type     = ETH_PHY_UNSPECIFIED,
+       .media_type     = ETH_PHY_BASE_T,
        .ver_addr       = 0,
        .req_flow_ctrl  = 0,
        .req_line_speed = 0,
@@ -6914,7 +6952,7 @@ static struct bnx2x_phy phy_xgxs = {
                           SUPPORTED_Autoneg |
                           SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
-       .media_type     = ETH_PHY_UNSPECIFIED,
+       .media_type     = ETH_PHY_CX4,
        .ver_addr       = 0,
        .req_flow_ctrl  = 0,
        .req_line_speed = 0,
@@ -6977,7 +7015,7 @@ static struct bnx2x_phy phy_8073 = {
                           SUPPORTED_Autoneg |
                           SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
-       .media_type     = ETH_PHY_UNSPECIFIED,
+       .media_type     = ETH_PHY_KR,
        .ver_addr       = 0,
        .req_flow_ctrl  = 0,
        .req_line_speed = 0,
@@ -7069,7 +7107,7 @@ static struct bnx2x_phy phy_8726 = {
                           SUPPORTED_FIBRE |
                           SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
-       .media_type     = ETH_PHY_SFP_FIBER,
+       .media_type     = ETH_PHY_NOT_PRESENT,
        .ver_addr       = 0,
        .req_flow_ctrl  = 0,
        .req_line_speed = 0,
@@ -7100,7 +7138,7 @@ static struct bnx2x_phy phy_8727 = {
                           SUPPORTED_FIBRE |
                           SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
-       .media_type     = ETH_PHY_SFP_FIBER,
+       .media_type     = ETH_PHY_NOT_PRESENT,
        .ver_addr       = 0,
        .req_flow_ctrl  = 0,
        .req_line_speed = 0,
@@ -7565,7 +7603,7 @@ u32 bnx2x_phy_selection(struct link_params *params)
 u8 bnx2x_phy_probe(struct link_params *params)
 {
        u8 phy_index, actual_phy_idx, link_cfg_idx;
-       u32 phy_config_swapped;
+       u32 phy_config_swapped, sync_offset, media_types;
        struct bnx2x *bp = params->bp;
        struct bnx2x_phy *phy;
        params->num_phys = 0;
@@ -7602,6 +7640,26 @@ u8 bnx2x_phy_probe(struct link_params *params)
                if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
                        break;
 
+               sync_offset = params->shmem_base +
+                       offsetof(struct shmem_region,
+                       dev_info.port_hw_config[params->port].media_type);
+               media_types = REG_RD(bp, sync_offset);
+
+               /*
+                * Update media type for non-PMF sync only for the first time
+                * In case the media type changes afterwards, it will be updated
+                * using the update_status function
+                */
+               if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+                                   (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+                                    actual_phy_idx))) == 0) {
+                       media_types |= ((phy->media_type &
+                                       PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+                               (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+                                actual_phy_idx));
+               }
+               REG_WR(bp, sync_offset, media_types);
+
                bnx2x_phy_def_cfg(params, phy, phy_index);
                params->num_phys++;
        }
index 92f36b6950dc22246b94b0dde53d79c77e8713d0..ac348daae2f220ae5c7d4a8bfb57bb1878b50ae3 100644 (file)
@@ -153,6 +153,8 @@ struct bnx2x_phy {
 #define        ETH_PHY_XFP_FIBER   0x2
 #define        ETH_PHY_DA_TWINAX   0x3
 #define        ETH_PHY_BASE_T      0x4
+#define        ETH_PHY_KR          0xf0
+#define        ETH_PHY_CX4         0xf1
 #define        ETH_PHY_NOT_PRESENT 0xff
 
        /* The address in which version is located*/
index 4b70311a11ef9f4a3ff5b631585f0d8bded19984..c6591c46ebdf298dbe80dff6c818310d09e72eeb 100644 (file)
@@ -1732,45 +1732,6 @@ 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);