Commit 01cd4528 authored by Eilon Greenstein's avatar Eilon Greenstein Committed by David S. Miller

bnx2x: MDC/MDIO CL45 IOCTLs

As suggested by Ben Hutchings <bhutchings@solarflare.com>, using the MDC/MDIO
IOCTL
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 239d686d
...@@ -2722,6 +2722,7 @@ config BNX2X ...@@ -2722,6 +2722,7 @@ config BNX2X
select FW_LOADER select FW_LOADER
select ZLIB_INFLATE select ZLIB_INFLATE
select LIBCRC32C select LIBCRC32C
select MDIO
help help
This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards. This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#define BNX2X_NEW_NAPI #define BNX2X_NEW_NAPI
#include <linux/mdio.h>
#include "bnx2x_reg.h" #include "bnx2x_reg.h"
#include "bnx2x_fw_defs.h" #include "bnx2x_fw_defs.h"
#include "bnx2x_hsi.h" #include "bnx2x_hsi.h"
...@@ -895,6 +897,7 @@ struct bnx2x { ...@@ -895,6 +897,7 @@ struct bnx2x {
struct link_params link_params; struct link_params link_params;
struct link_vars link_vars; struct link_vars link_vars;
struct mdio_if_info mdio;
struct bnx2x_common common; struct bnx2x_common common;
struct bnx2x_port port; struct bnx2x_port port;
......
...@@ -8331,6 +8331,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) ...@@ -8331,6 +8331,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
u32 val, val2; u32 val, val2;
u32 config; u32 config;
u16 i; u16 i;
u32 ext_phy_type;
bp->link_params.bp = bp; bp->link_params.bp = bp;
bp->link_params.port = port; bp->link_params.port = port;
...@@ -8390,6 +8391,21 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) ...@@ -8390,6 +8391,21 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bnx2x_link_settings_requested(bp); bnx2x_link_settings_requested(bp);
/*
* If connected directly, work with the internal PHY, otherwise, work
* with the external PHY
*/
ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
bp->mdio.prtad = bp->link_params.phy_addr;
else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
(ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
bp->mdio.prtad =
(bp->link_params.ext_phy_config &
PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT;
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff); 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,7 +8630,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
} else } else
cmd->port = PORT_TP; cmd->port = PORT_TP;
cmd->phy_address = bp->port.phy_addr; cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL; cmd->transceiver = XCVR_INTERNAL;
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) 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,54 +11165,77 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
} }
/* called with rtnl_lock */ /* called with rtnl_lock */
static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
int devad, u16 addr)
{ {
struct mii_ioctl_data *data = if_mii(ifr); struct bnx2x *bp = netdev_priv(netdev);
struct bnx2x *bp = netdev_priv(dev); u16 value;
int port = BP_PORT(bp); int rc;
int err; u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
switch (cmd) { DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
case SIOCGMIIPHY: prtad, devad, addr);
data->phy_id = bp->port.phy_addr;
/* fallthrough */ if (prtad != bp->mdio.prtad) {
DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
prtad, bp->mdio.prtad);
return -EINVAL;
}
case SIOCGMIIREG: { /* The HW expects different devad if CL22 is used */
u16 mii_regval; devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
if (!netif_running(dev)) bnx2x_acquire_phy_lock(bp);
return -EAGAIN; rc = bnx2x_cl45_read(bp, BP_PORT(bp), phy_type, prtad,
devad, addr, &value);
bnx2x_release_phy_lock(bp);
DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
mutex_lock(&bp->port.phy_mutex); if (!rc)
err = bnx2x_cl45_read(bp, port, 0, bp->port.phy_addr, rc = value;
DEFAULT_PHY_DEV_ADDR, return rc;
(data->reg_num & 0x1f), &mii_regval); }
data->val_out = mii_regval;
mutex_unlock(&bp->port.phy_mutex); /* called with rtnl_lock */
return err; static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
u16 addr, u16 value)
{
struct bnx2x *bp = netdev_priv(netdev);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
int rc;
DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
" value 0x%x\n", prtad, devad, addr, value);
if (prtad != bp->mdio.prtad) {
DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
prtad, bp->mdio.prtad);
return -EINVAL;
} }
case SIOCSMIIREG: /* The HW expects different devad if CL22 is used */
if (!capable(CAP_NET_ADMIN)) devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
return -EPERM;
if (!netif_running(dev)) bnx2x_acquire_phy_lock(bp);
return -EAGAIN; rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
devad, addr, value);
bnx2x_release_phy_lock(bp);
return rc;
}
mutex_lock(&bp->port.phy_mutex); /* called with rtnl_lock */
err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr, static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
DEFAULT_PHY_DEV_ADDR, {
(data->reg_num & 0x1f), data->val_in); struct bnx2x *bp = netdev_priv(dev);
mutex_unlock(&bp->port.phy_mutex); struct mii_ioctl_data *mdio = if_mii(ifr);
return err;
default: DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
/* do nothing */ mdio->phy_id, mdio->reg_num, mdio->val_in);
break;
} if (!netif_running(dev))
return -EAGAIN;
return -EOPNOTSUPP; return mdio_mii_ioctl(&bp->mdio, mdio, cmd);
} }
/* called with rtnl_lock */ /* called with rtnl_lock */
...@@ -11420,6 +11459,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, ...@@ -11420,6 +11459,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->vlan_features |= NETIF_F_TSO6; dev->vlan_features |= NETIF_F_TSO6;
#endif #endif
/* get_port_hwinfo() will set prtad and mmds properly */
bp->mdio.prtad = MDIO_PRTAD_NONE;
bp->mdio.mmds = 0;
bp->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
bp->mdio.dev = dev;
bp->mdio.mdio_read = bnx2x_mdio_read;
bp->mdio.mdio_write = bnx2x_mdio_write;
return 0; return 0;
err_out_unmap: err_out_unmap:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment