aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/forcedeth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r--drivers/net/forcedeth.c108
1 files changed, 78 insertions, 30 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 14e6da2c1bf4..a7e7be7ed705 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2516,9 +2516,17 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2516 if (!netif_running(dev)) { 2516 if (!netif_running(dev)) {
2517 /* We do not track link speed / duplex setting if the 2517 /* We do not track link speed / duplex setting if the
2518 * interface is disabled. Force a link check */ 2518 * interface is disabled. Force a link check */
2519 nv_update_linkspeed(dev); 2519 if (nv_update_linkspeed(dev)) {
2520 if (!netif_carrier_ok(dev))
2521 netif_carrier_on(dev);
2522 } else {
2523 if (netif_carrier_ok(dev))
2524 netif_carrier_off(dev);
2525 }
2520 } 2526 }
2521 switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) { 2527
2528 if (netif_carrier_ok(dev)) {
2529 switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
2522 case NVREG_LINKSPEED_10: 2530 case NVREG_LINKSPEED_10:
2523 ecmd->speed = SPEED_10; 2531 ecmd->speed = SPEED_10;
2524 break; 2532 break;
@@ -2528,10 +2536,14 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2528 case NVREG_LINKSPEED_1000: 2536 case NVREG_LINKSPEED_1000:
2529 ecmd->speed = SPEED_1000; 2537 ecmd->speed = SPEED_1000;
2530 break; 2538 break;
2539 }
2540 ecmd->duplex = DUPLEX_HALF;
2541 if (np->duplex)
2542 ecmd->duplex = DUPLEX_FULL;
2543 } else {
2544 ecmd->speed = -1;
2545 ecmd->duplex = -1;
2531 } 2546 }
2532 ecmd->duplex = DUPLEX_HALF;
2533 if (np->duplex)
2534 ecmd->duplex = DUPLEX_FULL;
2535 2547
2536 ecmd->autoneg = np->autoneg; 2548 ecmd->autoneg = np->autoneg;
2537 2549
@@ -2539,23 +2551,20 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2539 if (np->autoneg) { 2551 if (np->autoneg) {
2540 ecmd->advertising |= ADVERTISED_Autoneg; 2552 ecmd->advertising |= ADVERTISED_Autoneg;
2541 adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); 2553 adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
2542 } else { 2554 if (adv & ADVERTISE_10HALF)
2543 adv = np->fixed_mode; 2555 ecmd->advertising |= ADVERTISED_10baseT_Half;
2544 } 2556 if (adv & ADVERTISE_10FULL)
2545 if (adv & ADVERTISE_10HALF) 2557 ecmd->advertising |= ADVERTISED_10baseT_Full;
2546 ecmd->advertising |= ADVERTISED_10baseT_Half; 2558 if (adv & ADVERTISE_100HALF)
2547 if (adv & ADVERTISE_10FULL) 2559 ecmd->advertising |= ADVERTISED_100baseT_Half;
2548 ecmd->advertising |= ADVERTISED_10baseT_Full; 2560 if (adv & ADVERTISE_100FULL)
2549 if (adv & ADVERTISE_100HALF) 2561 ecmd->advertising |= ADVERTISED_100baseT_Full;
2550 ecmd->advertising |= ADVERTISED_100baseT_Half; 2562 if (np->gigabit == PHY_GIGABIT) {
2551 if (adv & ADVERTISE_100FULL) 2563 adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
2552 ecmd->advertising |= ADVERTISED_100baseT_Full; 2564 if (adv & ADVERTISE_1000FULL)
2553 if (np->autoneg && np->gigabit == PHY_GIGABIT) { 2565 ecmd->advertising |= ADVERTISED_1000baseT_Full;
2554 adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); 2566 }
2555 if (adv & ADVERTISE_1000FULL)
2556 ecmd->advertising |= ADVERTISED_1000baseT_Full;
2557 } 2567 }
2558
2559 ecmd->supported = (SUPPORTED_Autoneg | 2568 ecmd->supported = (SUPPORTED_Autoneg |
2560 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 2569 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
2561 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | 2570 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2607,7 +2616,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2607 return -EINVAL; 2616 return -EINVAL;
2608 } 2617 }
2609 2618
2610 spin_lock_irq(&np->lock); 2619 netif_carrier_off(dev);
2620 if (netif_running(dev)) {
2621 nv_disable_irq(dev);
2622 spin_lock_bh(&dev->xmit_lock);
2623 spin_lock(&np->lock);
2624 /* stop engines */
2625 nv_stop_rx(dev);
2626 nv_stop_tx(dev);
2627 spin_unlock(&np->lock);
2628 spin_unlock_bh(&dev->xmit_lock);
2629 }
2630
2611 if (ecmd->autoneg == AUTONEG_ENABLE) { 2631 if (ecmd->autoneg == AUTONEG_ENABLE) {
2612 int adv, bmcr; 2632 int adv, bmcr;
2613 2633
@@ -2638,6 +2658,8 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2638 mii_rw(dev, np->phyaddr, MII_CTRL1000, adv); 2658 mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
2639 } 2659 }
2640 2660
2661 if (netif_running(dev))
2662 printk(KERN_INFO "%s: link down.\n", dev->name);
2641 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 2663 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
2642 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 2664 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
2643 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); 2665 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
@@ -2676,20 +2698,30 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2676 } 2698 }
2677 2699
2678 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 2700 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
2679 bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX); 2701 bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX);
2680 if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL)) 2702 if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL))
2681 bmcr |= BMCR_FULLDPLX; 2703 bmcr |= BMCR_FULLDPLX;
2682 if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL)) 2704 if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
2683 bmcr |= BMCR_SPEED100; 2705 bmcr |= BMCR_SPEED100;
2684 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); 2706 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
2685 2707 if (np->phy_oui == PHY_OUI_MARVELL) {
2686 if (netif_running(dev)) { 2708 /* reset the phy */
2709 if (phy_reset(dev)) {
2710 printk(KERN_INFO "%s: phy reset failed\n", dev->name);
2711 return -EINVAL;
2712 }
2713 } else if (netif_running(dev)) {
2687 /* Wait a bit and then reconfigure the nic. */ 2714 /* Wait a bit and then reconfigure the nic. */
2688 udelay(10); 2715 udelay(10);
2689 nv_linkchange(dev); 2716 nv_linkchange(dev);
2690 } 2717 }
2691 } 2718 }
2692 spin_unlock_irq(&np->lock); 2719
2720 if (netif_running(dev)) {
2721 nv_start_rx(dev);
2722 nv_start_tx(dev);
2723 nv_enable_irq(dev);
2724 }
2693 2725
2694 return 0; 2726 return 0;
2695} 2727}
@@ -2721,19 +2753,35 @@ static int nv_nway_reset(struct net_device *dev)
2721 struct fe_priv *np = netdev_priv(dev); 2753 struct fe_priv *np = netdev_priv(dev);
2722 int ret; 2754 int ret;
2723 2755
2724 spin_lock_irq(&np->lock);
2725 if (np->autoneg) { 2756 if (np->autoneg) {
2726 int bmcr; 2757 int bmcr;
2727 2758
2759 netif_carrier_off(dev);
2760 if (netif_running(dev)) {
2761 nv_disable_irq(dev);
2762 spin_lock_bh(&dev->xmit_lock);
2763 spin_lock(&np->lock);
2764 /* stop engines */
2765 nv_stop_rx(dev);
2766 nv_stop_tx(dev);
2767 spin_unlock(&np->lock);
2768 spin_unlock_bh(&dev->xmit_lock);
2769 printk(KERN_INFO "%s: link down.\n", dev->name);
2770 }
2771
2728 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 2772 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
2729 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 2773 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
2730 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); 2774 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
2731 2775
2776 if (netif_running(dev)) {
2777 nv_start_rx(dev);
2778 nv_start_tx(dev);
2779 nv_enable_irq(dev);
2780 }
2732 ret = 0; 2781 ret = 0;
2733 } else { 2782 } else {
2734 ret = -EINVAL; 2783 ret = -EINVAL;
2735 } 2784 }
2736 spin_unlock_irq(&np->lock);
2737 2785
2738 return ret; 2786 return ret;
2739} 2787}