Hi, On Sat, Dec 29, 2007 at 09:54:45PM -0800, Kok, Auke wrote: > ok, barely glanced over the patch but it might just be fine. Can you split up > this > patch and send a separate patch for the spelling mistakes? I'll then have some > quick testing done on the result and do a bit deeper review after newyears.
Thanks for your quick reply! OK, here's part 1, the MII-less support stuff. (preliminary posting, for review only) Note that these diffs apply to 2.6.24-rc6-mm1 without much trouble, thus might want to do -mm testing soon. Signed-off-by: Andreas Mohr <[EMAIL PROTECTED]> --- linux-2.6.24-rc6/drivers/net/e100.c 2008-01-01 12:57:06.000000000 +0100 +++ linux-2.6.24-rc6/drivers/net/e100.c 2008-01-01 16:17:45.000000000 +0100 @@ -251,6 +251,7 @@ mac_unknown = 0xFF, }; +/* FIXME: these are unused: what the heck?? */ enum phy { phy_100a = 0x000003E0, phy_100c = 0x035002A8, @@ -352,8 +353,12 @@ op_ewen = 0x13, }; +enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240, + S80C24, I82555, DP83840A=10, }; + enum eeprom_offsets { eeprom_cnfg_mdix = 0x03, + eeprom_phy_iface = 0x06, eeprom_id = 0x0A, eeprom_config_asf = 0x0D, eeprom_smbus_addr = 0x90, @@ -553,6 +558,7 @@ multicast_all = (1 << 2), wol_magic = (1 << 3), ich_10h_workaround = (1 << 4), + phy_is_non_mii = (1 << 5), } flags ____cacheline_aligned; enum mac mac; @@ -596,6 +602,11 @@ (void)ioread8(&nic->csr->scb.status); } +static inline int e100_phy_supports_mii(struct nic *nic) +{ + return ((nic->flags & phy_is_non_mii) == 0); +} + static void e100_enable_irq(struct nic *nic) { unsigned long flags; @@ -980,7 +991,8 @@ config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ + if (e100_phy_supports_mii(nic)) + config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ config->pad10 = 0x6; config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ @@ -1350,6 +1362,42 @@ offsetof(struct mem, dump_buf)); } +static int e100_phy_check_without_mii(struct nic *nic) +{ + u8 phy_type; + int without_mii; + + phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; + + switch (phy_type) { + case NonSuchPhy: /* Non-MII PHY; UNTESTED! */ + case I82503: /* Non-MII PHY; UNTESTED! */ + case S80C24: /* Non-MII PHY; tested and working */ + { + /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": + * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter + * doesn't have a programming interface of any sort. The + * media is sensed automatically based on how the link partner + * is configured. This is, in essence, manual configuration. + */ + DPRINTK(PROBE, INFO, "found MII-less i82503 or 80c24 or other PHY\n"); + nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ + + /* these might be needed for certain MII-less cards... + * nic->flags |= ich; + * nic->flags |= ich_10h_workaround; */ + + nic->flags |= phy_is_non_mii; + without_mii = 1; + } + break; + default: + without_mii = 0; + break; + } + return without_mii; +} + #define NCONFIG_AUTO_SWITCH 0x0080 #define MII_NSC_CONG MII_RESV1 #define NSC_CONG_ENABLE 0x0100 @@ -1370,9 +1418,21 @@ if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) break; } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; + if(addr == 32) { + /* uhoh, no PHY detected: check whether we seem to be some + * weird, rare variant which is *known* to not have any MII. + * But do this AFTER MII checking only, since this does + * lookup of EEPROM values which may easily be unreliable. */ + if (e100_phy_check_without_mii(nic)) + return 0; /* simply return and hope for the best */ + else { + /* for unknown cases log a fatal error */ + DPRINTK(HW, ERR, "Failed to locate any PHY, aborting.\n"); + return -EAGAIN; + } + } + else + DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); /* Selected the phy and isolate the rest */ for(addr = 0; addr < 32; addr++) { @@ -1568,19 +1628,25 @@ DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - /* mii library handles link maintenance tasks */ + if (e100_phy_supports_mii(nic)) { + /* MII library handles link maintenance tasks */ - mii_ethtool_gset(&nic->mii, &cmd); + mii_ethtool_gset(&nic->mii, &cmd); - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } + if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { + DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", + cmd.speed == SPEED_100 ? "100" : "10", + cmd.duplex == DUPLEX_FULL ? "full" : "half"); + } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { + DPRINTK(LINK, INFO, "link down\n"); + } - mii_check_link(&nic->mii); + mii_check_link(&nic->mii); + } else { + /* since MII API activates carrier internally, + * we have to do this manually for MII-less hardware */ + netif_carrier_on(nic->netdev); + } /* Software generated interrupt to recover from (rare) Rx * allocation failure. @@ -2180,6 +2246,9 @@ led_on_557 = 0x07, }; + if (!e100_phy_supports_mii(nic)) + return; + nic->leds = (nic->leds & led_on) ? led_off : (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); @@ -2189,6 +2258,10 @@ static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { struct nic *nic = netdev_priv(netdev); + + if (!e100_phy_supports_mii(nic)) + return -EINVAL; + return mii_ethtool_gset(&nic->mii, cmd); } @@ -2197,6 +2270,9 @@ struct nic *nic = netdev_priv(netdev); int err; + if (!e100_phy_supports_mii(nic)) + return -EINVAL; + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); err = mii_ethtool_sset(&nic->mii, cmd); e100_exec_cb(nic, NULL, e100_configure); @@ -2281,12 +2357,20 @@ static int e100_nway_reset(struct net_device *netdev) { struct nic *nic = netdev_priv(netdev); + + if (!e100_phy_supports_mii(nic)) + return 0; /* "success" */ + return mii_nway_restart(&nic->mii); } static u32 e100_get_link(struct net_device *netdev) { struct nic *nic = netdev_priv(netdev); + + if (!e100_phy_supports_mii(nic)) + return 1; /* "link ok" */ + return mii_link_ok(&nic->mii); } @@ -2379,6 +2463,9 @@ struct nic *nic = netdev_priv(netdev); int i, err; + if (!e100_phy_supports_mii(nic)) + return; + memset(data, 0, E100_TEST_LEN * sizeof(u64)); data[0] = !mii_link_ok(&nic->mii); data[1] = e100_eeprom_load(nic); @@ -2409,6 +2496,9 @@ { struct nic *nic = netdev_priv(netdev); + if (!e100_phy_supports_mii(nic)) + return 0; + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); mod_timer(&nic->blink_timer, jiffies); @@ -2505,6 +2595,9 @@ { struct nic *nic = netdev_priv(netdev); + if (!e100_phy_supports_mii(nic)) + return -EINVAL; + return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); } -- 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