aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/bnx2x.h3
-rw-r--r--drivers/net/bnx2x_main.c121
3 files changed, 88 insertions, 37 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9948fa232220..29935a9fb1a2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2722,6 +2722,7 @@ config BNX2X
2722 select FW_LOADER 2722 select FW_LOADER
2723 select ZLIB_INFLATE 2723 select ZLIB_INFLATE
2724 select LIBCRC32C 2724 select LIBCRC32C
2725 select MDIO
2725 help 2726 help
2726 This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards. 2727 This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
2727 To compile this driver as a module, choose M here: the module 2728 To compile this driver as a module, choose M here: the module
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index 5864ae2faabc..903c89d8518a 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -30,6 +30,8 @@
30#define BNX2X_NEW_NAPI 30#define BNX2X_NEW_NAPI
31 31
32 32
33
34#include <linux/mdio.h>
33#include "bnx2x_reg.h" 35#include "bnx2x_reg.h"
34#include "bnx2x_fw_defs.h" 36#include "bnx2x_fw_defs.h"
35#include "bnx2x_hsi.h" 37#include "bnx2x_hsi.h"
@@ -895,6 +897,7 @@ struct bnx2x {
895 897
896 struct link_params link_params; 898 struct link_params link_params;
897 struct link_vars link_vars; 899 struct link_vars link_vars;
900 struct mdio_if_info mdio;
898 901
899 struct bnx2x_common common; 902 struct bnx2x_common common;
900 struct bnx2x_port port; 903 struct bnx2x_port port;
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index a695e7f0647c..145866764d46 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -8331,6 +8331,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
8331 u32 val, val2; 8331 u32 val, val2;
8332 u32 config; 8332 u32 config;
8333 u16 i; 8333 u16 i;
8334 u32 ext_phy_type;
8334 8335
8335 bp->link_params.bp = bp; 8336 bp->link_params.bp = bp;
8336 bp->link_params.port = port; 8337 bp->link_params.port = port;
@@ -8390,6 +8391,21 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
8390 8391
8391 bnx2x_link_settings_requested(bp); 8392 bnx2x_link_settings_requested(bp);
8392 8393
8394 /*
8395 * If connected directly, work with the internal PHY, otherwise, work
8396 * with the external PHY
8397 */
8398 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
8399 if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
8400 bp->mdio.prtad = bp->link_params.phy_addr;
8401
8402 else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
8403 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
8404 bp->mdio.prtad =
8405 (bp->link_params.ext_phy_config &
8406 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
8407 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT;
8408
8393 val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); 8409 val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
8394 val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); 8410 val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
8395 bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff); 8411 bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
@@ -8614,7 +8630,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
8614 } else 8630 } else
8615 cmd->port = PORT_TP; 8631 cmd->port = PORT_TP;
8616 8632
8617 cmd->phy_address = bp->port.phy_addr; 8633 cmd->phy_address = bp->mdio.prtad;
8618 cmd->transceiver = XCVR_INTERNAL; 8634 cmd->transceiver = XCVR_INTERNAL;
8619 8635
8620 if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) 8636 if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
@@ -11149,54 +11165,77 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
11149} 11165}
11150 11166
11151/* called with rtnl_lock */ 11167/* called with rtnl_lock */
11152static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 11168static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
11169 int devad, u16 addr)
11153{ 11170{
11154 struct mii_ioctl_data *data = if_mii(ifr); 11171 struct bnx2x *bp = netdev_priv(netdev);
11155 struct bnx2x *bp = netdev_priv(dev); 11172 u16 value;
11156 int port = BP_PORT(bp); 11173 int rc;
11157 int err; 11174 u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
11158 11175
11159 switch (cmd) { 11176 DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
11160 case SIOCGMIIPHY: 11177 prtad, devad, addr);
11161 data->phy_id = bp->port.phy_addr;
11162 11178
11163 /* fallthrough */ 11179 if (prtad != bp->mdio.prtad) {
11180 DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
11181 prtad, bp->mdio.prtad);
11182 return -EINVAL;
11183 }
11184
11185 /* The HW expects different devad if CL22 is used */
11186 devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
11164 11187
11165 case SIOCGMIIREG: { 11188 bnx2x_acquire_phy_lock(bp);
11166 u16 mii_regval; 11189 rc = bnx2x_cl45_read(bp, BP_PORT(bp), phy_type, prtad,
11190 devad, addr, &value);
11191 bnx2x_release_phy_lock(bp);
11192 DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
11167 11193
11168 if (!netif_running(dev)) 11194 if (!rc)
11169 return -EAGAIN; 11195 rc = value;
11196 return rc;
11197}
11170 11198
11171 mutex_lock(&bp->port.phy_mutex); 11199/* called with rtnl_lock */
11172 err = bnx2x_cl45_read(bp, port, 0, bp->port.phy_addr, 11200static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
11173 DEFAULT_PHY_DEV_ADDR, 11201 u16 addr, u16 value)
11174 (data->reg_num & 0x1f), &mii_regval); 11202{
11175 data->val_out = mii_regval; 11203 struct bnx2x *bp = netdev_priv(netdev);
11176 mutex_unlock(&bp->port.phy_mutex); 11204 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
11177 return err; 11205 int rc;
11206
11207 DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
11208 " value 0x%x\n", prtad, devad, addr, value);
11209
11210 if (prtad != bp->mdio.prtad) {
11211 DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
11212 prtad, bp->mdio.prtad);
11213 return -EINVAL;
11178 } 11214 }
11179 11215
11180 case SIOCSMIIREG: 11216 /* The HW expects different devad if CL22 is used */
11181 if (!capable(CAP_NET_ADMIN)) 11217 devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
11182 return -EPERM;
11183 11218
11184 if (!netif_running(dev)) 11219 bnx2x_acquire_phy_lock(bp);
11185 return -EAGAIN; 11220 rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
11221 devad, addr, value);
11222 bnx2x_release_phy_lock(bp);
11223 return rc;
11224}
11186 11225
11187 mutex_lock(&bp->port.phy_mutex); 11226/* called with rtnl_lock */
11188 err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr, 11227static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
11189 DEFAULT_PHY_DEV_ADDR, 11228{
11190 (data->reg_num & 0x1f), data->val_in); 11229 struct bnx2x *bp = netdev_priv(dev);
11191 mutex_unlock(&bp->port.phy_mutex); 11230 struct mii_ioctl_data *mdio = if_mii(ifr);
11192 return err;
11193 11231
11194 default: 11232 DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
11195 /* do nothing */ 11233 mdio->phy_id, mdio->reg_num, mdio->val_in);
11196 break;
11197 }
11198 11234
11199 return -EOPNOTSUPP; 11235 if (!netif_running(dev))
11236 return -EAGAIN;
11237
11238 return mdio_mii_ioctl(&bp->mdio, mdio, cmd);
11200} 11239}
11201 11240
11202/* called with rtnl_lock */ 11241/* called with rtnl_lock */
@@ -11420,6 +11459,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
11420 dev->vlan_features |= NETIF_F_TSO6; 11459 dev->vlan_features |= NETIF_F_TSO6;
11421#endif 11460#endif
11422 11461
11462 /* get_port_hwinfo() will set prtad and mmds properly */
11463 bp->mdio.prtad = MDIO_PRTAD_NONE;
11464 bp->mdio.mmds = 0;
11465 bp->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
11466 bp->mdio.dev = dev;
11467 bp->mdio.mdio_read = bnx2x_mdio_read;
11468 bp->mdio.mdio_write = bnx2x_mdio_write;
11469
11423 return 0; 11470 return 0;
11424 11471
11425err_out_unmap: 11472err_out_unmap: