diff options
Diffstat (limited to 'drivers/net/tg3.c')
| -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)) { |
