diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ec1953043102..d5a1f9e3794c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3373,8 +3373,8 @@ relink: | |||
3373 | tg3_phy_copper_begin(tp); | 3373 | tg3_phy_copper_begin(tp); |
3374 | 3374 | ||
3375 | tg3_readphy(tp, MII_BMSR, &bmsr); | 3375 | tg3_readphy(tp, MII_BMSR, &bmsr); |
3376 | if (!tg3_readphy(tp, MII_BMSR, &bmsr) && | 3376 | if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) || |
3377 | (bmsr & BMSR_LSTATUS)) | 3377 | (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)) |
3378 | current_link_up = 1; | 3378 | current_link_up = 1; |
3379 | } | 3379 | } |
3380 | 3380 | ||
@@ -6309,6 +6309,42 @@ dma_error: | |||
6309 | return NETDEV_TX_OK; | 6309 | return NETDEV_TX_OK; |
6310 | } | 6310 | } |
6311 | 6311 | ||
6312 | static void tg3_set_loopback(struct net_device *dev, u32 features) | ||
6313 | { | ||
6314 | struct tg3 *tp = netdev_priv(dev); | ||
6315 | |||
6316 | if (features & NETIF_F_LOOPBACK) { | ||
6317 | if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK) | ||
6318 | return; | ||
6319 | |||
6320 | /* | ||
6321 | * Clear MAC_MODE_HALF_DUPLEX or you won't get packets back in | ||
6322 | * loopback mode if Half-Duplex mode was negotiated earlier. | ||
6323 | */ | ||
6324 | tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; | ||
6325 | |||
6326 | /* Enable internal MAC loopback mode */ | ||
6327 | tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK; | ||
6328 | spin_lock_bh(&tp->lock); | ||
6329 | tw32(MAC_MODE, tp->mac_mode); | ||
6330 | netif_carrier_on(tp->dev); | ||
6331 | spin_unlock_bh(&tp->lock); | ||
6332 | netdev_info(dev, "Internal MAC loopback mode enabled.\n"); | ||
6333 | } else { | ||
6334 | if (!(tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)) | ||
6335 | return; | ||
6336 | |||
6337 | /* Disable internal MAC loopback mode */ | ||
6338 | tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK; | ||
6339 | spin_lock_bh(&tp->lock); | ||
6340 | tw32(MAC_MODE, tp->mac_mode); | ||
6341 | /* Force link status check */ | ||
6342 | tg3_setup_phy(tp, 1); | ||
6343 | spin_unlock_bh(&tp->lock); | ||
6344 | netdev_info(dev, "Internal MAC loopback mode disabled.\n"); | ||
6345 | } | ||
6346 | } | ||
6347 | |||
6312 | static u32 tg3_fix_features(struct net_device *dev, u32 features) | 6348 | static u32 tg3_fix_features(struct net_device *dev, u32 features) |
6313 | { | 6349 | { |
6314 | struct tg3 *tp = netdev_priv(dev); | 6350 | struct tg3 *tp = netdev_priv(dev); |
@@ -6319,6 +6355,16 @@ static u32 tg3_fix_features(struct net_device *dev, u32 features) | |||
6319 | return features; | 6355 | return features; |
6320 | } | 6356 | } |
6321 | 6357 | ||
6358 | static int tg3_set_features(struct net_device *dev, u32 features) | ||
6359 | { | ||
6360 | u32 changed = dev->features ^ features; | ||
6361 | |||
6362 | if ((changed & NETIF_F_LOOPBACK) && netif_running(dev)) | ||
6363 | tg3_set_loopback(dev, features); | ||
6364 | |||
6365 | return 0; | ||
6366 | } | ||
6367 | |||
6322 | static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, | 6368 | static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, |
6323 | int new_mtu) | 6369 | int new_mtu) |
6324 | { | 6370 | { |
@@ -9485,6 +9531,13 @@ static int tg3_open(struct net_device *dev) | |||
9485 | 9531 | ||
9486 | netif_tx_start_all_queues(dev); | 9532 | netif_tx_start_all_queues(dev); |
9487 | 9533 | ||
9534 | /* | ||
9535 | * Reset loopback feature if it was turned on while the device was down | ||
9536 | * make sure that it's installed properly now. | ||
9537 | */ | ||
9538 | if (dev->features & NETIF_F_LOOPBACK) | ||
9539 | tg3_set_loopback(dev, dev->features); | ||
9540 | |||
9488 | return 0; | 9541 | return 0; |
9489 | 9542 | ||
9490 | err_out3: | 9543 | err_out3: |
@@ -15033,6 +15086,7 @@ static const struct net_device_ops tg3_netdev_ops = { | |||
15033 | .ndo_tx_timeout = tg3_tx_timeout, | 15086 | .ndo_tx_timeout = tg3_tx_timeout, |
15034 | .ndo_change_mtu = tg3_change_mtu, | 15087 | .ndo_change_mtu = tg3_change_mtu, |
15035 | .ndo_fix_features = tg3_fix_features, | 15088 | .ndo_fix_features = tg3_fix_features, |
15089 | .ndo_set_features = tg3_set_features, | ||
15036 | #ifdef CONFIG_NET_POLL_CONTROLLER | 15090 | #ifdef CONFIG_NET_POLL_CONTROLLER |
15037 | .ndo_poll_controller = tg3_poll_controller, | 15091 | .ndo_poll_controller = tg3_poll_controller, |
15038 | #endif | 15092 | #endif |
@@ -15049,6 +15103,7 @@ static const struct net_device_ops tg3_netdev_ops_dma_bug = { | |||
15049 | .ndo_do_ioctl = tg3_ioctl, | 15103 | .ndo_do_ioctl = tg3_ioctl, |
15050 | .ndo_tx_timeout = tg3_tx_timeout, | 15104 | .ndo_tx_timeout = tg3_tx_timeout, |
15051 | .ndo_change_mtu = tg3_change_mtu, | 15105 | .ndo_change_mtu = tg3_change_mtu, |
15106 | .ndo_set_features = tg3_set_features, | ||
15052 | #ifdef CONFIG_NET_POLL_CONTROLLER | 15107 | #ifdef CONFIG_NET_POLL_CONTROLLER |
15053 | .ndo_poll_controller = tg3_poll_controller, | 15108 | .ndo_poll_controller = tg3_poll_controller, |
15054 | #endif | 15109 | #endif |
@@ -15246,6 +15301,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
15246 | dev->features |= hw_features; | 15301 | dev->features |= hw_features; |
15247 | dev->vlan_features |= hw_features; | 15302 | dev->vlan_features |= hw_features; |
15248 | 15303 | ||
15304 | /* | ||
15305 | * Add loopback capability only for a subset of devices that support | ||
15306 | * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY | ||
15307 | * loopback for the remaining devices. | ||
15308 | */ | ||
15309 | if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 && | ||
15310 | !tg3_flag(tp, CPMU_PRESENT)) | ||
15311 | /* Add the loopback capability */ | ||
15312 | dev->hw_features |= NETIF_F_LOOPBACK; | ||
15313 | |||
15249 | if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && | 15314 | if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && |
15250 | !tg3_flag(tp, TSO_CAPABLE) && | 15315 | !tg3_flag(tp, TSO_CAPABLE) && |
15251 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { | 15316 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { |