aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-07-08 01:50:15 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:18:33 -0400
commit7b6b83474cb9bdd07dadfb7497a29c3005ad9d1d (patch)
tree64fbf2a9c6a28f6f5e041b1da65b0cd12335a8c4 /drivers/net/bnx2.c
parent0d8a6571051d23c214d7a316976138a6fd8bda1c (diff)
[BNX2]: Add ethtool support for remote PHY.
Modify the driver's ethtool_ops->get_settings and set_settings functions to support remote PHY. Users control the remote copper PHY settings by specifying link settings for the tp (twisted pair) port. The nway_reset function is also modified to support remote PHY. mii-tool operations are not supported on remote PHY and we will return -EOPNOTSUPP. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c83
1 files changed, 56 insertions, 27 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index c571da60241d..d7fad6938bdd 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -5363,17 +5363,25 @@ static int
5363bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 5363bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5364{ 5364{
5365 struct bnx2 *bp = netdev_priv(dev); 5365 struct bnx2 *bp = netdev_priv(dev);
5366 int support_serdes = 0, support_copper = 0;
5366 5367
5367 cmd->supported = SUPPORTED_Autoneg; 5368 cmd->supported = SUPPORTED_Autoneg;
5368 if (bp->phy_flags & PHY_SERDES_FLAG) { 5369 if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
5370 support_serdes = 1;
5371 support_copper = 1;
5372 } else if (bp->phy_port == PORT_FIBRE)
5373 support_serdes = 1;
5374 else
5375 support_copper = 1;
5376
5377 if (support_serdes) {
5369 cmd->supported |= SUPPORTED_1000baseT_Full | 5378 cmd->supported |= SUPPORTED_1000baseT_Full |
5370 SUPPORTED_FIBRE; 5379 SUPPORTED_FIBRE;
5371 if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) 5380 if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
5372 cmd->supported |= SUPPORTED_2500baseX_Full; 5381 cmd->supported |= SUPPORTED_2500baseX_Full;
5373 5382
5374 cmd->port = PORT_FIBRE;
5375 } 5383 }
5376 else { 5384 if (support_copper) {
5377 cmd->supported |= SUPPORTED_10baseT_Half | 5385 cmd->supported |= SUPPORTED_10baseT_Half |
5378 SUPPORTED_10baseT_Full | 5386 SUPPORTED_10baseT_Full |
5379 SUPPORTED_100baseT_Half | 5387 SUPPORTED_100baseT_Half |
@@ -5381,9 +5389,10 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5381 SUPPORTED_1000baseT_Full | 5389 SUPPORTED_1000baseT_Full |
5382 SUPPORTED_TP; 5390 SUPPORTED_TP;
5383 5391
5384 cmd->port = PORT_TP;
5385 } 5392 }
5386 5393
5394 spin_lock_bh(&bp->phy_lock);
5395 cmd->port = bp->phy_port;
5387 cmd->advertising = bp->advertising; 5396 cmd->advertising = bp->advertising;
5388 5397
5389 if (bp->autoneg & AUTONEG_SPEED) { 5398 if (bp->autoneg & AUTONEG_SPEED) {
@@ -5401,6 +5410,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5401 cmd->speed = -1; 5410 cmd->speed = -1;
5402 cmd->duplex = -1; 5411 cmd->duplex = -1;
5403 } 5412 }
5413 spin_unlock_bh(&bp->phy_lock);
5404 5414
5405 cmd->transceiver = XCVR_INTERNAL; 5415 cmd->transceiver = XCVR_INTERNAL;
5406 cmd->phy_address = bp->phy_addr; 5416 cmd->phy_address = bp->phy_addr;
@@ -5416,6 +5426,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5416 u8 req_duplex = bp->req_duplex; 5426 u8 req_duplex = bp->req_duplex;
5417 u16 req_line_speed = bp->req_line_speed; 5427 u16 req_line_speed = bp->req_line_speed;
5418 u32 advertising = bp->advertising; 5428 u32 advertising = bp->advertising;
5429 int err = -EINVAL;
5430
5431 spin_lock_bh(&bp->phy_lock);
5432
5433 if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
5434 goto err_out_unlock;
5435
5436 if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG))
5437 goto err_out_unlock;
5419 5438
5420 if (cmd->autoneg == AUTONEG_ENABLE) { 5439 if (cmd->autoneg == AUTONEG_ENABLE) {
5421 autoneg |= AUTONEG_SPEED; 5440 autoneg |= AUTONEG_SPEED;
@@ -5428,44 +5447,41 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5428 (cmd->advertising == ADVERTISED_100baseT_Half) || 5447 (cmd->advertising == ADVERTISED_100baseT_Half) ||
5429 (cmd->advertising == ADVERTISED_100baseT_Full)) { 5448 (cmd->advertising == ADVERTISED_100baseT_Full)) {
5430 5449
5431 if (bp->phy_flags & PHY_SERDES_FLAG) 5450 if (cmd->port == PORT_FIBRE)
5432 return -EINVAL; 5451 goto err_out_unlock;
5433 5452
5434 advertising = cmd->advertising; 5453 advertising = cmd->advertising;
5435 5454
5436 } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { 5455 } else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
5437 if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) 5456 if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ||
5438 return -EINVAL; 5457 (cmd->port == PORT_TP))
5439 } else if (cmd->advertising == ADVERTISED_1000baseT_Full) { 5458 goto err_out_unlock;
5459 } else if (cmd->advertising == ADVERTISED_1000baseT_Full)
5440 advertising = cmd->advertising; 5460 advertising = cmd->advertising;
5441 } 5461 else if (cmd->advertising == ADVERTISED_1000baseT_Half)
5442 else if (cmd->advertising == ADVERTISED_1000baseT_Half) { 5462 goto err_out_unlock;
5443 return -EINVAL;
5444 }
5445 else { 5463 else {
5446 if (bp->phy_flags & PHY_SERDES_FLAG) { 5464 if (cmd->port == PORT_FIBRE)
5447 advertising = ETHTOOL_ALL_FIBRE_SPEED; 5465 advertising = ETHTOOL_ALL_FIBRE_SPEED;
5448 } 5466 else
5449 else {
5450 advertising = ETHTOOL_ALL_COPPER_SPEED; 5467 advertising = ETHTOOL_ALL_COPPER_SPEED;
5451 }
5452 } 5468 }
5453 advertising |= ADVERTISED_Autoneg; 5469 advertising |= ADVERTISED_Autoneg;
5454 } 5470 }
5455 else { 5471 else {
5456 if (bp->phy_flags & PHY_SERDES_FLAG) { 5472 if (cmd->port == PORT_FIBRE) {
5457 if ((cmd->speed != SPEED_1000 && 5473 if ((cmd->speed != SPEED_1000 &&
5458 cmd->speed != SPEED_2500) || 5474 cmd->speed != SPEED_2500) ||
5459 (cmd->duplex != DUPLEX_FULL)) 5475 (cmd->duplex != DUPLEX_FULL))
5460 return -EINVAL; 5476 goto err_out_unlock;
5461 5477
5462 if (cmd->speed == SPEED_2500 && 5478 if (cmd->speed == SPEED_2500 &&
5463 !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) 5479 !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
5464 return -EINVAL; 5480 goto err_out_unlock;
5465 }
5466 else if (cmd->speed == SPEED_1000) {
5467 return -EINVAL;
5468 } 5481 }
5482 else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500)
5483 goto err_out_unlock;
5484
5469 autoneg &= ~AUTONEG_SPEED; 5485 autoneg &= ~AUTONEG_SPEED;
5470 req_line_speed = cmd->speed; 5486 req_line_speed = cmd->speed;
5471 req_duplex = cmd->duplex; 5487 req_duplex = cmd->duplex;
@@ -5477,13 +5493,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5477 bp->req_line_speed = req_line_speed; 5493 bp->req_line_speed = req_line_speed;
5478 bp->req_duplex = req_duplex; 5494 bp->req_duplex = req_duplex;
5479 5495
5480 spin_lock_bh(&bp->phy_lock); 5496 err = bnx2_setup_phy(bp, cmd->port);
5481
5482 bnx2_setup_phy(bp, bp->phy_port);
5483 5497
5498err_out_unlock:
5484 spin_unlock_bh(&bp->phy_lock); 5499 spin_unlock_bh(&bp->phy_lock);
5485 5500
5486 return 0; 5501 return err;
5487} 5502}
5488 5503
5489static void 5504static void
@@ -5610,6 +5625,14 @@ bnx2_nway_reset(struct net_device *dev)
5610 5625
5611 spin_lock_bh(&bp->phy_lock); 5626 spin_lock_bh(&bp->phy_lock);
5612 5627
5628 if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
5629 int rc;
5630
5631 rc = bnx2_setup_remote_phy(bp, bp->phy_port);
5632 spin_unlock_bh(&bp->phy_lock);
5633 return rc;
5634 }
5635
5613 /* Force a link down visible on the other side */ 5636 /* Force a link down visible on the other side */
5614 if (bp->phy_flags & PHY_SERDES_FLAG) { 5637 if (bp->phy_flags & PHY_SERDES_FLAG) {
5615 bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); 5638 bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
@@ -6219,6 +6242,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6219 case SIOCGMIIREG: { 6242 case SIOCGMIIREG: {
6220 u32 mii_regval; 6243 u32 mii_regval;
6221 6244
6245 if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
6246 return -EOPNOTSUPP;
6247
6222 if (!netif_running(dev)) 6248 if (!netif_running(dev))
6223 return -EAGAIN; 6249 return -EAGAIN;
6224 6250
@@ -6235,6 +6261,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6235 if (!capable(CAP_NET_ADMIN)) 6261 if (!capable(CAP_NET_ADMIN))
6236 return -EPERM; 6262 return -EPERM;
6237 6263
6264 if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
6265 return -EOPNOTSUPP;
6266
6238 if (!netif_running(dev)) 6267 if (!netif_running(dev))
6239 return -EAGAIN; 6268 return -EAGAIN;
6240 6269