diff options
| author | Ayaz Abdulla <aabdulla@nvidia.com> | 2006-06-10 22:47:47 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-06-11 09:25:15 -0400 |
| commit | f9430a015a4331ba950eba1d7661dcd876c29f3c (patch) | |
| tree | 52433da933bc935fe3be5f5bf0cc617ca4ac017c | |
| parent | b6d0773fa7943fd93d564056395a7ff29b81213b (diff) | |
[PATCH] forcedeth config: phy
This patch fixes configuration bugs when modifying phy settings.
Signed-Off-By: Ayaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/net/forcedeth.c | 108 |
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 | } |
