diff -Nuarp linux-2.5.25/drivers/net/e100/e100.h linux-2.5.25-e100/drivers/net/e100/e100.h --- linux-2.5.25/drivers/net/e100/e100.h Fri Jul 5 16:42:19 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100.h Sat Jul 6 10:39:22 2002 @@ -91,6 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE #include #include #include +#include #include #include #include @@ -147,6 +148,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE #define E100_MAX_SCB_WAIT 100 /* Max udelays in wait_scb */ #define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */ +/* HWI feature related constant */ +#define HWI_MAX_LOOP 100 +#define MAX_SAME_RESULTS 3 +#define HWI_REGISTER_GRANULARITY 80 /* register granularity = 80 Cm */ +#define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */ + /* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled. * In some situations, such as the TCP windowing algorithm, it may be * better to limit the growth of the bundle size than let it go as @@ -504,6 +511,7 @@ enum led_state_e { #define IS_ICH 0x00000020 #define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */ #define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */ +#define DF_LINK_FC_TX_ONLY 0x00000100 /* Received PAUSE frames are honored*/ typedef struct net_device_stats net_dev_stats_t; @@ -987,6 +995,18 @@ struct e100_private { rwlock_t isolate_lock; int driver_isolated; + char *id_string; + char *cable_status; + char *mdix_status; + + /* Variables for HWI */ + int saved_open_circut; + int saved_short_circut; + int saved_distance; + int saved_i; + int saved_same; + unsigned char hwi_started; + struct timer_list hwi_timer; /* hwi timer id */ u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ diff -Nuarp linux-2.5.25/drivers/net/e100/e100_config.c linux-2.5.25-e100/drivers/net/e100/e100_config.c --- linux-2.5.25/drivers/net/e100/e100_config.c Fri Jul 5 16:42:20 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_config.c Sat Jul 6 10:39:22 2002 @@ -308,85 +308,58 @@ exit: /** * e100_config_fc - config flow-control state - * @bdp: atapter's private data struct + * @bdp: adapter's private data struct * * This routine will enable or disable flow control support in the adapter's * config block. Flow control will be enable only if requested using the command * line option, and if the link is flow-contorl capable (both us and the link - * partner). - * - * Returns: - * true: if then option was indeed changed - * false: if no change was needed + * partner). But, if link partner is capable of autoneg, but not capable of + * flow control, received PAUSE frames are still honored. */ -unsigned char +void e100_config_fc(struct e100_private *bdp) { unsigned char enable = false; - unsigned char changed = false; - /* 82557 doesn't support fc. Don't touch this option */ if (!(bdp->flags & IS_BACHELOR)) - return false; + return; /* Enable fc if requested and if the link supports it */ - if ((bdp->params.b_params & PRM_FC) && (bdp->flags & DF_LINK_FC_CAP)) { + if ((bdp->params.b_params & PRM_FC) && (bdp->flags & + (DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) { enable = true; } spin_lock_bh(&(bdp->config_lock)); if (enable) { - - if (bdp->config[16] != DFLT_FC_DELAY_LSB) { + if (bdp->flags & DF_LINK_FC_TX_ONLY) { + /* If link partner is capable of autoneg, but */ + /* not capable of flow control, Received PAUSE */ + /* frames are still honored, i.e., */ + /* transmitted frames would be paused by */ + /* incoming PAUSE frames */ + bdp->config[16] = DFLT_NO_FC_DELAY_LSB; + bdp->config[17] = DFLT_NO_FC_DELAY_MSB; + bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART); + bdp->config[19] |= CB_CFIG_FC_REJECT; + bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; + } else { bdp->config[16] = DFLT_FC_DELAY_LSB; - E100_CONFIG(bdp, 16); - changed = true; - } - - if (bdp->config[17] != DFLT_FC_DELAY_LSB) { bdp->config[17] = DFLT_FC_DELAY_MSB; - E100_CONFIG(bdp, 17); - changed = true; - } - - /* check if *all* fc config options were already set */ - if (((bdp->config[19] & CB_CFIG_FC_OPTS) != CB_CFIG_FC_OPTS) || - (bdp->config[19] & CB_CFIG_TX_FC_DIS)) { - bdp->config[19] |= CB_CFIG_FC_OPTS; bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - E100_CONFIG(bdp, 19); - changed = true; } - } else { - if (bdp->config[16] != DFLT_NO_FC_DELAY_LSB) { - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - E100_CONFIG(bdp, 16); - changed = true; - } - - if (bdp->config[17] != DFLT_NO_FC_DELAY_MSB) { - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - E100_CONFIG(bdp, 17); - changed = true; - } - - /* check if *any* fc config options was already set */ - if ((bdp->config[19] & CB_CFIG_FC_OPTS) || - !(bdp->config[19] & CB_CFIG_TX_FC_DIS)) { - - bdp->config[19] &= ~CB_CFIG_FC_OPTS; - bdp->config[19] |= CB_CFIG_TX_FC_DIS; - E100_CONFIG(bdp, 19); - changed = true; - } + bdp->config[16] = DFLT_NO_FC_DELAY_LSB; + bdp->config[17] = DFLT_NO_FC_DELAY_MSB; + bdp->config[19] &= ~CB_CFIG_FC_OPTS; + bdp->config[19] |= CB_CFIG_TX_FC_DIS; } - + E100_CONFIG(bdp, 19); spin_unlock_bh(&(bdp->config_lock)); - return changed; + return; } /** diff -Nuarp linux-2.5.25/drivers/net/e100/e100_config.h linux-2.5.25-e100/drivers/net/e100/e100_config.h --- linux-2.5.25/drivers/net/e100/e100_config.h Fri Jul 5 16:42:14 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_config.h Sat Jul 6 10:39:22 2002 @@ -198,7 +198,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE extern void e100_config_init(struct e100_private *bdp); extern unsigned char e100_force_config(struct e100_private *bdp); extern unsigned char e100_config(struct e100_private *bdp); -extern unsigned char e100_config_fc(struct e100_private *bdp); +extern void e100_config_fc(struct e100_private *bdp); extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable); extern void e100_config_brdcast_dsbl(struct e100_private *bdp); extern void e100_config_mulcast_enbl(struct e100_private *bdp, diff -Nuarp linux-2.5.25/drivers/net/e100/e100_main.c linux-2.5.25-e100/drivers/net/e100/e100_main.c --- linux-2.5.25/drivers/net/e100/e100_main.c Fri Jul 5 16:42:23 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_main.c Sun Jul 7 20:39:17 2002 @@ -93,6 +93,30 @@ Portions (C) 2002 Red Hat, Inc. under th * * **********************************************************************/ +/* Change Log + * + * 2.1.6 7/5/02 + * o Added device ID support for Dell LOM. + * o Added device ID support for 82511QM mobile nics. + * o Bug fix: ethtool get/set EEPROM routines modified to use byte + * addressing rather than word addressing. + * o Feature: added MDIX mode support for 82550 and up. + * o Bug fix: added reboot notifer to setup WOL settings when + * shutting system down. + * o Cleanup: removed yield() redefinition (Andrew Morton, + * akpm@zip.com.au). + * o Bug fix: flow control now working when link partner is + * autoneg capable but not flow control capable. + * o Bug fix: added check for corrupted EEPROM + * o Bug fix: don't report checksum offloading for the older + * controllers that don't support the feature. + * o Bug fix: calculate cable diagnostics when link goes down + * rather than when queuering /proc file. + * o Cleanup: move mdi_access_lock to local get/set mdi routines. + * + * 2.0.30 5/30/02 + */ + #undef __NO_VERSION__ #include @@ -184,23 +208,24 @@ static void e100_non_tx_background(unsig /* Global Data structures and variables */ char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; - -#define E100_VERSION "2.0.30-k1" - -#define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver " - -const char *e100_version = E100_VERSION; -const char *e100_full_driver_name = E100_FULL_DRIVER_NAME E100_VERSION; -char *e100_short_driver_name = "e100"; +char e100_driver_version[]="2.1.6-k1"; +const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; +char e100_short_driver_name[] = "e100"; static int e100nics = 0; #ifdef CONFIG_PM -static int e100_save_state(struct pci_dev *pcid, u32 state); +static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e100_suspend(struct pci_dev *pcid, u32 state); -static int e100_enable_wake(struct pci_dev *pcid, u32 state, int enable); static int e100_resume(struct pci_dev *pcid); +struct notifier_block e100_notifier = { + notifier_call: e100_notify_reboot, + next: NULL, + priority: 0 +}; #endif +static void e100_get_mdix_status(struct e100_private *bdp); + /*********************************************************************/ /*! This is a GCC extension to ANSI C. * See the item "Labeled Elements in Initializers" in the section @@ -250,6 +275,7 @@ static void e100_rd_pwa_no(struct e100_p extern u16 e100_eeprom_read(struct e100_private *, u16); extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16); extern u16 e100_eeprom_size(struct e100_private *); +u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); static unsigned char e100_clr_cntrs(struct e100_private *); static unsigned char e100_load_microcode(struct e100_private *); @@ -391,6 +417,8 @@ u32 e100_rx_srv(struct e100_private *, u void e100_polling_tasklet(unsigned long); void e100_watchdog(struct net_device *); +static void e100_do_hwi(struct net_device *); +static void e100_hwi_restore(struct e100_private *); void e100_refresh_txthld(struct e100_private *); void e100_manage_adaptive_ifs(struct e100_private *); void e100_clear_pools(struct e100_private *); @@ -400,7 +428,7 @@ static inline tcb_t *e100_prepare_xmit_b static void e100_set_multi_exec(struct net_device *dev); MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION(E100_FULL_DRIVER_NAME E100_VERSION); +MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver"); MODULE_LICENSE("Dual BSD/GPL"); E100_PARAM(TxDescriptors, "Number of transmit descriptors"); @@ -580,6 +608,7 @@ e100_found1(struct pci_dev *pcid, const struct net_device *dev = NULL; struct e100_private *bdp = NULL; int rc = 0; + u16 cal_checksum, read_checksum; dev = alloc_etherdev(sizeof (struct e100_private)); if (dev == NULL) { @@ -592,7 +621,8 @@ e100_found1(struct pci_dev *pcid, const if (first_time) { first_time = false; - printk(KERN_NOTICE "%s\n", e100_full_driver_name); + printk(KERN_NOTICE "%s - version %s\n", + e100_full_driver_name, e100_driver_version); printk(KERN_NOTICE "%s\n", e100_copyright); printk(KERN_NOTICE "\n"); } @@ -622,6 +652,10 @@ e100_found1(struct pci_dev *pcid, const bdp->watchdog_timer.data = (unsigned long) dev; bdp->watchdog_timer.function = (void *) &e100_watchdog; + init_timer(&bdp->hwi_timer); + bdp->hwi_timer.data = (unsigned long) dev; + bdp->hwi_timer.function = (void *) &e100_do_hwi; + if ((rc = e100_pci_setup(pcid, bdp)) != 0) { goto err_dealloc; } @@ -657,6 +691,16 @@ e100_found1(struct pci_dev *pcid, const goto err_pci; } + /* Check if checksum is valid */ + cal_checksum = e100_eeprom_calculate_chksum(bdp); + read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1)); + if (cal_checksum != read_checksum) { + printk(KERN_ERR "e100: Corrupted EERPROM on instance #%d\n", + e100nics); + rc = -ENODEV; + goto err_pci; + } + dev->irq = pcid->irq; dev->open = &e100_open; dev->hard_start_xmit = &e100_xmit_frame; @@ -685,6 +729,17 @@ e100_found1(struct pci_dev *pcid, const printk(KERN_NOTICE "%s: %s\n", bdp->device->name, e100_get_brand_msg(bdp)); e100_print_brd_conf(bdp); + bdp->id_string = e100_get_brand_msg(bdp); + e100_get_mdix_status(bdp); + + if (netif_carrier_ok(bdp->device)) + bdp->cable_status = "Cable OK"; + else { + if (bdp->rev_id < D102_REV_ID) + bdp->cable_status = "Not supported"; + else + bdp->cable_status = "Not available"; + } if (e100_create_proc_subdir(bdp) < 0) { printk(KERN_ERR "Failed to create proc directory for %s\n", @@ -786,27 +841,33 @@ static struct pci_driver e100_driver = { id_table: e100_id_table, probe: e100_found1, remove: __devexit_p(e100_remove1), -#ifdef CONFIG_PM +#ifdef CONFIG_PM suspend: e100_suspend, resume: e100_resume, - save_state: e100_save_state, - enable_wake: e100_enable_wake, -#else - suspend: NULL, - resume: NULL, #endif }; static int __init e100_init_module(void) { - return pci_module_init(&e100_driver); + int ret; + ret = pci_module_init(&e100_driver); +#ifdef CONFIG_PM + if(ret >= 0) + register_reboot_notifier(&e100_notifier); +#endif + + return ret; } static void __exit e100_cleanup_module(void) { +#ifdef CONFIG_PM + unregister_reboot_notifier(&e100_notifier); +#endif + pci_unregister_driver(&e100_driver); } @@ -1665,7 +1726,7 @@ e100_watchdog(struct net_device *dev) if (!netif_running(dev)) { goto exit; } - spin_lock_bh(&(bdp->mdi_access_lock)); + e100_get_mdix_status(bdp); /* check if link state has changed */ if (e100_phy_check(bdp)) { @@ -1677,11 +1738,38 @@ e100_watchdog(struct net_device *dev) "Half" : "Full"); e100_config_fc(bdp); - e100_config(bdp); + e100_config(bdp); + bdp->cable_status = "Cable OK"; } else { printk(KERN_ERR "e100: %s NIC Link is Down\n", bdp->device->name); + if (bdp->rev_id < D102_REV_ID) + bdp->cable_status = "Not supported"; + else { + /* Initiate hwi, ie, cable diagnostic */ + bdp->saved_open_circut = 0xffff; + bdp->saved_short_circut = 0xffff; + bdp->saved_distance = 0xffff; + bdp->saved_i = 0; + bdp->saved_same = 0; + bdp->hwi_started = 1; + + /* Disable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_RESET_ALL_MASK); + + /* Set to 100 Full as required by hwi test */ + e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, + BMCR_SPEED100 | BMCR_FULLDPLX); + + /* Enable and execute HWI test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, + (HWI_TEST_ENABLE | HWI_TEST_EXECUTE)); + + /* Launch hwi timer in 1 msec */ + mod_timer(&(bdp->hwi_timer), jiffies + (HZ / 1000) ); + } } } @@ -1722,8 +1810,6 @@ e100_watchdog(struct net_device *dev) wmb(); - spin_unlock_bh(&(bdp->mdi_access_lock)); - /* relaunch watchdog timer in 2 sec */ mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); @@ -3051,8 +3137,10 @@ e100_print_brd_conf(struct e100_private /* Print the string if checksum Offloading was enabled */ if (bdp->flags & DF_CSUM_OFFLOAD) printk(KERN_NOTICE " Hardware receive checksums enabled\n"); - else - printk(KERN_NOTICE " Hardware receive checksums disabled\n"); + else { + if (bdp->rev_id >= D101MA_REV_ID) + printk(KERN_NOTICE " Hardware receive checksums disabled\n"); + } if ((bdp->flags & DF_UCODE_LOADED)) printk(KERN_NOTICE " cpu cycle saver enabled\n"); @@ -3151,6 +3239,13 @@ e100_isolate_driver(struct e100_private del_timer_sync(&bdp->watchdog_timer); + del_timer_sync(&bdp->hwi_timer); + /* If in middle of cable diag, */ + if (bdp->hwi_started) { + bdp->hwi_started = 0; + e100_hwi_restore(bdp); + } + if (netif_running(bdp->device)) netif_stop_queue(bdp->device); @@ -3382,9 +3477,7 @@ e100_ethtool_get_settings(struct net_dev } if (bdp->speed_duplex_caps & SUPPORTED_MII) { - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert); - spin_unlock_bh(&(bdp->mdi_access_lock)); if (advert & ADVERTISE_10HALF) ecmd.advertising |= ADVERTISED_10baseT_Half; @@ -3495,9 +3588,7 @@ e100_ethtool_glink(struct net_device *de bdp = dev->priv; info.cmd = ETHTOOL_GLINK; - spin_lock_bh(&(bdp->mdi_access_lock)); info.data = e100_get_link_state(bdp); - spin_unlock_bh(&(bdp->mdi_access_lock)); if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) return -EFAULT; @@ -3569,7 +3660,7 @@ e100_ethtool_get_drvinfo(struct net_devi bdp = dev->priv; strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1); - strncpy(info.version, e100_version, sizeof (info.version) - 1); + strncpy(info.version, e100_driver_version, sizeof (info.version) - 1); strncpy(info.fw_version, e100_get_brand_msg(bdp), sizeof (info.fw_version) - 1); strncpy(info.bus_info, bdp->pdev->slot_name, @@ -3595,8 +3686,9 @@ e100_ethtool_eeprom(struct net_device *d struct ethtool_eeprom ecmd; u16 eeprom_data[256]; u16 *usr_eeprom_ptr; - u16 word_length, word_offset; - int i; + u16 first_word, last_word; + int i, max_len; + void *ptr; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -3609,39 +3701,49 @@ e100_ethtool_eeprom(struct net_device *d usr_eeprom_ptr = (u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data)); - word_offset = (ecmd.offset >> 1); - if (word_offset >= bdp->eeprom_size) + max_len = bdp->eeprom_size * 2; + if ((ecmd.offset + ecmd.len) > max_len) + ecmd.len = (max_len - ecmd.offset); + + first_word = ecmd.offset >> 1; + last_word = (ecmd.offset + ecmd.len - 1) >> 1; + + if (first_word >= bdp->eeprom_size) return -EFAULT; - word_length = - min_t(u32, (ecmd.len >> 1), (bdp->eeprom_size - word_offset)); - if (ecmd.cmd == ETHTOOL_GEEPROM) { - for (i = word_offset; i < (word_length + word_offset); i++) - eeprom_data[i] = e100_eeprom_read(bdp, i); + for(i = 0; i <= (last_word - first_word); i++) + eeprom_data[i] = e100_eeprom_read(bdp, first_word + i); - ecmd.len = (word_length << 1); ecmd.magic = E100_EEPROM_MAGIC; if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; - if (copy_to_user(usr_eeprom_ptr, &(eeprom_data[word_offset]), - (ecmd.len << 1))) + if (copy_to_user(usr_eeprom_ptr, eeprom_data, ecmd.len)) return -EFAULT; } else { if (ecmd.magic != E100_EEPROM_MAGIC) return -EFAULT; - if (copy_from_user(&(eeprom_data[word_offset]), usr_eeprom_ptr, - (ecmd.len << 1))) - return -EFAULT; - - e100_eeprom_write_block(bdp, word_offset, - &(eeprom_data[word_offset]), - word_length); + ptr = (void *)eeprom_data; + if(ecmd.offset & 1) { + /* need modification of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + eeprom_data[0] = e100_eeprom_read(bdp, first_word); + ptr++; + } + if((ecmd.offset + ecmd.len) & 1) { + /* need modification of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + eeprom_data[last_word - first_word] = + e100_eeprom_read(bdp, last_word); + } + if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len)) + return -EFAULT; - ecmd.len = (word_length << 1); + e100_eeprom_write_block(bdp, first_word, eeprom_data, + last_word - first_word + 1); if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; @@ -3663,12 +3765,9 @@ e100_ethtool_eeprom(struct net_device *d static void e100_led_control(struct e100_private *bdp, u16 led_mdi_op) { - spin_lock_bh(&bdp->mdi_access_lock); - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, led_mdi_op); - spin_unlock_bh(&bdp->mdi_access_lock); } /** * e100_led_blink_callback @@ -3965,10 +4064,8 @@ e100_mii_ioctl(struct net_device *dev, s case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, &(data_ptr->val_out)); - spin_unlock_bh(&(bdp->mdi_access_lock)); break; case SIOCSMIIREG: @@ -3977,10 +4074,8 @@ e100_mii_ioctl(struct net_device *dev, s if (netif_running(dev)) { return -EBUSY; } - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_write(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, data_ptr->val_in); - spin_unlock_bh(&(bdp->mdi_access_lock)); break; default: @@ -4149,17 +4244,22 @@ exit: #ifdef CONFIG_PM static int -e100_save_state(struct pci_dev *pcid, u32 state) +e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) { - struct net_device *dev; - struct e100_private *bdp; - - /* Actually, PCI PM does NOT call this entry */ - if (!(dev = (struct net_device *) pci_get_drvdata(pcid))) - return -1; - bdp = dev->priv; - pci_save_state(pcid, bdp->pci_state); - return 0; + struct pci_dev *pdev = NULL; + switch(event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + pci_for_each_dev(pdev) { + if(pci_dev_driver(pdev) == &e100_driver) { + /* If net_device struct is allocated? */ + if (pci_get_drvdata(pdev)) + e100_suspend(pdev, 3); + } + } + } + return NOTIFY_DONE; } static int @@ -4169,7 +4269,7 @@ e100_suspend(struct pci_dev *pcid, u32 s struct e100_private *bdp = netdev->priv; e100_isolate_driver(bdp); - e100_save_state(pcid, state); + pci_save_state(pcid, bdp->pci_state); /* If wol is enabled */ #ifdef ETHTOOL_GWOL @@ -4218,12 +4318,126 @@ e100_resume(struct pci_dev *pcid) return 0; } -static int -e100_enable_wake(struct pci_dev *pcid, u32 state, int enable) +#endif /* CONFIG_PM */ + +static void +e100_get_mdix_status(struct e100_private *bdp) +{ + if (bdp->rev_id < D102_REV_ID) { + if (netif_carrier_ok(bdp->device)) + bdp->mdix_status = "MDI"; + else + bdp->mdix_status = "None"; + } else { + u16 ctrl_reg; + /* Read the MDIX control register */ + e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &ctrl_reg); + if (ctrl_reg & MDI_MDIX_CONFIG_IS_OK) { + if (ctrl_reg & MDI_MDIX_STATUS) + bdp->mdix_status = "MDI-X"; + else + bdp->mdix_status = "MDI"; + } else + bdp->mdix_status = "None"; + } +} + +static void +e100_do_hwi(struct net_device *dev) { - /* Driver doesn't need to do anything because it will enable */ - /* wol when suspended. */ - /* Actually, PCI PM does NOT call this entry. */ - return 0; + struct e100_private *bdp = dev->priv; + u16 ctrl_reg; + int distance, open_circut, short_circut; + + e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg); + + distance = ctrl_reg & HWI_TEST_DISTANCE; + open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM; + short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM; + + if ((distance == bdp->saved_distance) && + (open_circut == bdp->saved_open_circut) && + (short_circut == bdp->saved_short_circut)) + bdp->saved_same++; + else { + bdp->saved_same = 0; + bdp->saved_distance = distance; + bdp->saved_open_circut = open_circut; + bdp->saved_short_circut = short_circut; + } + + if (bdp->saved_same == MAX_SAME_RESULTS) { + if ((open_circut && !(short_circut)) || + (!(open_circut) && short_circut)) { + + u8 near_end = ((distance * HWI_REGISTER_GRANULARITY) < + HWI_NEAR_END_BOUNDARY); + if (open_circut) { + if (near_end) + bdp->cable_status = "Open Circut Near End"; + else + bdp->cable_status = "Open Circut Far End"; + } else { + if (near_end) + bdp->cable_status = "Short Circut Near End"; + else + bdp->cable_status = "Short Circut Far End"; + } + goto done; + } + } + else if (bdp->saved_i == HWI_MAX_LOOP) { + bdp->cable_status = "Test failed"; + goto done; + } + + /* Do another hwi test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, + (HWI_TEST_ENABLE | HWI_TEST_EXECUTE)); + bdp->saved_i++; + /* relaunch hwi timer in 1 msec */ + mod_timer(&(bdp->hwi_timer), jiffies + (HZ / 1000) ); + return; + +done: + e100_hwi_restore(bdp); + bdp->hwi_started = 0; + return; +} + +static void e100_hwi_restore(struct e100_private *bdp) +{ + u16 control = 0; + + /* Restore speed, duplex and autoneg before */ + /* hwi test, i.e., cable diagnostic */ + + /* Reset hwi test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, HWI_RESET_ALL_MASK); + + if ((bdp->params.e100_speed_duplex == E100_AUTONEG) && + (bdp->rev_id >= D102_REV_ID)) + /* Enable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_AUTO_SWITCH_ENABLE); + + switch (bdp->params.e100_speed_duplex) { + case E100_SPEED_10_HALF: + break; + case E100_SPEED_10_FULL: + control = BMCR_FULLDPLX; + break; + case E100_SPEED_100_HALF: + control = BMCR_SPEED100; + break; + case E100_SPEED_100_FULL: + control = BMCR_SPEED100 | BMCR_FULLDPLX; + break; + case E100_AUTONEG: + control = BMCR_ANENABLE | BMCR_ANRESTART; + break; + } + /* Restore original speed/duplex */ + e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); + return; } -#endif /* CONFIG_PM */ diff -Nuarp linux-2.5.25/drivers/net/e100/e100_phy.c linux-2.5.25-e100/drivers/net/e100/e100_phy.c --- linux-2.5.25/drivers/net/e100/e100_phy.c Fri Jul 5 16:42:01 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_phy.c Sat Jul 6 10:39:22 2002 @@ -96,6 +96,7 @@ e100_mdi_write(struct e100_private *bdp, int e100_retry; u32 temp_val; + spin_lock_bh(&bdp->mdi_access_lock); temp_val = (((u32) data) | (reg_addr << 16) | (phy_addr << 21) | (MDI_WRITE << 26)); writel(temp_val, &bdp->scb->scb_mdi_cntrl); @@ -111,6 +112,7 @@ e100_mdi_write(struct e100_private *bdp, udelay(20); e100_retry--; } + spin_unlock_bh(&bdp->mdi_access_lock); } /* @@ -138,6 +140,7 @@ e100_mdi_read(struct e100_private *bdp, int e100_retry; u32 temp_val; + spin_lock_bh(&bdp->mdi_access_lock); /* Issue the read command to the MDI control register. */ temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26)); writel(temp_val, &bdp->scb->scb_mdi_cntrl); @@ -156,6 +159,7 @@ e100_mdi_read(struct e100_private *bdp, // return the lower word *data = (u16) readl(&bdp->scb->scb_mdi_cntrl); + spin_unlock_bh(&bdp->mdi_access_lock); } static unsigned char __devinit @@ -657,8 +661,6 @@ e100_force_speed_duplex(struct e100_priv bdp->flags |= DF_SPEED_FORCED; - spin_lock_bh(&(bdp->mdi_access_lock)); - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); control &= ~BMCR_ANENABLE; @@ -702,14 +704,10 @@ e100_force_speed_duplex(struct e100_priv time_after(jiffies, expires)) { break; } else { - spin_unlock_bh(&(bdp->mdi_access_lock)); yield(); - spin_lock_bh(&(bdp->mdi_access_lock)); } } while (true); - - spin_unlock_bh(&(bdp->mdi_access_lock)); } /* @@ -753,7 +751,12 @@ e100_set_fc(struct e100_private *bdp) if (ad_reg & NWAY_AD_FC_SUPPORTED) bdp->flags |= DF_LINK_FC_CAP; else - bdp->flags &= ~DF_LINK_FC_CAP; + /* If link partner is capable of autoneg, but */ + /* not capable of flow control, Received PAUSE */ + /* frames are still honored, i.e., */ + /* transmitted frames would be paused */ + /* by incoming PAUSE frames */ + bdp->flags |= DF_LINK_FC_TX_ONLY; } else { bdp->flags &= ~DF_LINK_FC_CAP; @@ -821,8 +824,6 @@ e100_auto_neg(struct e100_private *bdp, bdp->flags &= ~DF_SPEED_FORCED; - spin_lock_bh(&(bdp->mdi_access_lock)); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); @@ -848,25 +849,30 @@ e100_auto_neg(struct e100_private *bdp, time_after(jiffies, expires) ) { goto exit; } else { - spin_unlock_bh(&(bdp->mdi_access_lock)); yield(); - spin_lock_bh(&(bdp->mdi_access_lock)); } } while (true); } exit: e100_find_speed_duplex(bdp); - spin_unlock_bh(&(bdp->mdi_access_lock)); } void e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart) { if (bdp->params.e100_speed_duplex == E100_AUTONEG) { + if (bdp->rev_id >= D102_REV_ID) + /* Enable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_AUTO_SWITCH_ENABLE); e100_auto_neg(bdp, force_restart); } else { + if (bdp->rev_id >= D102_REV_ID) + /* Disable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_RESET_ALL_MASK); e100_force_speed_duplex(bdp); } diff -Nuarp linux-2.5.25/drivers/net/e100/e100_proc.c linux-2.5.25-e100/drivers/net/e100/e100_proc.c --- linux-2.5.25/drivers/net/e100/e100_proc.c Fri Jul 5 16:42:21 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_proc.c Sat Jul 6 10:39:23 2002 @@ -106,8 +106,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE static struct proc_dir_entry *adapters_proc_dir = 0; /* externs from e100_main.c */ -extern const char *e100_short_driver_name; -extern const char *e100_version; +extern char e100_short_driver_name[]; +extern char e100_driver_version[]; extern struct net_device_stats *e100_get_stats(struct net_device *dev); extern char *e100_get_brand_msg(struct e100_private *bdp); extern void e100_mdi_write(struct e100_private *, u32, u32, u16); @@ -191,7 +191,7 @@ read_descr(char *page, char **start, off struct e100_private *bdp = data; int len; - len = sprintf(page, "%s\n", e100_get_brand_msg(bdp)); + len = sprintf(page, "%s\n", bdp->id_string); return generic_read(page, start, off, count, eof, len); } @@ -223,23 +223,15 @@ read_part_number(char *page, char **star static void set_led(struct e100_private *bdp, u16 led_mdi_op) { - spin_lock_bh(&bdp->mdi_access_lock); - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, led_mdi_op); - spin_unlock_bh(&bdp->mdi_access_lock); - set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(MDI_SLEEP_TIME); - spin_lock_bh(&bdp->mdi_access_lock); - /* turn led ownership to the chip */ e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, PHY_82555_LED_NORMAL_CONTROL); - - spin_unlock_bh(&bdp->mdi_access_lock); } static int @@ -351,6 +343,7 @@ read_info(char *page, char **start, off_ } #ifdef E100_EOU +#ifdef MODULE /********************** * parameter entries **********************/ @@ -677,6 +670,7 @@ static e100_proc_entry e100_proc_params[ {"PollingMaxWork.val", read_gen_prm, 0, bdp_prm_off(PollingMaxWork)}, {"", 0, 0, 0} }; +#endif /* MODULE */ #endif /* E100_EOU */ static struct proc_dir_entry * __devinit @@ -706,6 +700,7 @@ create_proc_rw(char *name, void *data, s } #ifdef E100_EOU +#ifdef MODULE static int __devinit create_proc_param_subdir(struct e100_private *bdp, struct proc_dir_entry *dev_dir) @@ -755,7 +750,8 @@ remove_proc_param_subdir(struct proc_dir remove_proc_entry("LoadParameters", parent); } -#endif /* E100_EOU */ +#endif /* MODULE */ +#endif void e100_remove_proc_subdir(struct e100_private *bdp) @@ -781,9 +777,11 @@ e100_remove_proc_subdir(struct e100_priv remove_proc_entry(pe->name, bdp->proc_parent); } -#ifdef E100_EOU +#ifdef E100_EOU +#ifdef MODULE remove_proc_param_subdir(bdp->proc_parent); #endif +#endif remove_proc_entry(bdp->device->name, adapters_proc_dir); bdp->proc_parent = NULL; } @@ -844,12 +842,14 @@ e100_create_proc_subdir(struct e100_priv } } -#ifdef E100_EOU +#ifdef E100_EOU +#ifdef MODULE if (create_proc_param_subdir(bdp, dev_dir)) { e100_remove_proc_subdir(bdp); return -ENOMEM; } #endif +#endif return 0; } diff -Nuarp linux-2.5.25/drivers/net/e100/e100_vendor.h linux-2.5.25-e100/drivers/net/e100/e100_vendor.h --- linux-2.5.25/drivers/net/e100/e100_vendor.h Fri Jul 5 16:42:33 2002 +++ linux-2.5.25-e100/drivers/net/e100/e100_vendor.h Sat Jul 6 10:39:23 2002 @@ -125,6 +125,7 @@ enum e100_device_type { E100_82559_LOM, E100_82559_LOM_AOL, E100_82559_LOM_AOL2, + E100_82559_LOM_DELL, E100_IBM_MDS, E100_CMPQ_S, E100_PROVE_DA, @@ -132,7 +133,8 @@ enum e100_device_type { E100_PROVE_LOM, E100_PROVE_NET, E100_82562, - E100_ALL_BOARDS, + E100_82551QM, + E100_ALL_BOARDS }; struct e100_vendor_info e100_vendor_info_array[] = { @@ -147,6 +149,7 @@ struct e100_vendor_info e100_vendor_info { E100_BRD_100, "Intel(R) PRO/100+ PCI Adapter"}, { E100_BRD_100M, "Intel(R) PRO/100+ Management Adapter"}, { E100_BRD_AOL2, "Intel(R) PRO/100+ Alert on LAN* 2 Management Adapter"}, + { E100_82559_LOM_DELL, "Intel(R) 8255x Based Network Connection"}, { E100_BRD_AOL, "Intel(R) PRO/100+ Alert on LAN* Management Adapter"}, { E100_PROS_M, "Intel(R) PRO/100 S Management Adapter"}, { E100_PROS_AM, "Intel(R) PRO/100 S Advanced Management Adapter"}, @@ -186,6 +189,7 @@ struct e100_vendor_info e100_vendor_info { E100_PROVE_LOM, "Intel(R) PRO/100 VE Network ConnectionPLC LOM" }, { E100_PROVE_NET, "Intel(R) PRO/100 VE Network Connection"}, { E100_82562, "Intel(R)82562 based Fast Ethernet Connection"}, + { E100_82551QM, "Intel(R) PRO/100 M Mobile Connection"}, { E100_ALL_BOARDS, "Intel(R) 8255x-based Ethernet Adapter"}, {0,NULL} }; @@ -309,6 +313,7 @@ static struct pci_device_id e100_id_tabl {0x8086, 0x1229, 0x0E11, 0xB144, 0, 0, E100_CMPQ_S}, {0x8086, 0x1229, 0x0E11, 0xB163, 0, 0, E100_CMPQ_S}, {0x8086, 0x1229, 0x0E11, 0xB164, 0, 0, E100_CMPQ_S}, + {0x8086, 0x1229, 0x1028, PCI_ANY_ID, 0, 0, E100_82559_LOM_DELL}, {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x2449, 0x1014, 0x0265, 0, 0, E100_PROVE_D}, @@ -324,7 +329,11 @@ static struct pci_device_id e100_id_tabl {0x8086, 0x2449, 0x0E11, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, {0x8086, 0x2449, 0x1014, PCI_ANY_ID, 0, 0, E100_PROVE_D}, {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - + + {0x8086, 0x1059, 0x1179, 0x0005, 0, 0, E100_82551QM}, + {0x8086, 0x1059, 0x1033, 0x8191, 0, 0, E100_82551QM}, + {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82551QM}, + {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, .