... > > 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