Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+3 −0
Original line number Original line Diff line number Diff line
@@ -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;
+84 −37
Original line number Original line Diff line number Diff line
@@ -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)
@@ -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);
		return err;
}
}


	case SIOCSMIIREG:
/* called with rtnl_lock */
		if (!capable(CAP_NET_ADMIN))
static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
			return -EPERM;
			    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;


		if (!netif_running(dev))
	DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
			return -EAGAIN;
			   " value 0x%x\n", prtad, devad, addr, value);


		mutex_lock(&bp->port.phy_mutex);
	if (prtad != bp->mdio.prtad) {
		err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr,
		DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
				       DEFAULT_PHY_DEV_ADDR,
		   prtad, bp->mdio.prtad);
				       (data->reg_num & 0x1f), data->val_in);
		return -EINVAL;
		mutex_unlock(&bp->port.phy_mutex);
	}
		return err;


	default:
	/* The HW expects different devad if CL22 is used */
		/* do nothing */
	devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
		break;

	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;
}
}


	return -EOPNOTSUPP;
/* called with rtnl_lock */
static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct bnx2x *bp = netdev_priv(dev);
	struct mii_ioctl_data *mdio = if_mii(ifr);

	DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
	   mdio->phy_id, mdio->reg_num, mdio->val_in);

	if (!netif_running(dev))
		return -EAGAIN;

	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,
	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: