...
> > I still have a patch in queue to improve usage of netif_carrier_{on,off} 
> > but I had no possibility to test yet, so I did not send.
> 
> I'd be happy to test it out if you'd like.
> 
> Dan

Hi Dan,

here is the patch for testing.


The patch _should_ do the following:

1. Set the polling intervall for media changes to 5 seconds if link is down 
and 60 seconds if link is up.
2. Handle netif_carrier_{on,of} and check for media changes in 
proper way by using mii_check_media() in the mii case.
3. Handle netif_carrier_{on,of} also if media is forced to 10baseT/100baseTx.
4. Use ethtool_op_get_link instead of vortex_get_link. 
So it is possible to test with ethtool.

The patch compiles, but as I told it is fairly untested. 

Please let me know the results of your tests.
Thanks in advance,

Steffen

Signed-off-by: Steffen Klassert <[EMAIL PROTECTED]>

--- vanilla-2.6.15/drivers/net/3c59x.c  2006-01-03 04:21:10.000000000 +0100
+++ linux-2.6.15-sk2/drivers/net/3c59x.c        2006-01-13 16:15:28.000000000 
+0100
@@ -789,7 +789,7 @@
        int options;                                            /* 
User-settable misc. driver options. */
        unsigned int media_override:4,          /* Passed-in media type. */
                default_media:4,                                /* Read from 
the EEPROM/Wn3_Config. */
-               full_duplex:1, force_fd:1, autoselect:1,
+               full_duplex:1, autoselect:1,
                bus_master:1,                                   /* Vortex can 
only do a fragment bus-m. */
                full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
                flow_ctrl:1,                                    /* Use 802.3x 
flow control (PAUSE only) */
@@ -1326,7 +1326,7 @@
                        vp->enable_wol = 1;
        }
 
-       vp->force_fd = vp->full_duplex;
+       vp->mii.force_media = vp->full_duplex;
        vp->options = option;
        /* Read the station address from the EEPROM. */
        EL3WINDOW(0);
@@ -1616,6 +1616,48 @@
 }
 
 static void
+vortex_set_duplex(struct net_device *dev)
+{
+       int mii_reg1, mii_reg5;
+       struct vortex_private *vp = netdev_priv(dev);
+       long *ioaddr = vp->ioaddr;
+       
+       EL3WINDOW(4);
+       mii_reg1 = mdio_read(dev, vp->phys[0], 1);
+       mii_reg5 = mdio_read(dev, vp->phys[0], 5);
+       vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
+       EL3WINDOW(3);
+       if (vortex_debug > 1)
+               printk(KERN_INFO "%s: MII #%d status %4.4x, link partner 
capability %4.4x,"
+                          " info1 %04x, setting %s-duplex.\n",
+                               dev->name, vp->phys[0],
+                               mii_reg1, mii_reg5,
+                               vp->info1, ((vp->info1 & 0x8000) || 
vp->full_duplex) ? "full" : "half");
+       /* Set the full-duplex bit. */
+       iowrite16(      ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+                       (vp->large_frames ? 0x40 : 0) |
+                       ((vp->full_duplex && vp->flow_ctrl && 
vp->partner_flow_ctrl) ? 0x100 : 0),
+                       ioaddr + Wn3_MAC_Ctrl);
+       /* AKPM: bug: should reset Tx and Rx after setting Duplex.  Page 180 */
+}
+
+static void
+vortex_check_media(struct net_device *dev, unsigned int init)
+{
+       struct vortex_private *vp = netdev_priv(dev);
+       unsigned int ok_to_print = 0;
+
+       if (vortex_debug > 3)
+               ok_to_print = 1;
+       
+       if (mii_check_media(&vp->mii, ok_to_print, init)) {
+               vp->full_duplex = vp->mii.full_duplex;
+               vortex_set_duplex(dev);
+       } else if (init) 
+               vortex_set_duplex(dev);
+}
+
+static void
 vortex_up(struct net_device *dev)
 {
        struct vortex_private *vp = netdev_priv(dev);
@@ -1675,55 +1717,15 @@
                printk(KERN_DEBUG "%s: Initial media type %s.\n",
                           dev->name, media_tbl[dev->if_port].name);
 
-       vp->full_duplex = vp->force_fd;
+       vp->full_duplex = vp->mii.force_media;
        config = BFINS(config, dev->if_port, 20, 4);
        if (vortex_debug > 6)
                printk(KERN_DEBUG "vortex_up(): writing 0x%x to 
InternalConfig\n", config);
        iowrite32(config, ioaddr + Wn3_Config);
 
-       if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
-               int mii_reg1, mii_reg5;
-               EL3WINDOW(4);
-               /* Read BMSR (reg1) only to clear old status. */
-               mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
-               mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
-               if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000) {
-                       netif_carrier_off(dev); /* No MII device or no link 
partner report */
-               } else {
-                       mii_reg5 &= vp->advertising;
-                       if ((mii_reg5 & 0x0100) != 0    /* 100baseTx-FD */
-                                || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, 
but not 100-HD */
-                       vp->full_duplex = 1;
-                       netif_carrier_on(dev);
-               }
-               vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
-               if (vortex_debug > 1)
-                       printk(KERN_INFO "%s: MII #%d status %4.4x, link 
partner capability %4.4x,"
-                                  " info1 %04x, setting %s-duplex.\n",
-                                       dev->name, vp->phys[0],
-                                       mii_reg1, mii_reg5,
-                                       vp->info1, ((vp->info1 & 0x8000) || 
vp->full_duplex) ? "full" : "half");
-               EL3WINDOW(3);
-       }
-
-       /* Set the full-duplex bit. */
-       iowrite16(      ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-                       (vp->large_frames ? 0x40 : 0) |
-                       ((vp->full_duplex && vp->flow_ctrl && 
vp->partner_flow_ctrl) ? 0x100 : 0),
-                       ioaddr + Wn3_MAC_Ctrl);
-
-       if (vortex_debug > 1) {
-               printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n",
-                       dev->name, config);
-       }
-
-       issue_and_wait(dev, TxReset);
-       /*
-        * Don't reset the PHY - that upsets autonegotiation during DHCP 
operations.
-        */
-       issue_and_wait(dev, RxReset|0x04);
-
-       iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+       netif_carrier_off(dev);
+       if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY)
+               vortex_check_media(dev, 1);
 
        if (vortex_debug > 1) {
                EL3WINDOW(4);
@@ -1883,7 +1885,7 @@
        void __iomem *ioaddr = vp->ioaddr;
        int next_tick = 60*HZ;
        int ok = 0;
-       int media_status, mii_status, old_window;
+       int media_status, old_window;
 
        if (vortex_debug > 2) {
                printk(KERN_DEBUG "%s: Media selection timer tick happened, 
%s.\n",
@@ -1891,8 +1893,6 @@
                printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", 
dev->watchdog_timeo);
        }
 
-       if (vp->medialock)
-               goto leave_media_alone;
        disable_irq(dev->irq);
        old_window = ioread16(ioaddr + EL3_CMD) >> 13;
        EL3WINDOW(4);
@@ -1915,44 +1915,9 @@
                break;
        case XCVR_MII: case XCVR_NWAY:
                {
-                       spin_lock_bh(&vp->lock);
-                       mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
-                       if (!(mii_status & BMSR_LSTATUS)) {
-                               /* Re-read to get actual link status */
-                               mii_status = mdio_read(dev, vp->phys[0], 
MII_BMSR);
-                       }
                        ok = 1;
-                       if (vortex_debug > 2)
-                               printk(KERN_DEBUG "%s: MII transceiver has 
status %4.4x.\n",
-                                       dev->name, mii_status);
-                       if (mii_status & BMSR_LSTATUS) {
-                               int mii_reg5 = mdio_read(dev, vp->phys[0], 
MII_LPA);
-                               if (! vp->force_fd  &&  mii_reg5 != 0xffff) {
-                                       int duplex;
-
-                                       mii_reg5 &= vp->advertising;
-                                       duplex = (mii_reg5&0x0100) || (mii_reg5 
& 0x01C0) == 0x0040;
-                                       if (vp->full_duplex != duplex) {
-                                               vp->full_duplex = duplex;
-                                               printk(KERN_INFO "%s: Setting 
%s-duplex based on MII "
-                                                       "#%d link partner 
capability of %4.4x.\n",
-                                                       dev->name, 
vp->full_duplex ? "full" : "half",
-                                                       vp->phys[0], mii_reg5);
-                                               /* Set the full-duplex bit. */
-                                               EL3WINDOW(3);
-                                               iowrite16(      
(vp->full_duplex ? 0x20 : 0) |
-                                                               
(vp->large_frames ? 0x40 : 0) |
-                                                               
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
-                                                               ioaddr + 
Wn3_MAC_Ctrl);
-                                               if (vortex_debug > 1)
-                                                       printk(KERN_DEBUG 
"Setting duplex in Wn3_MAC_Ctrl\n");
-                                               /* AKPM: bug: should reset Tx 
and Rx after setting Duplex.  Page 180 */
-                                       }
-                               }
-                               netif_carrier_on(dev);
-                       } else {
-                               netif_carrier_off(dev);
-                       }
+                       spin_lock_bh(&vp->lock);
+                       vortex_check_media(dev, 0);
                        spin_unlock_bh(&vp->lock);
                }
                break;
@@ -1962,7 +1927,14 @@
                                 dev->name, media_tbl[dev->if_port].name, 
media_status);
                ok = 1;
        }
-       if ( ! ok) {
+
+       if (!netif_carrier_ok(dev))
+               next_tick = 5*HZ;
+
+       if (vp->medialock)
+               goto leave_media_alone;
+
+       if (!ok) {
                unsigned int config;
 
                do {
@@ -1995,10 +1967,10 @@
                        printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", 
config);
                /* AKPM: FIXME: Should reset Rx & Tx here.  P60 of 3c90xc.pdf */
        }
-       EL3WINDOW(old_window);
-       enable_irq(dev->irq);
 
 leave_media_alone:
+       EL3WINDOW(old_window);
+       enable_irq(dev->irq);
        if (vortex_debug > 2)
          printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
                         dev->name, media_tbl[dev->if_port].name);
@@ -2767,6 +2739,8 @@
        del_timer_sync(&vp->rx_oom_timer);
        del_timer_sync(&vp->timer);
 
+       netif_carrier_off(dev);
+
        /* Turn off statistics ASAP.  We update vp->stats below. */
        iowrite16(StatsDisable, ioaddr + EL3_CMD);
 
@@ -2967,20 +2941,6 @@
        return rc;
 }
 
-static u32 vortex_get_link(struct net_device *dev)
-{
-       struct vortex_private *vp = netdev_priv(dev);
-       void __iomem *ioaddr = vp->ioaddr;
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(&vp->lock, flags);
-       EL3WINDOW(4);
-       rc = mii_link_ok(&vp->mii);
-       spin_unlock_irqrestore(&vp->lock, flags);
-       return rc;
-}
-
 static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct vortex_private *vp = netdev_priv(dev);
@@ -3080,7 +3040,7 @@
        .get_stats_count        = vortex_get_stats_count,
        .get_settings           = vortex_get_settings,
        .set_settings           = vortex_set_settings,
-       .get_link               = vortex_get_link,
+       .get_link               = ethtool_op_get_link,
        .nway_reset             = vortex_nway_reset,
        .get_perm_addr                  = ethtool_op_get_perm_addr,
 };
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to