diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-08-12 04:23:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 02:02:29 -0400 |
commit | 01cd452846c98609dd3efbee0deea050e6706f02 (patch) | |
tree | 87647fccfe40819aa803b1f8191d7d4127024e63 /drivers/net | |
parent | 239d686d494f10ecd83a89ddc4e31f9462ca4901 (diff) |
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/bnx2x.h | 3 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 121 |
3 files changed, 88 insertions, 37 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9948fa23222..29935a9fb1a 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 5864ae2faab..903c89d8518 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 a695e7f0647..145866764d4 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 */ |
11152 | static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 11168 | static 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, | 11200 | static 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, | 11227 | static 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 | ||
11425 | err_out_unmap: | 11472 | err_out_unmap: |