mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-28 15:20:41 +00:00
bnx2x: MDC/MDIO CL45 IOCTLs
As suggested by Ben Hutchings <bhutchings@solarflare.com>, using the MDC/MDIO IOCTL Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
239d686d49
commit
01cd452846
3 changed files with 94 additions and 43 deletions
|
@ -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 @@
|
||||||
#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 {
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
} 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)
|
||||||
|
@ -11148,55 +11164,78 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called with rtnl_lock */
|
||||||
|
static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
|
||||||
|
int devad, u16 addr)
|
||||||
|
{
|
||||||
|
struct bnx2x *bp = netdev_priv(netdev);
|
||||||
|
u16 value;
|
||||||
|
int rc;
|
||||||
|
u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
|
||||||
|
|
||||||
|
DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
|
||||||
|
prtad, devad, addr);
|
||||||
|
|
||||||
|
if (prtad != bp->mdio.prtad) {
|
||||||
|
DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
|
||||||
|
prtad, bp->mdio.prtad);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The HW expects different devad if CL22 is used */
|
||||||
|
devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
|
||||||
|
|
||||||
|
bnx2x_acquire_phy_lock(bp);
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
rc = value;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called with rtnl_lock */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The HW expects different devad if CL22 is used */
|
||||||
|
devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
|
||||||
|
|
||||||
|
bnx2x_acquire_phy_lock(bp);
|
||||||
|
rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
|
||||||
|
devad, addr, value);
|
||||||
|
bnx2x_release_phy_lock(bp);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* called with rtnl_lock */
|
/* called with rtnl_lock */
|
||||||
static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
{
|
{
|
||||||
struct mii_ioctl_data *data = if_mii(ifr);
|
|
||||||
struct bnx2x *bp = netdev_priv(dev);
|
struct bnx2x *bp = netdev_priv(dev);
|
||||||
int port = BP_PORT(bp);
|
struct mii_ioctl_data *mdio = if_mii(ifr);
|
||||||
int err;
|
|
||||||
|
|
||||||
switch (cmd) {
|
DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
|
||||||
case SIOCGMIIPHY:
|
mdio->phy_id, mdio->reg_num, mdio->val_in);
|
||||||
data->phy_id = bp->port.phy_addr;
|
|
||||||
|
|
||||||
/* fallthrough */
|
if (!netif_running(dev))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
case SIOCGMIIREG: {
|
return mdio_mii_ioctl(&bp->mdio, mdio, cmd);
|
||||||
u16 mii_regval;
|
|
||||||
|
|
||||||
if (!netif_running(dev))
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
mutex_lock(&bp->port.phy_mutex);
|
|
||||||
err = bnx2x_cl45_read(bp, port, 0, bp->port.phy_addr,
|
|
||||||
DEFAULT_PHY_DEV_ADDR,
|
|
||||||
(data->reg_num & 0x1f), &mii_regval);
|
|
||||||
data->val_out = mii_regval;
|
|
||||||
mutex_unlock(&bp->port.phy_mutex);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SIOCSMIIREG:
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
if (!netif_running(dev))
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
mutex_lock(&bp->port.phy_mutex);
|
|
||||||
err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr,
|
|
||||||
DEFAULT_PHY_DEV_ADDR,
|
|
||||||
(data->reg_num & 0x1f), data->val_in);
|
|
||||||
mutex_unlock(&bp->port.phy_mutex);
|
|
||||||
return err;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* do nothing */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called with rtnl_lock */
|
/* called with rtnl_lock */
|
||||||
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue