Commit 81c830a4 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/jgarzik/net-drivers-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 01166d96 cd8286cf
...@@ -671,7 +671,7 @@ static void arcnet_timeout(struct net_device *dev) ...@@ -671,7 +671,7 @@ static void arcnet_timeout(struct net_device *dev)
* interrupts. Establish which device needs attention, and call the correct * interrupts. Establish which device needs attention, and call the correct
* chipset interrupt handler. * chipset interrupt handler.
*/ */
void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct arcnet_local *lp; struct arcnet_local *lp;
...@@ -696,7 +696,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -696,7 +696,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ACOMMAND(CFLAGScmd | RESETclear); ACOMMAND(CFLAGScmd | RESETclear);
AINTMASK(0); AINTMASK(0);
spin_unlock(&arcnet_lock); spin_unlock(&arcnet_lock);
return; return IRQ_HANDLED;
} }
BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
...@@ -864,6 +864,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -864,6 +864,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
AINTMASK(lp->intmask); AINTMASK(lp->intmask);
spin_unlock(&arcnet_lock); spin_unlock(&arcnet_lock);
return IRQ_RETVAL(didsomething);
} }
......
...@@ -60,7 +60,14 @@ ...@@ -60,7 +60,14 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/mii.h> #include <linux/mii.h>
#define E100_REGS_LEN 1 #define E100_CABLE_UNKNOWN 0
#define E100_CABLE_OK 1
#define E100_CABLE_OPEN_NEAR 2 /* Open Circuit Near End */
#define E100_CABLE_OPEN_FAR 3 /* Open Circuit Far End */
#define E100_CABLE_SHORT_NEAR 4 /* Short Circuit Near End */
#define E100_CABLE_SHORT_FAR 5 /* Short Circuit Far End */
#define E100_REGS_LEN 2
/* /*
* Configure parameters for buffers per controller. * Configure parameters for buffers per controller.
* If the machine this is being used on is a faster machine (i.e. > 150MHz) * If the machine this is being used on is a faster machine (i.e. > 150MHz)
...@@ -105,8 +112,6 @@ ...@@ -105,8 +112,6 @@
#define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */ #define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */
/* HWI feature related constant */ /* 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_REGISTER_GRANULARITY 80 /* register granularity = 80 Cm */
#define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */ #define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */
...@@ -942,7 +947,6 @@ struct e100_private { ...@@ -942,7 +947,6 @@ struct e100_private {
#ifdef CONFIG_PM #ifdef CONFIG_PM
u32 pci_state[16]; u32 pci_state[16];
#endif #endif
char ifname[IFNAMSIZ];
#ifdef E100_CU_DEBUG #ifdef E100_CU_DEBUG
u8 last_cmd; u8 last_cmd;
u8 last_sub_cmd; u8 last_sub_cmd;
...@@ -956,7 +960,10 @@ struct e100_private { ...@@ -956,7 +960,10 @@ struct e100_private {
#define E100_SPEED_100_FULL 4 #define E100_SPEED_100_FULL 4
/********* function prototypes *************/ /********* function prototypes *************/
extern int e100_open(struct net_device *);
extern int e100_close(struct net_device *);
extern void e100_isolate_driver(struct e100_private *bdp); extern void e100_isolate_driver(struct e100_private *bdp);
extern unsigned char e100_hw_init(struct e100_private *);
extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd); extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd);
extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb); extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb);
extern void e100_free_non_tx_cmd(struct e100_private *bdp, extern void e100_free_non_tx_cmd(struct e100_private *bdp,
...@@ -981,14 +988,13 @@ extern unsigned char e100_cu_unknown_state(struct e100_private *bdp); ...@@ -981,14 +988,13 @@ extern unsigned char e100_cu_unknown_state(struct e100_private *bdp);
#define TEST_TIMEOUT 0x08 #define TEST_TIMEOUT 0x08
enum test_offsets { enum test_offsets {
E100_EEPROM_TEST_FAIL = 0, test_link,
E100_CHIP_TIMEOUT, test_eeprom,
E100_ROM_TEST_FAIL, test_self_test,
E100_REG_TEST_FAIL, test_loopback_mac,
E100_MAC_TEST_FAIL, test_loopback_phy,
E100_LPBK_MAC_FAIL, cable_diag,
E100_LPBK_PHY_FAIL, max_test_res, /* must be last */
E100_MAX_TEST_RES
}; };
#endif #endif
...@@ -45,6 +45,24 @@ ...@@ -45,6 +45,24 @@
**********************************************************************/ **********************************************************************/
/* Change Log /* Change Log
*
* 2.3.13 05/08/03
* o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely
* o Feature remove: IDIAG support (use ethtool -t instead)
* o Cleanup: fixed spelling mistakes found by community
* o Feature add: ethtool cable diag test
* o Feature add: ethtool parameter support (ring size, xsum, flow ctrl)
* o Cleanup: move e100_asf_enable under CONFIG_PM to avoid warning
* [Stephen Rothwell (sfr@canb.auug.org.au)]
* o Bug fix: don't call any netif_carrier_* until netdev registered.
* [Andrew Morton (akpm@digeo.com)]
* o Cleanup: replace (skb->len - skb->data_len) with skb_headlen(skb)
* [jmorris@intercode.com.au]
* o Bug fix: cleanup of Tx skbs after running ethtool diags
* o Bug fix: incorrect reporting of ethtool diag overall results
* o Bug fix: must hold xmit_lock before stopping queue in ethtool
* operations that require reset h/w and driver structures.
* o Bug fix: statistic command failure would stop statistic collection.
* *
* 2.2.21 02/11/03 * 2.2.21 02/11/03
* o Removed marketing brand strings. Instead, Using generic string * o Removed marketing brand strings. Instead, Using generic string
...@@ -61,21 +79,6 @@ ...@@ -61,21 +79,6 @@
* o New feature: added ICH5 support * o New feature: added ICH5 support
* *
* 2.1.27 11/20/02 * 2.1.27 11/20/02
* o Bug fix: Device command timeout due to SMBus processing during init
* o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly
* o Bug fix: Not using EEPROM WoL setting as default in ethtool
* o Bug fix: Not able to set autoneg on using ethtool when interface down
* o Bug fix: Not able to change speed/duplex using ethtool/mii
* when interface up
* o Bug fix: Ethtool shows autoneg on when forced to 100/Full
* o Bug fix: Compiler error when CONFIG_PROC_FS not defined
* o Bug fix: 2.5.44 e100 doesn't load with preemptive kernel enabled
* (sleep while holding spinlock)
* o Bug fix: 2.1.24-k1 doesn't display complete statistics
* o Bug fix: System panic due to NULL watchdog timer dereference during
* ifconfig down, rmmod and insmod
*
* 2.1.24 10/7/02
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -121,14 +124,13 @@ extern void e100_config_wol(struct e100_private *bdp); ...@@ -121,14 +124,13 @@ extern void e100_config_wol(struct e100_private *bdp);
extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags); extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
static int e100_ethtool_test(struct net_device *, struct ifreq *); static int e100_ethtool_test(struct net_device *, struct ifreq *);
static int e100_ethtool_gstrings(struct net_device *, struct ifreq *); static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
static char *test_strings[] = { static char test_strings[][ETH_GSTRING_LEN] = {
"E100_EEPROM_TEST_FAIL", "Link test (on/offline)",
"E100_CHIP_TIMEOUT", "Eeprom test (on/offline)",
"E100_ROM_TEST_FAIL", "Self test (offline)",
"E100_REG_TEST_FAIL", "Mac loopback (offline)",
"E100_MAC_TEST_FAIL", "Phy loopback (offline)",
"E100_LPBK_MAC_FAIL", "Cable diagnostic (offline)"
"E100_LPBK_PHY_FAIL"
}; };
static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
...@@ -139,10 +141,10 @@ static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, ...@@ -139,10 +141,10 @@ static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *,
nxmit_cb_entry_t *); nxmit_cb_entry_t *);
static void e100_free_nontx_list(struct e100_private *); static void e100_free_nontx_list(struct e100_private *);
static void e100_non_tx_background(unsigned long); static void e100_non_tx_background(unsigned long);
static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
/* Global Data structures and variables */ /* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation"; char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
char e100_driver_version[]="2.2.21-k1"; char e100_driver_version[]="2.3.13-k1";
const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
char e100_short_driver_name[] = "e100"; char e100_short_driver_name[] = "e100";
static int e100nics = 0; static int e100nics = 0;
...@@ -155,6 +157,7 @@ static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); ...@@ -155,6 +157,7 @@ static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); 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_suspend(struct pci_dev *pcid, u32 state);
static int e100_resume(struct pci_dev *pcid); static int e100_resume(struct pci_dev *pcid);
static unsigned char e100_asf_enabled(struct e100_private *bdp);
struct notifier_block e100_notifier_reboot = { struct notifier_block e100_notifier_reboot = {
.notifier_call = e100_notify_reboot, .notifier_call = e100_notify_reboot,
.next = NULL, .next = NULL,
...@@ -182,8 +185,6 @@ struct notifier_block e100_notifier_reboot = { ...@@ -182,8 +185,6 @@ struct notifier_block e100_notifier_reboot = {
static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *); static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *);
static u8 e100_D102_check_checksum(rfd_t *); static u8 e100_D102_check_checksum(rfd_t *);
static int e100_ioctl(struct net_device *, struct ifreq *, int); static int e100_ioctl(struct net_device *, struct ifreq *, int);
static int e100_open(struct net_device *);
static int e100_close(struct net_device *);
static int e100_change_mtu(struct net_device *, int); static int e100_change_mtu(struct net_device *, int);
static int e100_xmit_frame(struct sk_buff *, struct net_device *); static int e100_xmit_frame(struct sk_buff *, struct net_device *);
static unsigned char e100_init(struct e100_private *); static unsigned char e100_init(struct e100_private *);
...@@ -193,7 +194,6 @@ struct net_device_stats *e100_get_stats(struct net_device *); ...@@ -193,7 +194,6 @@ struct net_device_stats *e100_get_stats(struct net_device *);
static irqreturn_t e100intr(int, void *, struct pt_regs *); static irqreturn_t e100intr(int, void *, struct pt_regs *);
static void e100_print_brd_conf(struct e100_private *); static void e100_print_brd_conf(struct e100_private *);
static void e100_set_multi(struct net_device *); static void e100_set_multi(struct net_device *);
void e100_set_speed_duplex(struct e100_private *);
static u8 e100_pci_setup(struct pci_dev *, struct e100_private *); static u8 e100_pci_setup(struct pci_dev *, struct e100_private *);
static u8 e100_sw_init(struct e100_private *); static u8 e100_sw_init(struct e100_private *);
...@@ -215,7 +215,6 @@ u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); ...@@ -215,7 +215,6 @@ u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
static unsigned char e100_clr_cntrs(struct e100_private *); static unsigned char e100_clr_cntrs(struct e100_private *);
static unsigned char e100_load_microcode(struct e100_private *); static unsigned char e100_load_microcode(struct e100_private *);
static unsigned char e100_hw_init(struct e100_private *);
static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *); static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *);
static unsigned char e100_update_stats(struct e100_private *bdp); static unsigned char e100_update_stats(struct e100_private *bdp);
...@@ -228,7 +227,6 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int, ...@@ -228,7 +227,6 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
char *); char *);
unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8); unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
void e100_exec_cmplx(struct e100_private *, u32, u8); void e100_exec_cmplx(struct e100_private *, u32, u8);
static unsigned char e100_asf_enabled(struct e100_private *bdp);
/** /**
* e100_get_rx_struct - retrieve cell to hold skb buff from the pool * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
...@@ -616,6 +614,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -616,6 +614,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
goto err_dealloc; goto err_dealloc;
} }
if ((rc = register_netdev(dev)) != 0) {
goto err_pci;
}
if (((bdp->pdev->device > 0x1030) if (((bdp->pdev->device > 0x1030)
&& (bdp->pdev->device < 0x103F)) && (bdp->pdev->device < 0x103F))
|| ((bdp->pdev->device >= 0x1050) || ((bdp->pdev->device >= 0x1050)
...@@ -645,7 +647,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -645,7 +647,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
printk(KERN_ERR "e100: Failed to initialize, instance #%d\n", printk(KERN_ERR "e100: Failed to initialize, instance #%d\n",
e100nics); e100nics);
rc = -ENODEV; rc = -ENODEV;
goto err_pci; goto err_unregister_netdev;
} }
/* Check if checksum is valid */ /* Check if checksum is valid */
...@@ -655,7 +657,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -655,7 +657,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n", printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n",
e100nics); e100nics);
rc = -ENODEV; rc = -ENODEV;
goto err_pci; goto err_unregister_netdev;
} }
dev->vlan_rx_register = e100_vlan_rx_register; dev->vlan_rx_register = e100_vlan_rx_register;
...@@ -679,12 +681,6 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -679,12 +681,6 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
e100_get_speed_duplex_caps(bdp); e100_get_speed_duplex_caps(bdp);
if ((rc = register_netdev(dev)) != 0) {
goto err_pci;
}
memcpy(bdp->ifname, dev->name, IFNAMSIZ);
bdp->ifname[IFNAMSIZ-1] = 0;
printk(KERN_NOTICE printk(KERN_NOTICE
"e100: %s: %s\n", "e100: %s: %s\n",
bdp->device->name, "Intel(R) PRO/100 Network Connection"); bdp->device->name, "Intel(R) PRO/100 Network Connection");
...@@ -709,6 +705,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -709,6 +705,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
goto out; goto out;
err_unregister_netdev:
unregister_netdev(dev);
err_pci: err_pci:
iounmap(bdp->scb); iounmap(bdp->scb);
pci_release_regions(pcid); pci_release_regions(pcid);
...@@ -974,7 +972,7 @@ e100_set_bool_option(struct e100_private *bdp, int val, u32 mask, ...@@ -974,7 +972,7 @@ e100_set_bool_option(struct e100_private *bdp, int val, u32 mask,
} }
} }
static int int
e100_open(struct net_device *dev) e100_open(struct net_device *dev)
{ {
struct e100_private *bdp; struct e100_private *bdp;
...@@ -1012,6 +1010,10 @@ e100_open(struct net_device *dev) ...@@ -1012,6 +1010,10 @@ e100_open(struct net_device *dev)
mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
if (dev->flags & IFF_UP)
/* Otherwise process may sleep forever */
netif_wake_queue(dev);
else
netif_start_queue(dev); netif_start_queue(dev);
e100_start_ru(bdp); e100_start_ru(bdp);
...@@ -1033,7 +1035,7 @@ e100_open(struct net_device *dev) ...@@ -1033,7 +1035,7 @@ e100_open(struct net_device *dev)
return rc; return rc;
} }
static int int
e100_close(struct net_device *dev) e100_close(struct net_device *dev)
{ {
struct e100_private *bdp = dev->priv; struct e100_private *bdp = dev->priv;
...@@ -1074,7 +1076,8 @@ e100_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -1074,7 +1076,8 @@ e100_xmit_frame(struct sk_buff *skb, struct net_device *dev)
goto exit2; goto exit2;
} }
if (!TCBS_AVAIL(bdp->tcb_pool) || /* tcb list may be empty temporarily during releasing resources */
if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) ||
(bdp->non_tx_command_state != E100_NON_TX_IDLE)) { (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {
notify_stop = true; notify_stop = true;
rc = 1; rc = 1;
...@@ -1285,10 +1288,8 @@ e100_init(struct e100_private *bdp) ...@@ -1285,10 +1288,8 @@ e100_init(struct e100_private *bdp)
/* read NIC's part number */ /* read NIC's part number */
e100_rd_pwa_no(bdp); e100_rd_pwa_no(bdp);
if (!e100_hw_init(bdp)) { if (!e100_hw_init(bdp))
printk(KERN_ERR "e100: hw init failed\n");
return false; return false;
}
/* Interrupts are enabled after device reset */ /* Interrupts are enabled after device reset */
e100_disable_clear_intr(bdp); e100_disable_clear_intr(bdp);
...@@ -1330,6 +1331,8 @@ e100_sw_init(struct e100_private *bdp) ...@@ -1330,6 +1331,8 @@ e100_sw_init(struct e100_private *bdp)
spin_lock_init(&(bdp->bd_non_tx_lock)); spin_lock_init(&(bdp->bd_non_tx_lock));
spin_lock_init(&(bdp->config_lock)); spin_lock_init(&(bdp->config_lock));
spin_lock_init(&(bdp->mdi_access_lock)); spin_lock_init(&(bdp->mdi_access_lock));
/* Initialize configuration data */
e100_config_init(bdp);
return 1; return 1;
} }
...@@ -1384,11 +1387,11 @@ e100_tco_workaround(struct e100_private *bdp) ...@@ -1384,11 +1387,11 @@ e100_tco_workaround(struct e100_private *bdp)
* true - If the adapter was initialized * true - If the adapter was initialized
* false - If the adapter failed initialization * false - If the adapter failed initialization
*/ */
unsigned char __devinit unsigned char
e100_hw_init(struct e100_private *bdp) e100_hw_init(struct e100_private *bdp)
{ {
if (!e100_phy_init(bdp)) if (!e100_phy_init(bdp))
return false; goto err;
e100_sw_reset(bdp, PORT_SELECTIVE_RESET); e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
...@@ -1398,27 +1401,25 @@ e100_hw_init(struct e100_private *bdp) ...@@ -1398,27 +1401,25 @@ e100_hw_init(struct e100_private *bdp)
/* Load the CU BASE (set to 0, because we use linear mode) */ /* Load the CU BASE (set to 0, because we use linear mode) */
if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
return false; goto err;
if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
return false; goto err;
/* Load interrupt microcode */ /* Load interrupt microcode */
if (e100_load_microcode(bdp)) { if (e100_load_microcode(bdp)) {
bdp->flags |= DF_UCODE_LOADED; bdp->flags |= DF_UCODE_LOADED;
} }
e100_config_init(bdp); if (!e100_config(bdp))
if (!e100_config(bdp)) { goto err;
return false;
}
if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr))
return false; goto err;
/* Clear the internal counters */ /* Clear the internal counters */
if (!e100_clr_cntrs(bdp)) if (!e100_clr_cntrs(bdp))
return false; goto err;
/* Change for 82558 enhancement */ /* Change for 82558 enhancement */
/* If 82558/9 and if the user has enabled flow control, set up the /* If 82558/9 and if the user has enabled flow control, set up the
...@@ -1431,6 +1432,9 @@ e100_hw_init(struct e100_private *bdp) ...@@ -1431,6 +1432,9 @@ e100_hw_init(struct e100_private *bdp)
} }
return true; return true;
err:
printk(KERN_ERR "e100: hw init failed\n");
return false;
} }
/** /**
...@@ -1591,9 +1595,22 @@ e100_alloc_tcb_pool(struct e100_private *bdp) ...@@ -1591,9 +1595,22 @@ e100_alloc_tcb_pool(struct e100_private *bdp)
void void
e100_free_tcb_pool(struct e100_private *bdp) e100_free_tcb_pool(struct e100_private *bdp)
{ {
tcb_t *tcb;
int i;
/* Return tx skbs */
for (i = 0; i < bdp->params.TxDescriptors; i++) {
tcb = bdp->tcb_pool.data;
tcb += bdp->tcb_pool.head;
e100_tx_skb_free(bdp, tcb);
if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail)
break;
bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
}
pci_free_consistent(bdp->pdev, pci_free_consistent(bdp->pdev,
sizeof (tcb_t) * bdp->params.TxDescriptors, sizeof (tcb_t) * bdp->params.TxDescriptors,
bdp->tcb_pool.data, bdp->tcb_phys); bdp->tcb_pool.data, bdp->tcb_phys);
bdp->tcb_pool.head = 0;
bdp->tcb_pool.tail = 1;
bdp->tcb_phys = 0; bdp->tcb_phys = 0;
} }
...@@ -1747,12 +1764,10 @@ e100_watchdog(struct net_device *dev) ...@@ -1747,12 +1764,10 @@ e100_watchdog(struct net_device *dev)
e100_set_multi(dev); e100_set_multi(dev);
} }
} }
/* Update the statistics needed by the upper interface */
/* This should be the last statistic related command
* as it's async. now */
e100_dump_stats_cntrs(bdp);
} }
/* Issue command to dump statistics from device. */
/* Check for command completion on next watchdog timer. */
e100_dump_stats_cntrs(bdp);
wmb(); wmb();
...@@ -2544,6 +2559,7 @@ e100_update_stats(struct e100_private *bdp) ...@@ -2544,6 +2559,7 @@ e100_update_stats(struct e100_private *bdp)
pcmd_complete = e100_cmd_complete_location(bdp); pcmd_complete = e100_cmd_complete_location(bdp);
if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) && if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) &&
*pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) { *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) {
*pcmd_complete = 0;
return false; return false;
} }
...@@ -3041,23 +3057,6 @@ e100_isolate_driver(struct e100_private *bdp) ...@@ -3041,23 +3057,6 @@ e100_isolate_driver(struct e100_private *bdp)
e100_sw_reset(bdp, PORT_SELECTIVE_RESET); e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
} }
void
e100_set_speed_duplex(struct e100_private *bdp)
{
int carrier_ok;
/* Device may lose link with some siwtches when */
/* changing speed/duplex to non-autoneg. e100 */
/* needs to remember carrier state in order to */
/* start watchdog timer for recovering link */
if ((carrier_ok = netif_carrier_ok(bdp->device)))
e100_isolate_driver(bdp);
e100_phy_set_speed_duplex(bdp, true);
e100_config_fc(bdp); /* re-config flow-control if necessary */
e100_config(bdp);
if (carrier_ok)
e100_deisolate_driver(bdp, false);
}
static void static void
e100_tcb_add_C_bit(struct e100_private *bdp) e100_tcb_add_C_bit(struct e100_private *bdp)
{ {
...@@ -3213,6 +3212,144 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) ...@@ -3213,6 +3212,144 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
case ETHTOOL_PHYS_ID: case ETHTOOL_PHYS_ID:
rc = e100_ethtool_led_blink(dev,ifr); rc = e100_ethtool_led_blink(dev,ifr);
break; break;
#ifdef ETHTOOL_GRINGPARAM
case ETHTOOL_GRINGPARAM: {
struct ethtool_ringparam ering;
struct e100_private *bdp = dev->priv;
memset((void *) &ering, 0, sizeof(ering));
ering.rx_max_pending = E100_MAX_RFD;
ering.tx_max_pending = E100_MAX_TCB;
ering.rx_pending = bdp->params.RxDescriptors;
ering.tx_pending = bdp->params.TxDescriptors;
rc = copy_to_user(ifr->ifr_data, &ering, sizeof(ering))
? -EFAULT : 0;
return rc;
}
#endif
#ifdef ETHTOOL_SRINGPARAM
case ETHTOOL_SRINGPARAM: {
struct ethtool_ringparam ering;
struct e100_private *bdp = dev->priv;
if (copy_from_user(&ering, ifr->ifr_data, sizeof(ering)))
return -EFAULT;
if (ering.rx_pending > E100_MAX_RFD
|| ering.rx_pending < E100_MIN_RFD)
return -EINVAL;
if (ering.tx_pending > E100_MAX_TCB
|| ering.tx_pending < E100_MIN_TCB)
return -EINVAL;
if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
/* Use new values to open interface */
bdp->params.RxDescriptors = ering.rx_pending;
bdp->params.TxDescriptors = ering.tx_pending;
e100_hw_init(bdp);
e100_open(dev);
}
else {
bdp->params.RxDescriptors = ering.rx_pending;
bdp->params.TxDescriptors = ering.tx_pending;
}
return 0;
}
#endif
#ifdef ETHTOOL_GPAUSEPARAM
case ETHTOOL_GPAUSEPARAM: {
struct ethtool_pauseparam epause;
struct e100_private *bdp = dev->priv;
memset((void *) &epause, 0, sizeof(epause));
if ((bdp->flags & IS_BACHELOR)
&& (bdp->params.b_params & PRM_FC)) {
epause.autoneg = 1;
if (bdp->flags && DF_LINK_FC_CAP) {
epause.rx_pause = 1;
epause.tx_pause = 1;
}
if (bdp->flags && DF_LINK_FC_TX_ONLY)
epause.tx_pause = 1;
}
rc = copy_to_user(ifr->ifr_data, &epause, sizeof(epause))
? -EFAULT : 0;
return rc;
}
#endif
#ifdef ETHTOOL_SPAUSEPARAM
case ETHTOOL_SPAUSEPARAM: {
struct ethtool_pauseparam epause;
struct e100_private *bdp = dev->priv;
if (!(bdp->flags & IS_BACHELOR))
return -EINVAL;
if (copy_from_user(&epause, ifr->ifr_data, sizeof(epause)))
return -EFAULT;
if (epause.autoneg == 1)
bdp->params.b_params |= PRM_FC;
else
bdp->params.b_params &= ~PRM_FC;
if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
return 0;
}
#endif
#ifdef ETHTOOL_GRXCSUM
case ETHTOOL_GRXCSUM:
case ETHTOOL_GTXCSUM:
case ETHTOOL_GSG:
{ struct ethtool_value eval;
struct e100_private *bdp = dev->priv;
memset((void *) &eval, 0, sizeof(eval));
if ((ecmd.cmd == ETHTOOL_GRXCSUM)
&& (bdp->params.b_params & PRM_XSUMRX))
eval.data = 1;
else
eval.data = 0;
rc = copy_to_user(ifr->ifr_data, &eval, sizeof(eval))
? -EFAULT : 0;
return rc;
}
#endif
#ifdef ETHTOOL_SRXCSUM
case ETHTOOL_SRXCSUM:
case ETHTOOL_STXCSUM:
case ETHTOOL_SSG:
{ struct ethtool_value eval;
struct e100_private *bdp = dev->priv;
if (copy_from_user(&eval, ifr->ifr_data, sizeof(eval)))
return -EFAULT;
if (ecmd.cmd == ETHTOOL_SRXCSUM) {
if (eval.data == 1) {
if (bdp->rev_id >= D101MA_REV_ID)
bdp->params.b_params |= PRM_XSUMRX;
else
return -EINVAL;
} else {
if (bdp->rev_id >= D101MA_REV_ID)
bdp->params.b_params &= ~PRM_XSUMRX;
else
return 0;
}
} else {
if (eval.data == 1)
return -EINVAL;
else
return 0;
}
if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
return 0;
}
#endif
default: default:
break; break;
} //switch } //switch
...@@ -3298,7 +3435,13 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) ...@@ -3298,7 +3435,13 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
if ((ecmd.autoneg == AUTONEG_ENABLE) if ((ecmd.autoneg == AUTONEG_ENABLE)
&& (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) { && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) {
bdp->params.e100_speed_duplex = E100_AUTONEG; bdp->params.e100_speed_duplex = E100_AUTONEG;
e100_set_speed_duplex(bdp); if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
} else { } else {
if (ecmd.speed == SPEED_10) { if (ecmd.speed == SPEED_10) {
if (ecmd.duplex == DUPLEX_HALF) { if (ecmd.duplex == DUPLEX_HALF) {
...@@ -3329,7 +3472,13 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) ...@@ -3329,7 +3472,13 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) { if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) {
bdp->params.e100_speed_duplex = bdp->params.e100_speed_duplex =
e100_new_speed_duplex; e100_new_speed_duplex;
e100_set_speed_duplex(bdp); if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
} else { } else {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -3364,14 +3513,14 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr) ...@@ -3364,14 +3513,14 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
struct ethtool_test *info; struct ethtool_test *info;
int rc = -EFAULT; int rc = -EFAULT;
info = kmalloc(sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64), info = kmalloc(sizeof(*info) + max_test_res * sizeof(u64),
GFP_ATOMIC); GFP_ATOMIC);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
memset((void *) info, 0, sizeof(*info) + memset((void *) info, 0, sizeof(*info) +
E100_MAX_TEST_RES * sizeof(u64)); max_test_res * sizeof(u64));
if (copy_from_user(info, ifr->ifr_data, sizeof(*info))) if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
goto exit; goto exit;
...@@ -3379,7 +3528,7 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr) ...@@ -3379,7 +3528,7 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
info->flags = e100_run_diag(dev, info->data, info->flags); info->flags = e100_run_diag(dev, info->data, info->flags);
if (!copy_to_user(ifr->ifr_data, info, if (!copy_to_user(ifr->ifr_data, info,
sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64))) sizeof(*info) + max_test_res * sizeof(u64)))
rc = 0; rc = 0;
exit: exit:
kfree(info); kfree(info);
...@@ -3393,6 +3542,7 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr) ...@@ -3393,6 +3542,7 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
u32 regs_buff[E100_REGS_LEN]; u32 regs_buff[E100_REGS_LEN];
struct ethtool_regs regs = {ETHTOOL_GREGS}; struct ethtool_regs regs = {ETHTOOL_GREGS};
void *addr = ifr->ifr_data; void *addr = ifr->ifr_data;
u16 mdi_reg;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -3405,6 +3555,8 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr) ...@@ -3405,6 +3555,8 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 | regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 |
readb(&(bdp->scb->scb_cmd_low)) << 16 | readb(&(bdp->scb->scb_cmd_low)) << 16 |
readw(&(bdp->scb->scb_status)); readw(&(bdp->scb->scb_status));
e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &mdi_reg);
regs_buff[1] = mdi_reg;
if(copy_to_user(addr, &regs, sizeof(regs))) if(copy_to_user(addr, &regs, sizeof(regs)))
return -EFAULT; return -EFAULT;
...@@ -3428,7 +3580,13 @@ e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr) ...@@ -3428,7 +3580,13 @@ e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) && if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
(bdp->params.e100_speed_duplex == E100_AUTONEG)) { (bdp->params.e100_speed_duplex == E100_AUTONEG)) {
e100_set_speed_duplex(bdp); if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
} else { } else {
return -EFAULT; return -EFAULT;
} }
...@@ -3454,7 +3612,7 @@ e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr) ...@@ -3454,7 +3612,7 @@ e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr)
info.n_stats = E100_STATS_LEN; info.n_stats = E100_STATS_LEN;
info.regdump_len = E100_REGS_LEN * sizeof(u32); info.regdump_len = E100_REGS_LEN * sizeof(u32);
info.eedump_len = (bdp->eeprom_size << 1); info.eedump_len = (bdp->eeprom_size << 1);
info.testinfo_len = E100_MAX_TEST_RES; info.testinfo_len = max_test_res;
if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
return -EFAULT; return -EFAULT;
...@@ -3804,15 +3962,15 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) ...@@ -3804,15 +3962,15 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
switch (info.string_set) { switch (info.string_set) {
case ETH_SS_TEST: { case ETH_SS_TEST: {
int ret = 0; int ret = 0;
if (info.len > E100_MAX_TEST_RES) if (info.len > max_test_res)
info.len = E100_MAX_TEST_RES; info.len = max_test_res;
strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC); strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
if (!strings) if (!strings)
return -ENOMEM; return -ENOMEM;
memset(strings, 0, info.len * ETH_GSTRING_LEN); memset(strings, 0, info.len * ETH_GSTRING_LEN);
for (i = 0; i < info.len; i++) { for (i = 0; i < info.len; i++) {
sprintf(strings + i * ETH_GSTRING_LEN, "%-31s", sprintf(strings + i * ETH_GSTRING_LEN, "%s",
test_strings[i]); test_strings[i]);
} }
if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
...@@ -3881,7 +4039,13 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -3881,7 +4039,13 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
bdp->params.e100_speed_duplex = E100_SPEED_10_FULL; bdp->params.e100_speed_duplex = E100_SPEED_10_FULL;
else else
bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
e100_set_speed_duplex(bdp); if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
e100_close(dev);
spin_unlock_bh(&dev->xmit_lock);
e100_hw_init(bdp);
e100_open(dev);
}
} }
else else
/* Only allows changing speed/duplex */ /* Only allows changing speed/duplex */
...@@ -4164,7 +4328,6 @@ e100_resume(struct pci_dev *pcid) ...@@ -4164,7 +4328,6 @@ e100_resume(struct pci_dev *pcid)
return 0; return 0;
} }
#endif /* CONFIG_PM */
/** /**
* e100_asf_enabled - checks if ASF is configured on the current adaper * e100_asf_enabled - checks if ASF is configured on the current adaper
...@@ -4190,6 +4353,7 @@ e100_asf_enabled(struct e100_private *bdp) ...@@ -4190,6 +4353,7 @@ e100_asf_enabled(struct e100_private *bdp)
} }
return false; return false;
} }
#endif /* CONFIG_PM */
#ifdef E100_CU_DEBUG #ifdef E100_CU_DEBUG
unsigned char unsigned char
......
...@@ -628,8 +628,6 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -628,8 +628,6 @@ e100_force_speed_duplex(struct e100_private *bdp)
u16 control; u16 control;
unsigned long expires; unsigned long expires;
e100_phy_reset(bdp);
bdp->flags |= DF_SPEED_FORCED; bdp->flags |= DF_SPEED_FORCED;
e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
...@@ -912,6 +910,10 @@ e100_phy_reset(struct e100_private *bdp) ...@@ -912,6 +910,10 @@ e100_phy_reset(struct e100_private *bdp)
u16 ctrl_reg; u16 ctrl_reg;
ctrl_reg = BMCR_RESET; ctrl_reg = BMCR_RESET;
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
/* ieee 802.3 : The reset process shall be completed */
/* within 0.5 seconds from the settting of PHY reset bit. */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 2);
} }
unsigned char __devinit unsigned char __devinit
...@@ -928,6 +930,7 @@ e100_phy_init(struct e100_private *bdp) ...@@ -928,6 +930,7 @@ e100_phy_init(struct e100_private *bdp)
bdp->PhyDelay = 0; bdp->PhyDelay = 0;
bdp->zlock_state = ZLOCK_INITIAL; bdp->zlock_state = ZLOCK_INITIAL;
e100_phy_reset(bdp);
e100_phy_set_speed_duplex(bdp, false); e100_phy_set_speed_duplex(bdp, false);
e100_fix_polarity(bdp); e100_fix_polarity(bdp);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/ *******************************************************************************/
#include "e100.h" #include "e100_phy.h"
#include "e100_config.h" #include "e100_config.h"
extern u16 e100_eeprom_read(struct e100_private *, u16); extern u16 e100_eeprom_read(struct e100_private *, u16);
...@@ -46,6 +46,7 @@ static u8 e100_diag_loopback_alloc(struct e100_private *); ...@@ -46,6 +46,7 @@ static u8 e100_diag_loopback_alloc(struct e100_private *);
static void e100_diag_loopback_cu_ru_exec(struct e100_private *); static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
static u8 e100_diag_check_pkt(u8 *); static u8 e100_diag_check_pkt(u8 *);
static void e100_diag_loopback_free(struct e100_private *); static void e100_diag_loopback_free(struct e100_private *);
static int e100_cable_diag(struct e100_private *bdp);
#define LB_PACKET_SIZE 1500 #define LB_PACKET_SIZE 1500
...@@ -60,46 +61,52 @@ u32 ...@@ -60,46 +61,52 @@ u32
e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags) e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
{ {
struct e100_private* bdp = dev->priv; struct e100_private* bdp = dev->priv;
u8 test_result = true; u8 test_result = 0;
e100_isolate_driver(bdp);
if (!e100_get_link_state(bdp)) {
test_result = ETH_TEST_FL_FAILED;
test_info[test_link] = true;
}
if (!e100_diag_eeprom(dev)) {
test_result = ETH_TEST_FL_FAILED;
test_info[test_eeprom] = true;
}
if (flags & ETH_TEST_FL_OFFLINE) { if (flags & ETH_TEST_FL_OFFLINE) {
u8 fail_mask; u8 fail_mask;
if (netif_running(dev)) {
fail_mask = e100_diag_selftest(dev); spin_lock_bh(&dev->xmit_lock);
if (fail_mask) { e100_close(dev);
test_result = false; spin_unlock_bh(&dev->xmit_lock);
if (fail_mask & REGISTER_TEST_FAIL) }
test_info [E100_REG_TEST_FAIL] = true; if (e100_diag_selftest(dev)) {
if (fail_mask & ROM_TEST_FAIL) test_result = ETH_TEST_FL_FAILED;
test_info [E100_ROM_TEST_FAIL] = true; test_info[test_self_test] = true;
if (fail_mask & SELF_TEST_FAIL)
test_info [E100_MAC_TEST_FAIL] = true;
if (fail_mask & TEST_TIMEOUT)
test_info [E100_CHIP_TIMEOUT] = true;
} }
fail_mask = e100_diag_loopback(dev); fail_mask = e100_diag_loopback(dev);
if (fail_mask) { if (fail_mask) {
test_result = false; test_result = ETH_TEST_FL_FAILED;
if (fail_mask & PHY_LOOPBACK) if (fail_mask & PHY_LOOPBACK)
test_info [E100_LPBK_PHY_FAIL] = true; test_info[test_loopback_phy] = true;
if (fail_mask & MAC_LOOPBACK) if (fail_mask & MAC_LOOPBACK)
test_info [E100_LPBK_MAC_FAIL] = true; test_info[test_loopback_mac] = true;
}
} }
if (!e100_diag_eeprom(dev)) { test_info[cable_diag] = e100_cable_diag(bdp);
test_result = false; /* Need hw init regardless of netif_running */
test_info [E100_EEPROM_TEST_FAIL] = true; e100_hw_init(bdp);
if (netif_running(dev)) {
e100_open(dev);
}
}
else {
test_info[test_self_test] = false;
test_info[test_loopback_phy] = false;
test_info[test_loopback_mac] = false;
test_info[cable_diag] = false;
} }
set_current_state(TASK_UNINTERRUPTIBLE); return flags | test_result;
schedule_timeout(HZ * 2);
e100_deisolate_driver(bdp, false);
return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
} }
/** /**
...@@ -126,8 +133,6 @@ e100_diag_selftest(struct net_device *dev) ...@@ -126,8 +133,6 @@ e100_diag_selftest(struct net_device *dev)
} }
} }
e100_configure_device(bdp);
return retval; return retval;
} }
...@@ -165,14 +170,14 @@ e100_diag_loopback (struct net_device *dev) ...@@ -165,14 +170,14 @@ e100_diag_loopback (struct net_device *dev)
u8 rc = 0; u8 rc = 0;
printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name); printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name);
e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET); e100_hw_init(dev->priv);
if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) { if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
rc |= PHY_LOOPBACK; rc |= PHY_LOOPBACK;
} }
printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name); printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name);
printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name); printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name);
e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET); e100_hw_init(dev->priv);
if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) { if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
rc |= MAC_LOOPBACK; rc |= MAC_LOOPBACK;
} }
...@@ -257,14 +262,9 @@ e100_diag_config_loopback(struct e100_private* bdp, ...@@ -257,14 +262,9 @@ e100_diag_config_loopback(struct e100_private* bdp,
if (set_loopback) if (set_loopback)
/* Set PHY loopback mode */ /* Set PHY loopback mode */
e100_phy_set_loopback(bdp); e100_phy_set_loopback(bdp);
else { /* Back to normal speed and duplex */
if (bdp->params.e100_speed_duplex == E100_AUTONEG)
/* Reset PHY and do autoneg */
e100_phy_autoneg(bdp);
else else
/* Reset PHY and force speed and duplex */ /* Reset PHY loopback mode */
e100_force_speed_duplex(bdp); e100_phy_reset(bdp);
}
/* Wait for PHY state change */ /* Wait for PHY state change */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ); schedule_timeout(HZ);
...@@ -348,10 +348,6 @@ static void ...@@ -348,10 +348,6 @@ static void
e100_diag_loopback_cu_ru_exec(struct e100_private *bdp) e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
{ {
/*load CU & RU base */ /*load CU & RU base */
if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
printk(KERN_ERR "e100: SCB_CUC_LOAD_BASE failed\n");
if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
printk(KERN_ERR "e100: SCB_RUC_LOAD_BASE failed!\n");
if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0)) if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0))
printk(KERN_ERR "e100: SCB_RUC_START failed!\n"); printk(KERN_ERR "e100: SCB_RUC_START failed!\n");
...@@ -433,3 +429,72 @@ e100_diag_loopback_free (struct e100_private *bdp) ...@@ -433,3 +429,72 @@ e100_diag_loopback_free (struct e100_private *bdp)
bdp->loopback.dma_handle); bdp->loopback.dma_handle);
} }
static int
e100_cable_diag(struct e100_private *bdp)
{
int saved_open_circut = 0xffff;
int saved_short_circut = 0xffff;
int saved_distance = 0xffff;
int saved_same = 0;
int cable_status = E100_CABLE_UNKNOWN;
int i;
/* If we have link, */
if (e100_get_link_state(bdp))
return E100_CABLE_OK;
if (bdp->rev_id < D102_REV_ID)
return E100_CABLE_UNKNOWN;
/* 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 cable test */
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
BMCR_SPEED100 | BMCR_FULLDPLX);
/* Test up to 100 times */
for (i = 0; i < 100; i++) {
u16 ctrl_reg;
int distance, open_circut, short_circut, near_end;
/* Enable and execute cable test */
e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
/* Wait for cable test finished */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/100 + 1);
/* Read results */
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 == saved_distance) &&
(open_circut == saved_open_circut) &&
(short_circut == saved_short_circut))
saved_same++;
else {
saved_same = 0;
saved_distance = distance;
saved_open_circut = open_circut;
saved_short_circut = short_circut;
}
/* If results are the same 3 times */
if (saved_same == 3) {
near_end = ((distance * HWI_REGISTER_GRANULARITY) <
HWI_NEAR_END_BOUNDARY);
if (open_circut)
cable_status = (near_end) ?
E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
if (short_circut)
cable_status = (near_end) ?
E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
break;
}
}
/* Reset cable test */
e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, HWI_RESET_ALL_MASK);
return cable_status;
}
################################################################################ ################################################################################
# #
# #
# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. # Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free # under the terms of the GNU General Public License as published by the Free
......
...@@ -134,6 +134,7 @@ struct e1000_buffer { ...@@ -134,6 +134,7 @@ struct e1000_buffer {
uint64_t dma; uint64_t dma;
unsigned long length; unsigned long length;
unsigned long time_stamp; unsigned long time_stamp;
unsigned int next_to_watch;
}; };
struct e1000_desc_ring { struct e1000_desc_ring {
...@@ -169,7 +170,6 @@ struct e1000_adapter { ...@@ -169,7 +170,6 @@ struct e1000_adapter {
struct timer_list watchdog_timer; struct timer_list watchdog_timer;
struct timer_list phy_info_timer; struct timer_list phy_info_timer;
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
char *id_string;
uint32_t bd_number; uint32_t bd_number;
uint32_t rx_buffer_len; uint32_t rx_buffer_len;
uint32_t part_num; uint32_t part_num;
...@@ -218,6 +218,9 @@ struct e1000_adapter { ...@@ -218,6 +218,9 @@ struct e1000_adapter {
struct e1000_phy_info phy_info; struct e1000_phy_info phy_info;
struct e1000_phy_stats phy_stats; struct e1000_phy_stats phy_stats;
uint32_t test_icr;
struct e1000_desc_ring test_tx_ring;
struct e1000_desc_ring test_rx_ring;
uint32_t pci_state[16]; uint32_t pci_state[16];
......
...@@ -40,15 +40,60 @@ extern void e1000_down(struct e1000_adapter *adapter); ...@@ -40,15 +40,60 @@ extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reset(struct e1000_adapter *adapter); extern void e1000_reset(struct e1000_adapter *adapter);
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = { struct e1000_stats {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", char stat_string[ETH_GSTRING_LEN];
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", int sizeof_stat;
"rx_length_errors", "rx_over_errors", "rx_crc_errors", int stat_offset;
"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
"tx_heartbeat_errors", "tx_window_errors",
}; };
#define E1000_STATS_LEN sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN
#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
offsetof(struct e1000_adapter, m)
static struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_packets", E1000_STAT(net_stats.rx_packets) },
{ "tx_packets", E1000_STAT(net_stats.tx_packets) },
{ "rx_bytes", E1000_STAT(net_stats.rx_bytes) },
{ "tx_bytes", E1000_STAT(net_stats.tx_bytes) },
{ "rx_errors", E1000_STAT(net_stats.rx_errors) },
{ "tx_errors", E1000_STAT(net_stats.tx_errors) },
{ "rx_dropped", E1000_STAT(net_stats.rx_dropped) },
{ "tx_dropped", E1000_STAT(net_stats.tx_dropped) },
{ "multicast", E1000_STAT(net_stats.multicast) },
{ "collisions", E1000_STAT(net_stats.collisions) },
{ "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) },
{ "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) },
{ "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) },
{ "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
{ "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) },
{ "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) },
{ "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) },
{ "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) },
{ "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) },
{ "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) },
{ "tx_window_errors", E1000_STAT(net_stats.tx_window_errors) },
{ "tx_abort_late_coll", E1000_STAT(stats.latecol) },
{ "tx_deferred_ok", E1000_STAT(stats.dc) },
{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
{ "rx_long_length_errors", E1000_STAT(stats.roc) },
{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
{ "tx_tcp_seg_good", E1000_STAT(stats.tsctc) },
{ "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) },
{ "rx_flow_control_xon", E1000_STAT(stats.xonrxc) },
{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
static char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)", "Eeprom test (offline)",
"Interrupt test (offline)", "Loopback test (offline)",
"Link test (on/offline)"
};
#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
static void static void
e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
...@@ -154,6 +199,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, ...@@ -154,6 +199,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->fw_version, "N/A", 32);
strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
drvinfo->n_stats = E1000_STATS_LEN; drvinfo->n_stats = E1000_STATS_LEN;
drvinfo->testinfo_len = E1000_TEST_LEN;
#define E1000_REGS_LEN 32 #define E1000_REGS_LEN 32
drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t);
drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
...@@ -164,6 +210,7 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter, ...@@ -164,6 +210,7 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter,
struct ethtool_regs *regs, uint32_t *regs_buff) struct ethtool_regs *regs, uint32_t *regs_buff)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
uint16_t phy_data;
regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
...@@ -182,6 +229,62 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter, ...@@ -182,6 +229,62 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter,
regs_buff[10] = E1000_READ_REG(hw, TDT); regs_buff[10] = E1000_READ_REG(hw, TDT);
regs_buff[11] = E1000_READ_REG(hw, TIDV); regs_buff[11] = E1000_READ_REG(hw, TIDV);
regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
if(hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[13] = (uint32_t)phy_data; /* cable length */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_B);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[14] = (uint32_t)phy_data; /* cable length */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_C);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[15] = (uint32_t)phy_data; /* cable length */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_D);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[16] = (uint32_t)phy_data; /* cable length */
regs_buff[17] = 0; /* extended 10bt distance (not needed) */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_PCS_INIT_REG);
e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
IGP01E1000_PHY_PAGE_SELECT, &phy_data);
regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
regs_buff[20] = 0; /* polarity correction enabled (always) */
regs_buff[22] = 0; /* phy receive errors (unavailable) */
regs_buff[23] = regs_buff[18]; /* mdix mode */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
} else {
e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
regs_buff[13] = (uint32_t)phy_data; /* cable length */
regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */
e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
regs_buff[18] = regs_buff[13]; /* cable polarity */
regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff[20] = regs_buff[17]; /* polarity correction */
/* phy receive errors */
regs_buff[22] = adapter->phy_stats.receive_errors;
regs_buff[23] = regs_buff[13]; /* mdix mode */
}
regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
return; return;
} }
...@@ -249,7 +352,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -249,7 +352,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
first_word = eeprom->offset >> 1; first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_buff = kmalloc(max_len, GFP_KERNEL); eeprom_buff = kmalloc(max_len, GFP_KERNEL);
if(eeprom_buff == NULL) if(!eeprom_buff)
return -ENOMEM; return -ENOMEM;
ptr = (void *)eeprom_buff; ptr = (void *)eeprom_buff;
...@@ -284,6 +387,765 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -284,6 +387,765 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
return ret_val; return ret_val;
} }
#define REG_PATTERN_TEST(R, M, W) \
{ \
uint32_t pat, value; \
uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
if(value != (test[pat] & W & M)) { \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
} \
} \
}
#define REG_SET_AND_CHECK(R, M, W) \
{ \
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
if ((W & M) != (value & M)) { \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
} \
}
static int
e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
{
uint32_t value;
uint32_t i;
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833));
E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF));
if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) {
*data = 1;
return 1;
}
REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
if(adapter->hw.mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
for(i = 0; i < E1000_RAR_ENTRIES; i++) {
REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
0xFFFFFFFF);
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
0xFFFFFFFF);
}
} else {
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
}
for(i = 0; i < E1000_MC_TBL_SIZE; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
return 0;
}
static int
e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
{
uint16_t temp;
uint16_t checksum = 0;
uint16_t i;
*data = 0;
/* Read and add up the contents of the EEPROM */
for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
checksum += temp;
}
/* If Checksum is not Correct return error else test passed */
if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
*data = 2;
return *data;
}
static irqreturn_t
e1000_test_intr(int irq,
void *data,
struct pt_regs *regs)
{
struct net_device *netdev = (struct net_device *) data;
struct e1000_adapter *adapter = netdev->priv;
adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
return IRQ_HANDLED;
}
static int
e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
{
struct net_device *netdev = adapter->netdev;
uint32_t icr, mask, i=0;
*data = 0;
/* Hook up test interrupt handler just for this test */
if(request_irq
(netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) {
*data = 1;
return -1;
}
/* Disable all the interrupts */
E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
msec_delay(10);
/* Interrupts are disabled, so read interrupt cause
* register (icr) twice to verify that there are no interrupts
* pending. icr is clear on read.
*/
icr = E1000_READ_REG(&adapter->hw, ICR);
icr = E1000_READ_REG(&adapter->hw, ICR);
if(icr != 0) {
/* if icr is non-zero, there is no point
* running other interrupt tests.
*/
*data = 2;
i = 10;
}
/* Test each interrupt */
for(; i < 10; i++) {
/* Interrupt to test */
mask = 1 << i;
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was posted to the bus, the
* test failed.
*/
adapter->test_icr = 0;
E1000_WRITE_REG(&adapter->hw, IMC, mask);
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
if(adapter->test_icr & mask) {
*data = 3;
break;
}
/* Enable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was not posted to the bus, the
* test failed.
*/
adapter->test_icr = 0;
E1000_WRITE_REG(&adapter->hw, IMS, mask);
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
if(!(adapter->test_icr & mask)) {
*data = 4;
break;
}
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
* an interrupt was posted to the bus, the
* test failed.
*/
adapter->test_icr = 0;
E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
msec_delay(10);
if(adapter->test_icr) {
*data = 5;
break;
}
}
/* Disable all the interrupts */
E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
msec_delay(10);
/* Unhook test interrupt handler */
free_irq(netdev->irq, netdev);
return *data;
}
static void
e1000_free_desc_rings(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i;
if(txdr->desc && txdr->buffer_info) {
for(i = 0; i < txdr->count; i++) {
if(txdr->buffer_info[i].dma)
pci_unmap_single(pdev, txdr->buffer_info[i].dma,
txdr->buffer_info[i].length,
PCI_DMA_TODEVICE);
if(txdr->buffer_info[i].skb)
dev_kfree_skb(txdr->buffer_info[i].skb);
}
}
if(rxdr->desc && rxdr->buffer_info) {
for(i = 0; i < rxdr->count; i++) {
if(rxdr->buffer_info[i].dma)
pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
rxdr->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
if(rxdr->buffer_info[i].skb)
dev_kfree_skb(rxdr->buffer_info[i].skb);
}
}
if(txdr->desc)
pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
if(rxdr->desc)
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
if(txdr->buffer_info)
kfree(txdr->buffer_info);
if(rxdr->buffer_info)
kfree(rxdr->buffer_info);
return;
}
static int
e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
uint32_t rctl;
int size, i, ret_val;
/* Setup Tx descriptor ring and Tx buffers */
txdr->count = 80;
size = txdr->count * sizeof(struct e1000_buffer);
if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 1;
goto err_nomem;
}
memset(txdr->buffer_info, 0, size);
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
E1000_ROUNDUP(txdr->size, 4096);
if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
ret_val = 2;
goto err_nomem;
}
memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = txdr->next_to_clean = 0;
E1000_WRITE_REG(&adapter->hw, TDBAL,
((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
E1000_WRITE_REG(&adapter->hw, TDLEN,
txdr->count * sizeof(struct e1000_tx_desc));
E1000_WRITE_REG(&adapter->hw, TDH, 0);
E1000_WRITE_REG(&adapter->hw, TDT, 0);
E1000_WRITE_REG(&adapter->hw, TCTL,
E1000_TCTL_PSP | E1000_TCTL_EN |
E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
for(i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
if(!(skb = alloc_skb(size, GFP_KERNEL))) {
ret_val = 3;
goto err_nomem;
}
skb_put(skb, size);
txdr->buffer_info[i].skb = skb;
txdr->buffer_info[i].length = skb->len;
txdr->buffer_info[i].dma =
pci_map_single(pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
tx_desc->lower.data = cpu_to_le32(skb->len);
tx_desc->lower.data |= E1000_TXD_CMD_EOP;
tx_desc->lower.data |= E1000_TXD_CMD_IFCS;
tx_desc->lower.data |= E1000_TXD_CMD_RPS;
tx_desc->upper.data = 0;
}
/* Setup Rx descriptor ring and Rx buffers */
rxdr->count = 80;
size = rxdr->count * sizeof(struct e1000_buffer);
if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 4;
goto err_nomem;
}
memset(rxdr->buffer_info, 0, size);
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
ret_val = 5;
goto err_nomem;
}
memset(rxdr->desc, 0, rxdr->size);
rxdr->next_to_use = rxdr->next_to_clean = 0;
rctl = E1000_READ_REG(&adapter->hw, RCTL);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
E1000_WRITE_REG(&adapter->hw, RDBAL,
((uint64_t) rxdr->dma & 0xFFFFFFFF));
E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
E1000_WRITE_REG(&adapter->hw, RDH, 0);
E1000_WRITE_REG(&adapter->hw, RDT, 0);
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
for(i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) {
ret_val = 6;
goto err_nomem;
}
skb_reserve(skb, 2);
rxdr->buffer_info[i].skb = skb;
rxdr->buffer_info[i].length = E1000_RXBUFFER_2048;
rxdr->buffer_info[i].dma =
pci_map_single(pdev, skb->data, E1000_RXBUFFER_2048,
PCI_DMA_FROMDEVICE);
rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
memset(skb->data, 0x00, skb->len);
}
return 0;
err_nomem:
e1000_free_desc_rings(adapter);
return ret_val;
}
static void
e1000_phy_disable_receiver(struct e1000_adapter *adapter)
{
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
return;
}
static void
e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
{
uint16_t phy_reg;
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This
* value defaults back to a 2.5MHz clock when the PHY is reset.
*/
e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_EPSCR_TX_CLK_25;
e1000_write_phy_reg(&adapter->hw,
M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
/* In addition, because of the s/w reset above, we need to enable
* CRS on TX. This must be set for both full and half duplex
* operation.
*/
e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
e1000_write_phy_reg(&adapter->hw,
M88E1000_PHY_SPEC_CTRL, phy_reg);
}
static int
e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
{
uint32_t ctrl_reg;
uint16_t phy_reg;
/* Setup the Device Control Register for PHY loopback test. */
ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */
E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
/* Read the PHY Specific Control Register (0x10) */
e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
/* Clear Auto-Crossover bits in PHY Specific Control Register
* (bits 6:5).
*/
phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
/* Perform software reset on the PHY */
e1000_phy_reset(&adapter->hw);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs(adapter);
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
/* Wait for reset to complete. */
udelay(500);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs(adapter);
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
e1000_phy_disable_receiver(adapter);
/* Set the loopback bit in the PHY control register. */
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
/* Setup TX_CLK and TX_CRS one more time. */
e1000_phy_reset_clk_and_crs(adapter);
/* Check Phy Configuration */
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
if(phy_reg != 0x4100)
return 9;
e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
if(phy_reg != 0x0070)
return 10;
e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
if(phy_reg != 0x001A)
return 11;
return 0;
}
static int
e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
{
uint32_t ctrl_reg = 0;
uint32_t stat_reg = 0;
adapter->hw.autoneg = FALSE;
if(adapter->hw.phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
e1000_write_phy_reg(&adapter->hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
/* autoneg off */
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
}
/* force 1000, set loopback */
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
if(adapter->hw.media_type == e1000_media_type_copper &&
adapter->hw.phy_type == e1000_phy_m88) {
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
} else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
if((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
if(adapter->hw.phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
return 0;
}
static int
e1000_set_phy_loopback(struct e1000_adapter *adapter)
{
uint16_t phy_reg = 0;
uint16_t count = 0;
switch (adapter->hw.mac_type) {
case e1000_82543:
if(adapter->hw.media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
*/
while(e1000_nonintegrated_phy_loopback(adapter) &&
count++ < 10);
if(count < 11)
return 0;
}
break;
case e1000_82544:
case e1000_82540:
case e1000_82545:
case e1000_82546:
case e1000_82541:
case e1000_82547:
return e1000_integrated_phy_loopback(adapter);
break;
default:
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
*/
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
return 0;
break;
}
return 8;
}
static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
uint32_t rctl;
if(adapter->hw.media_type == e1000_media_type_fiber) {
if(adapter->hw.mac_type == e1000_82545 ||
adapter->hw.mac_type == e1000_82546)
return e1000_set_phy_loopback(adapter);
else {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
return 0;
}
} else if(adapter->hw.media_type == e1000_media_type_copper)
return e1000_set_phy_loopback(adapter);
return 7;
}
static void
e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
uint32_t rctl;
uint16_t phy_reg;
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
if(adapter->hw.media_type == e1000_media_type_copper ||
(adapter->hw.media_type == e1000_media_type_fiber &&
(adapter->hw.mac_type == e1000_82545 ||
adapter->hw.mac_type == e1000_82546))) {
adapter->hw.autoneg = TRUE;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
if(phy_reg & MII_CR_LOOPBACK) {
phy_reg &= ~MII_CR_LOOPBACK;
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
e1000_phy_reset(&adapter->hw);
}
}
}
static void
e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
}
static int
e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
if(*(skb->data + 3) == 0xFF) {
if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
(*(skb->data + frame_size / 2 + 12) == 0xAF)) {
return 0;
}
}
return 13;
}
static int
e1000_run_loopback_test(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i;
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
for(i = 0; i < 64; i++) {
e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,
txdr->buffer_info[i].length,
PCI_DMA_TODEVICE);
}
E1000_WRITE_REG(&adapter->hw, TDT, i);
msec_delay(200);
pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,
rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
}
static int
e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
{
if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
e1000_free_desc_rings(adapter);
err_loopback:
return *data;
}
static int
e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
{
*data = 0;
e1000_check_for_link(&adapter->hw);
if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
return *data;
}
static int
e1000_ethtool_test(struct e1000_adapter *adapter,
struct ethtool_test *eth_test, uint64_t *data)
{
boolean_t if_running = netif_running(adapter->netdev);
if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
/* Offline tests */
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
if(e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
if(if_running)
e1000_down(adapter);
e1000_reset(adapter);
if(e1000_reg_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
if(e1000_eeprom_test(adapter, &data[1]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
if(e1000_intr_test(adapter, &data[2]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
if(e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
if(if_running)
e1000_up(adapter);
} else {
/* Online tests */
if(e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* Offline tests aren't run; pass by default */
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
}
return 0;
}
static void static void
e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
{ {
...@@ -443,24 +1305,46 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) ...@@ -443,24 +1305,46 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
case ETHTOOL_GSTRINGS: { case ETHTOOL_GSTRINGS: {
struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
char *strings = NULL; char *strings = NULL;
int err = 0;
if(copy_from_user(&gstrings, addr, sizeof(gstrings))) if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
return -EFAULT; return -EFAULT;
switch(gstrings.string_set) { switch(gstrings.string_set) {
case ETH_SS_STATS: case ETH_SS_TEST:
gstrings.len = E1000_TEST_LEN;
strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN,
GFP_KERNEL);
if(!strings)
return -ENOMEM;
memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN *
ETH_GSTRING_LEN);
break;
case ETH_SS_STATS: {
int i;
gstrings.len = E1000_STATS_LEN; gstrings.len = E1000_STATS_LEN;
strings = *e1000_gstrings_stats; strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN,
GFP_KERNEL);
if(!strings)
return -ENOMEM;
for(i=0; i < E1000_STATS_LEN; i++) {
memcpy(&strings[i * ETH_GSTRING_LEN],
e1000_gstrings_stats[i].stat_string,
ETH_GSTRING_LEN);
}
break; break;
}
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if(copy_to_user(addr, &gstrings, sizeof(gstrings))) if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
return -EFAULT; err = -EFAULT;
addr += offsetof(struct ethtool_gstrings, data); addr += offsetof(struct ethtool_gstrings, data);
if(copy_to_user(addr, strings, if(!err && copy_to_user(addr, strings,
gstrings.len * ETH_GSTRING_LEN)) gstrings.len * ETH_GSTRING_LEN))
return -EFAULT; err = -EFAULT;
return 0;
kfree(strings);
return err;
} }
case ETHTOOL_GREGS: { case ETHTOOL_GREGS: {
struct ethtool_regs regs = {ETHTOOL_GREGS}; struct ethtool_regs regs = {ETHTOOL_GREGS};
...@@ -522,16 +1406,14 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) ...@@ -522,16 +1406,14 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
void *ptr; void *ptr;
int err = 0; int err = 0;
if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
return -EFAULT;
eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
if(eeprom_buff == NULL) if(!eeprom_buff)
return -ENOMEM; return -ENOMEM;
if(copy_from_user(&eeprom, addr, sizeof(eeprom))) {
err = -EFAULT;
goto err_geeprom_ioctl;
}
if((err = e1000_ethtool_geeprom(adapter, &eeprom, if((err = e1000_ethtool_geeprom(adapter, &eeprom,
eeprom_buff))) eeprom_buff)))
goto err_geeprom_ioctl; goto err_geeprom_ioctl;
...@@ -565,18 +1447,45 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) ...@@ -565,18 +1447,45 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
} }
case ETHTOOL_GSTATS: { case ETHTOOL_GSTATS: {
struct { struct {
struct ethtool_stats cmd; struct ethtool_stats eth_stats;
uint64_t data[E1000_STATS_LEN]; uint64_t data[E1000_STATS_LEN];
} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
int i; int i;
for(i = 0; i < E1000_STATS_LEN; i++) for(i = 0; i < E1000_STATS_LEN; i++)
stats.data[i] = stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
((unsigned long *)&adapter->net_stats)[i]; sizeof(uint64_t)) ?
*(uint64_t *)((char *)adapter +
e1000_gstrings_stats[i].stat_offset) :
*(uint32_t *)((char *)adapter +
e1000_gstrings_stats[i].stat_offset);
if(copy_to_user(addr, &stats, sizeof(stats))) if(copy_to_user(addr, &stats, sizeof(stats)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case ETHTOOL_TEST: {
struct {
struct ethtool_test eth_test;
uint64_t data[E1000_TEST_LEN];
} test = { {ETHTOOL_TEST} };
int err;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
return -EFAULT;
test.eth_test.len = E1000_TEST_LEN;
if((err = e1000_ethtool_test(adapter, &test.eth_test,
test.data)))
return err;
if(copy_to_user(addr, &test, sizeof(test)) != 0)
return -EFAULT;
return 0;
}
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -185,6 +185,7 @@ e1000_set_mac_type(struct e1000_hw *hw) ...@@ -185,6 +185,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
break; break;
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
hw->mac_type = e1000_82546; hw->mac_type = e1000_82546;
break; break;
case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI:
...@@ -288,9 +289,7 @@ e1000_reset_hw(struct e1000_hw *hw) ...@@ -288,9 +289,7 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */ /* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK; led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE; led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl); E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
} }
...@@ -737,9 +736,7 @@ e1000_setup_copper_link(struct e1000_hw *hw) ...@@ -737,9 +736,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */ /* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK; led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE; led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl); E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
...@@ -2293,9 +2290,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) ...@@ -2293,9 +2290,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */ /* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK; led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE; led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl); E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
} }
} }
...@@ -3801,6 +3796,7 @@ e1000_setup_led(struct e1000_hw *hw) ...@@ -3801,6 +3796,7 @@ e1000_setup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI: case E1000_DEV_ID_82547EI:
...@@ -3842,6 +3838,7 @@ e1000_cleanup_led(struct e1000_hw *hw) ...@@ -3842,6 +3838,7 @@ e1000_cleanup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI: case E1000_DEV_ID_82547EI:
...@@ -3896,6 +3893,7 @@ e1000_led_on(struct e1000_hw *hw) ...@@ -3896,6 +3893,7 @@ e1000_led_on(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI: case E1000_DEV_ID_82547EI:
...@@ -3949,6 +3947,7 @@ e1000_led_off(struct e1000_hw *hw) ...@@ -3949,6 +3947,7 @@ e1000_led_off(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI: case E1000_DEV_ID_82547EI:
...@@ -4206,7 +4205,11 @@ e1000_get_bus_info(struct e1000_hw *hw) ...@@ -4206,7 +4205,11 @@ e1000_get_bus_info(struct e1000_hw *hw)
status = E1000_READ_REG(hw, STATUS); status = E1000_READ_REG(hw, STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
e1000_bus_type_pcix : e1000_bus_type_pci; e1000_bus_type_pcix : e1000_bus_type_pci;
if(hw->bus_type == e1000_bus_type_pci) {
if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
e1000_bus_speed_66 : e1000_bus_speed_120;
} else if(hw->bus_type == e1000_bus_type_pci) {
hw->bus_speed = (status & E1000_STATUS_PCI66) ? hw->bus_speed = (status & E1000_STATUS_PCI66) ?
e1000_bus_speed_66 : e1000_bus_speed_33; e1000_bus_speed_66 : e1000_bus_speed_33;
} else { } else {
......
...@@ -99,6 +99,7 @@ typedef enum { ...@@ -99,6 +99,7 @@ typedef enum {
e1000_bus_speed_33, e1000_bus_speed_33,
e1000_bus_speed_66, e1000_bus_speed_66,
e1000_bus_speed_100, e1000_bus_speed_100,
e1000_bus_speed_120,
e1000_bus_speed_133, e1000_bus_speed_133,
e1000_bus_speed_reserved e1000_bus_speed_reserved
} e1000_bus_speed; } e1000_bus_speed;
...@@ -314,10 +315,11 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); ...@@ -314,10 +315,11 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
#define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_FIBER 0x1012
#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
#define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EI 0x1013
#define E1000_DEV_ID_82541EP 0x1018 #define E1000_DEV_ID_82541EP 0x1018
#define E1000_DEV_ID_82547EI 0x1019 #define E1000_DEV_ID_82547EI 0x1019
#define NUM_DEV_IDS 19 #define NUM_DEV_IDS 20
#define NODE_ADDRESS_SIZE 6 #define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6 #define ETH_LENGTH_OF_ADDRESS 6
...@@ -601,7 +603,7 @@ struct e1000_ffvt_entry { ...@@ -601,7 +603,7 @@ struct e1000_ffvt_entry {
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access Register - RW */ #define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
...@@ -730,6 +732,7 @@ struct e1000_ffvt_entry { ...@@ -730,6 +732,7 @@ struct e1000_ffvt_entry {
* the registers function in the same manner. * the registers function in the same manner.
*/ */
#define E1000_82542_CTRL E1000_CTRL #define E1000_82542_CTRL E1000_CTRL
#define E1000_82542_CTRL_DUP E1000_CTRL_DUP
#define E1000_82542_STATUS E1000_STATUS #define E1000_82542_STATUS E1000_STATUS
#define E1000_82542_EECD E1000_EECD #define E1000_82542_EECD E1000_EECD
#define E1000_82542_EERD E1000_EERD #define E1000_82542_EERD E1000_EERD
...@@ -1485,7 +1488,6 @@ struct e1000_hw { ...@@ -1485,7 +1488,6 @@ struct e1000_hw {
#define E1000_COLLISION_DISTANCE 64 #define E1000_COLLISION_DISTANCE 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_GB_HDX_COLLISION_DISTANCE 512
#define E1000_COLD_SHIFT 12 #define E1000_COLD_SHIFT 12
/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ /* The number of Transmit and Receive Descriptors must be a multiple of 8 */
......
...@@ -30,7 +30,14 @@ ...@@ -30,7 +30,14 @@
/* Change Log /* Change Log
* *
* 5.0.43 3/5/03 * 5.1.11 5/6/03
* o Feature: Added support for 82546EB (Quad-port) hardware.
* o Feature: Added support for Diagnostics through Ethtool.
* o Cleanup: Removed /proc support.
* o Cleanup: Removed proprietary IDIAG interface.
* o Bug fix: TSO bug fixes.
*
* 5.0.42 3/5/03
* o Feature: Added support for 82541 and 82547 hardware. * o Feature: Added support for 82541 and 82547 hardware.
* o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of * o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
* eeproms. * eeproms.
...@@ -46,51 +53,22 @@ ...@@ -46,51 +53,22 @@
* shared interrupt instances. * shared interrupt instances.
* *
* 4.4.18 11/27/02 * 4.4.18 11/27/02
* o Feature: Added user-settable knob for interrupt throttle rate (ITR).
* o Cleanup: removed large static array allocations.
* o Cleanup: C99 struct initializer format.
* o Bug fix: restore VLAN settings when interface is brought up.
* o Bug fix: return cleanly in probe if error in detecting MAC type.
* o Bug fix: Wake up on magic packet by default only if enabled in eeprom.
* o Bug fix: Validate MAC address in set_mac.
* o Bug fix: Throw away zero-length Tx skbs.
* o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool.
*
* 4.4.12 10/15/02
*/ */
char e1000_driver_name[] = "e1000"; char e1000_driver_name[] = "e1000";
char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
char e1000_driver_version[] = "5.0.43-k3"; char e1000_driver_version[] = "5.1.11-k1";
char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table /* e1000_pci_tbl - PCI Device ID Table
* *
* Private driver_data field (last one) stores an index into e1000_strings
* Wildcard entries (PCI_ANY_ID) should come last * Wildcard entries (PCI_ANY_ID) should come last
* Last entry must be all 0s * Last entry must be all 0s
* *
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, String Index } * Class, Class Mask, private data (not used) }
*/ */
static struct pci_device_id e1000_pci_tbl[] __devinitdata = { static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
/* Intel(R) PRO/1000 Network Connection */
{0x8086, 0x1000, 0x8086, 0x1000, 0, 0, 0},
{0x8086, 0x1001, 0x8086, 0x1003, 0, 0, 0},
{0x8086, 0x1004, 0x8086, 0x1004, 0, 0, 0},
{0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0},
{0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0},
{0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0},
{0x8086, 0x100E, 0x8086, 0x001E, 0, 0, 0},
/* Compaq Gigabit Ethernet Server Adapter */
{0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1},
{0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1},
{0x8086, 0x1004, 0x0E11, PCI_ANY_ID, 0, 0, 1},
/* IBM Mobile, Desktop & Server Adapters */
{0x8086, 0x1000, 0x1014, PCI_ANY_ID, 0, 0, 2},
{0x8086, 0x1001, 0x1014, PCI_ANY_ID, 0, 0, 2},
{0x8086, 0x1004, 0x1014, PCI_ANY_ID, 0, 0, 2},
/* Generic */
{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
...@@ -106,6 +84,7 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { ...@@ -106,6 +84,7 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */ /* required last entry */
...@@ -114,12 +93,6 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { ...@@ -114,12 +93,6 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
static char *e1000_strings[] = {
"Intel(R) PRO/1000 Network Connection",
"HP Gigabit Ethernet Server Adapter",
"IBM Mobile, Desktop & Server Adapters"
};
/* Local Function Prototypes */ /* Local Function Prototypes */
int e1000_up(struct e1000_adapter *adapter); int e1000_up(struct e1000_adapter *adapter);
...@@ -130,7 +103,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); ...@@ -130,7 +103,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
static int e1000_init_module(void); static int e1000_init_module(void);
static void e1000_exit_module(void); static void e1000_exit_module(void);
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void e1000_remove(struct pci_dev *pdev); static void __devexit e1000_remove(struct pci_dev *pdev);
static int e1000_sw_init(struct e1000_adapter *adapter); static int e1000_sw_init(struct e1000_adapter *adapter);
static int e1000_open(struct net_device *netdev); static int e1000_open(struct net_device *netdev);
static int e1000_close(struct net_device *netdev); static int e1000_close(struct net_device *netdev);
...@@ -195,7 +168,6 @@ struct notifier_block e1000_notifier_reboot = { ...@@ -195,7 +168,6 @@ struct notifier_block e1000_notifier_reboot = {
.priority = 0 .priority = 0
}; };
/* Exported from other modules */ /* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter); extern void e1000_check_options(struct e1000_adapter *adapter);
...@@ -234,8 +206,9 @@ e1000_init_module(void) ...@@ -234,8 +206,9 @@ e1000_init_module(void)
printk(KERN_INFO "%s\n", e1000_copyright); printk(KERN_INFO "%s\n", e1000_copyright);
ret = pci_module_init(&e1000_driver); ret = pci_module_init(&e1000_driver);
if(ret >= 0) if(ret >= 0) {
register_reboot_notifier(&e1000_notifier_reboot); register_reboot_notifier(&e1000_notifier_reboot);
}
return ret; return ret;
} }
...@@ -439,7 +412,6 @@ e1000_probe(struct pci_dev *pdev, ...@@ -439,7 +412,6 @@ e1000_probe(struct pci_dev *pdev,
netdev->base_addr = adapter->hw.io_base; netdev->base_addr = adapter->hw.io_base;
adapter->bd_number = cards_found; adapter->bd_number = cards_found;
adapter->id_string = e1000_strings[ent->driver_data];
/* setup the private structure */ /* setup the private structure */
...@@ -500,15 +472,14 @@ e1000_probe(struct pci_dev *pdev, ...@@ -500,15 +472,14 @@ e1000_probe(struct pci_dev *pdev,
(void (*)(void *))e1000_tx_timeout_task, netdev); (void (*)(void *))e1000_tx_timeout_task, netdev);
register_netdev(netdev); register_netdev(netdev);
memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
adapter->ifname[IFNAMSIZ-1] = 0;
/* we're going to reset, so assume we have no link for now */ /* we're going to reset, so assume we have no link for now */
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev); netif_stop_queue(netdev);
printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string); printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n",
netdev->name);
e1000_check_options(adapter); e1000_check_options(adapter);
/* Initial Wake on LAN setting /* Initial Wake on LAN setting
...@@ -568,7 +539,6 @@ e1000_remove(struct pci_dev *pdev) ...@@ -568,7 +539,6 @@ e1000_remove(struct pci_dev *pdev)
e1000_phy_hw_reset(&adapter->hw); e1000_phy_hw_reset(&adapter->hw);
iounmap(adapter->hw.hw_addr); iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -831,8 +801,9 @@ e1000_configure_tx(struct e1000_adapter *adapter) ...@@ -831,8 +801,9 @@ e1000_configure_tx(struct e1000_adapter *adapter)
e1000_config_collision_dist(&adapter->hw); e1000_config_collision_dist(&adapter->hw);
/* Setup Transmit Descriptor Settings for this adapter */ /* Setup Transmit Descriptor Settings for eop descriptor */
adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE; adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
E1000_TXD_CMD_IFCS;
if(adapter->hw.report_tx_early == 1) if(adapter->hw.report_tx_early == 1)
adapter->txd_cmd |= E1000_TXD_CMD_RS; adapter->txd_cmd |= E1000_TXD_CMD_RS;
...@@ -1435,7 +1406,7 @@ e1000_watchdog(unsigned long data) ...@@ -1435,7 +1406,7 @@ e1000_watchdog(unsigned long data)
#define E1000_TX_FLAGS_VLAN_SHIFT 16 #define E1000_TX_FLAGS_VLAN_SHIFT 16
static inline boolean_t static inline boolean_t
e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
{ {
#ifdef NETIF_F_TSO #ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc; struct e1000_context_desc *context_desc;
...@@ -1471,7 +1442,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) ...@@ -1471,7 +1442,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags)
context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss);
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(adapter->txd_cmd | context_desc->cmd_and_length = cpu_to_le32(
E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
(skb->len - (hdr_len))); (skb->len - (hdr_len)));
...@@ -1504,8 +1475,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1504,8 +1475,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->upper_setup.tcp_fields.tucso = cso; context_desc->upper_setup.tcp_fields.tucso = cso;
context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->upper_setup.tcp_fields.tucse = 0;
context_desc->tcp_seg_setup.data = 0; context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
if(++i == adapter->tx_ring.count) i = 0; if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i; adapter->tx_ring.next_to_use = i;
...@@ -1520,7 +1490,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1520,7 +1490,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR) #define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
static inline int static inline int
e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
unsigned int first)
{ {
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
int len = skb->len, offset = 0, size, count = 0, i; int len = skb->len, offset = 0, size, count = 0, i;
...@@ -1588,6 +1559,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1588,6 +1559,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
} }
if(--i < 0) i = tx_ring->count - 1; if(--i < 0) i = tx_ring->count - 1;
tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[i].skb = skb;
tx_ring->buffer_info[first].next_to_watch = i;
return count; return count;
} }
...@@ -1597,12 +1569,9 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) ...@@ -1597,12 +1569,9 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
{ {
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_tx_desc *tx_desc = NULL; struct e1000_tx_desc *tx_desc = NULL;
uint32_t txd_upper, txd_lower; uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
int i; int i;
txd_upper = 0;
txd_lower = adapter->txd_cmd;
if(tx_flags & E1000_TX_FLAGS_TSO) { if(tx_flags & E1000_TX_FLAGS_TSO) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE; E1000_TXD_CMD_TSE;
...@@ -1630,7 +1599,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) ...@@ -1630,7 +1599,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
if(++i == tx_ring->count) i = 0; if(++i == tx_ring->count) i = 0;
} }
tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP); tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
/* Force memory writes to complete before letting h/w /* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only * know there are new descriptors to fetch. (Only
...@@ -1690,6 +1659,7 @@ static int ...@@ -1690,6 +1659,7 @@ static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct e1000_adapter *adapter = netdev->priv; struct e1000_adapter *adapter = netdev->priv;
unsigned int first;
int tx_flags = 0; int tx_flags = 0;
if(skb->len <= 0) { if(skb->len <= 0) {
...@@ -1715,12 +1685,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1715,12 +1685,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
} }
if(e1000_tso(adapter, skb, tx_flags)) first = adapter->tx_ring.next_to_use;
if(e1000_tso(adapter, skb))
tx_flags |= E1000_TX_FLAGS_TSO; tx_flags |= E1000_TX_FLAGS_TSO;
else if(e1000_tx_csum(adapter, skb)) else if(e1000_tx_csum(adapter, skb))
tx_flags |= E1000_TX_FLAGS_CSUM; tx_flags |= E1000_TX_FLAGS_CSUM;
e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags); e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags);
netdev->trans_start = jiffies; netdev->trans_start = jiffies;
...@@ -1952,6 +1924,7 @@ e1000_update_stats(struct e1000_adapter *adapter) ...@@ -1952,6 +1924,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
} }
if((hw->mac_type <= e1000_82546) && if((hw->mac_type <= e1000_82546) &&
(hw->phy_type == e1000_phy_m88) &&
!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
adapter->phy_stats.receive_errors += phy_tmp; adapter->phy_stats.receive_errors += phy_tmp;
} }
...@@ -2069,39 +2042,47 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) ...@@ -2069,39 +2042,47 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
struct e1000_tx_desc *tx_desc; struct e1000_tx_desc *tx_desc, *eop_desc;
int i, cleaned = FALSE; struct e1000_buffer *buffer_info;
int i, eop, cleaned = FALSE;
i = tx_ring->next_to_clean; i = tx_ring->next_to_clean;
tx_desc = E1000_TX_DESC(*tx_ring, i); eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
cleaned = TRUE; for(cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
if(tx_ring->buffer_info[i].dma) { if(buffer_info->dma) {
pci_unmap_page(pdev, pci_unmap_page(pdev,
tx_ring->buffer_info[i].dma, buffer_info->dma,
tx_ring->buffer_info[i].length, buffer_info->length,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
tx_ring->buffer_info[i].dma = 0; buffer_info->dma = 0;
} }
if(tx_ring->buffer_info[i].skb) { if(buffer_info->skb) {
dev_kfree_skb_any(tx_ring->buffer_info[i].skb); dev_kfree_skb_any(buffer_info->skb);
tx_ring->buffer_info[i].skb = NULL; buffer_info->skb = NULL;
} }
tx_desc->buffer_addr = 0; tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0; tx_desc->lower.data = 0;
tx_desc->upper.data = 0; tx_desc->upper.data = 0;
cleaned = (i == eop);
if(++i == tx_ring->count) i = 0; if(++i == tx_ring->count) i = 0;
tx_desc = E1000_TX_DESC(*tx_ring, i); }
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
} }
tx_ring->next_to_clean = i; tx_ring->next_to_clean = i;
...@@ -2224,7 +2205,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2224,7 +2205,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
netif_rx(skb); netif_rx(skb);
} }
#endif /* CONFIG_E1000_NAPI */ #endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies; netdev->last_rx = jiffies;
rx_desc->status = 0; rx_desc->status = 0;
...@@ -2677,7 +2657,6 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) ...@@ -2677,7 +2657,6 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int static int
e1000_suspend(struct pci_dev *pdev, uint32_t state) e1000_suspend(struct pci_dev *pdev, uint32_t state)
{ {
......
...@@ -134,7 +134,7 @@ clone_list[] __initdata = { ...@@ -134,7 +134,7 @@ clone_list[] __initdata = {
{0,} {0,}
}; };
static void tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs); static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs);
static int initialize_register_pointers(struct fc_info *fi); static int initialize_register_pointers(struct fc_info *fi);
...@@ -623,7 +623,7 @@ u_int bus_addr, bus_indx_addr, i; ...@@ -623,7 +623,7 @@ u_int bus_addr, bus_indx_addr, i;
} }
static void tachyon_interrupt(int irq, void* dev_id, struct pt_regs* regs) static irqreturn_t tachyon_interrupt(int irq, void* dev_id, struct pt_regs* regs)
{ {
struct Scsi_Host *host = dev_id; struct Scsi_Host *host = dev_id;
struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata; struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
...@@ -632,6 +632,7 @@ u_long flags; ...@@ -632,6 +632,7 @@ u_long flags;
spin_lock_irqsave(&fi->fc_lock, flags); spin_lock_irqsave(&fi->fc_lock, flags);
tachyon_interrupt_handler(irq, dev_id, regs); tachyon_interrupt_handler(irq, dev_id, regs);
spin_unlock_irqrestore(&fi->fc_lock, flags); spin_unlock_irqrestore(&fi->fc_lock, flags);
return IRQ_HANDLED;
} }
static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs) static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs)
...@@ -3720,12 +3721,13 @@ struct fc_info *fi = (struct fc_info*)dev->priv; ...@@ -3720,12 +3721,13 @@ struct fc_info *fi = (struct fc_info*)dev->priv;
int iph5526_detect(Scsi_Host_Template *tmpt) int iph5526_detect(Scsi_Host_Template *tmpt)
{ {
struct Scsi_Host *host = NULL; struct Scsi_Host *host = NULL;
struct iph5526_hostdata *hostdata; struct iph5526_hostdata *hostdata;
struct fc_info *fi = NULL; struct fc_info *fi = NULL;
int no_of_hosts = 0, timeout, i, j, count = 0; int no_of_hosts = 0, i, j, count = 0;
u_int pci_maddr = 0; u_int pci_maddr = 0;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
unsigned long timeout;
tmpt->proc_name = "iph5526"; tmpt->proc_name = "iph5526";
if (pci_present() == 0) { if (pci_present() == 0) {
......
...@@ -188,7 +188,7 @@ struct fec_enet_private { ...@@ -188,7 +188,7 @@ struct fec_enet_private {
static int fec_enet_open(struct net_device *dev); static int fec_enet_open(struct net_device *dev);
static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void fec_enet_mii(struct net_device *dev); static void fec_enet_mii(struct net_device *dev);
static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); static irqreturn_t fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
static void fec_enet_tx(struct net_device *dev); static void fec_enet_tx(struct net_device *dev);
static void fec_enet_rx(struct net_device *dev); static void fec_enet_rx(struct net_device *dev);
static int fec_enet_close(struct net_device *dev); static int fec_enet_close(struct net_device *dev);
...@@ -393,12 +393,13 @@ fec_timeout(struct net_device *dev) ...@@ -393,12 +393,13 @@ fec_timeout(struct net_device *dev)
/* The interrupt handler. /* The interrupt handler.
* This is called from the MPC core interrupt. * This is called from the MPC core interrupt.
*/ */
static void static irqreturn_t
fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
volatile fec_t *fecp; volatile fec_t *fecp;
uint int_events; uint int_events;
int handled = 0;
fecp = (volatile fec_t*)dev->base_addr; fecp = (volatile fec_t*)dev->base_addr;
...@@ -413,20 +414,27 @@ fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) ...@@ -413,20 +414,27 @@ fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
/* Handle receive event in its own function. /* Handle receive event in its own function.
*/ */
if (int_events & FEC_ENET_RXF) if (int_events & FEC_ENET_RXF) {
handled = 1;
fec_enet_rx(dev); fec_enet_rx(dev);
}
/* Transmit OK, or non-fatal error. Update the buffer /* Transmit OK, or non-fatal error. Update the buffer
descriptors. FEC handles all errors, we just discover descriptors. FEC handles all errors, we just discover
them as part of the transmit process. them as part of the transmit process.
*/ */
if (int_events & FEC_ENET_TXF) if (int_events & FEC_ENET_TXF) {
handled = 1;
fec_enet_tx(dev); fec_enet_tx(dev);
}
if (int_events & FEC_ENET_MII) if (int_events & FEC_ENET_MII) {
handled = 1;
fec_enet_mii(dev); fec_enet_mii(dev);
}
} }
return IRQ_RETVAL(handled);
} }
......
...@@ -114,7 +114,7 @@ extern int fmv18x_probe(struct net_device *dev); ...@@ -114,7 +114,7 @@ extern int fmv18x_probe(struct net_device *dev);
static int fmv18x_probe1(struct net_device *dev, short ioaddr); static int fmv18x_probe1(struct net_device *dev, short ioaddr);
static int net_open(struct net_device *dev); static int net_open(struct net_device *dev);
static int net_send_packet(struct sk_buff *skb, struct net_device *dev); static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct net_device *dev); static void net_rx(struct net_device *dev);
static void net_timeout(struct net_device *dev); static void net_timeout(struct net_device *dev);
static int net_close(struct net_device *dev); static int net_close(struct net_device *dev);
...@@ -423,7 +423,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -423,7 +423,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
/* The typical workload of the driver: /* The typical workload of the driver:
Handle the network interface interrupts. */ Handle the network interface interrupts. */
static void static irqreturn_t
net_interrupt(int irq, void *dev_id, struct pt_regs *regs) net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
...@@ -476,7 +476,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -476,7 +476,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&lp->lock); spin_unlock(&lp->lock);
} }
} }
return; return IRQ_RETVAL(status);
} }
/* We have a good packet(s), get it/them out of the buffers. */ /* We have a good packet(s), get it/them out of the buffers. */
......
...@@ -199,7 +199,7 @@ static void z8530_init(void); ...@@ -199,7 +199,7 @@ static void z8530_init(void);
static void init_channel(struct scc_channel *scc); static void init_channel(struct scc_channel *scc);
static void scc_key_trx (struct scc_channel *scc, char tx); static void scc_key_trx (struct scc_channel *scc, char tx);
static void scc_isr(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void scc_init_timer(struct scc_channel *scc); static void scc_init_timer(struct scc_channel *scc);
static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev); static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev);
...@@ -625,7 +625,7 @@ static void scc_isr_dispatch(struct scc_channel *scc, int vector) ...@@ -625,7 +625,7 @@ static void scc_isr_dispatch(struct scc_channel *scc, int vector)
#define SCC_IRQTIMEOUT 30000 #define SCC_IRQTIMEOUT 30000
static void scc_isr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned char vector; unsigned char vector;
struct scc_channel *scc; struct scc_channel *scc;
...@@ -653,7 +653,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -653,7 +653,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
if (k == SCC_IRQTIMEOUT) if (k == SCC_IRQTIMEOUT)
printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n"); printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
return; return IRQ_HANDLED;
} }
/* Find the SCC generating the interrupt by polling all attached SCCs /* Find the SCC generating the interrupt by polling all attached SCCs
...@@ -701,6 +701,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -701,6 +701,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
} else } else
ctrl++; ctrl++;
} }
return IRQ_HANDLED;
} }
......
...@@ -541,6 +541,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -541,6 +541,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct myri_channel *chan = &mp->shmem->channel; struct myri_channel *chan = &mp->shmem->channel;
unsigned long flags; unsigned long flags;
u32 status; u32 status;
int handled = 0;
spin_lock_irqsave(&mp->irq_lock, flags); spin_lock_irqsave(&mp->irq_lock, flags);
...@@ -549,6 +550,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -549,6 +550,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & ISTAT_HOST) { if (status & ISTAT_HOST) {
u32 softstate; u32 softstate;
handled = 1;
DIRQ(("IRQ_DISAB ")); DIRQ(("IRQ_DISAB "));
myri_disable_irq(lregs, mp->cregs); myri_disable_irq(lregs, mp->cregs);
softstate = sbus_readl(&chan->state); softstate = sbus_readl(&chan->state);
...@@ -568,7 +570,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -568,7 +570,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock_irqrestore(&mp->irq_lock, flags); spin_unlock_irqrestore(&mp->irq_lock, flags);
return IRQ_HANDLED; return IRQ_RETVAL(handled);
} }
static int myri_open(struct net_device *dev) static int myri_open(struct net_device *dev)
......
...@@ -202,7 +202,6 @@ ppp_sync_open(struct tty_struct *tty) ...@@ -202,7 +202,6 @@ ppp_sync_open(struct tty_struct *tty)
struct syncppp *ap; struct syncppp *ap;
int err; int err;
MOD_INC_USE_COUNT;
ap = kmalloc(sizeof(*ap), GFP_KERNEL); ap = kmalloc(sizeof(*ap), GFP_KERNEL);
err = -ENOMEM; err = -ENOMEM;
if (ap == 0) if (ap == 0)
...@@ -236,7 +235,6 @@ ppp_sync_open(struct tty_struct *tty) ...@@ -236,7 +235,6 @@ ppp_sync_open(struct tty_struct *tty)
out_free: out_free:
kfree(ap); kfree(ap);
out: out:
MOD_DEC_USE_COUNT;
return err; return err;
} }
...@@ -276,7 +274,6 @@ ppp_sync_close(struct tty_struct *tty) ...@@ -276,7 +274,6 @@ ppp_sync_close(struct tty_struct *tty)
if (ap->tpkt != 0) if (ap->tpkt != 0)
kfree_skb(ap->tpkt); kfree_skb(ap->tpkt);
kfree(ap); kfree(ap);
MOD_DEC_USE_COUNT;
} }
/* /*
...@@ -404,6 +401,7 @@ ppp_sync_wakeup(struct tty_struct *tty) ...@@ -404,6 +401,7 @@ ppp_sync_wakeup(struct tty_struct *tty)
static struct tty_ldisc ppp_sync_ldisc = { static struct tty_ldisc ppp_sync_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC, .magic = TTY_LDISC_MAGIC,
.name = "pppsync", .name = "pppsync",
.open = ppp_sync_open, .open = ppp_sync_open,
......
...@@ -84,7 +84,7 @@ static int seeq8005_probe1(struct net_device *dev, int ioaddr); ...@@ -84,7 +84,7 @@ static int seeq8005_probe1(struct net_device *dev, int ioaddr);
static int seeq8005_open(struct net_device *dev); static int seeq8005_open(struct net_device *dev);
static void seeq8005_timeout(struct net_device *dev); static void seeq8005_timeout(struct net_device *dev);
static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev); static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void seeq8005_rx(struct net_device *dev); static void seeq8005_rx(struct net_device *dev);
static int seeq8005_close(struct net_device *dev); static int seeq8005_close(struct net_device *dev);
static struct net_device_stats *seeq8005_get_stats(struct net_device *dev); static struct net_device_stats *seeq8005_get_stats(struct net_device *dev);
...@@ -400,11 +400,12 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -400,11 +400,12 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
/* The typical workload of the driver: /* The typical workload of the driver:
Handle the network interface interrupts. */ Handle the network interface interrupts. */
static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct net_local *lp; struct net_local *lp;
int ioaddr, status, boguscount = 0; int ioaddr, status, boguscount = 0;
int handled = 0;
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv; lp = (struct net_local *)dev->priv;
...@@ -416,17 +417,20 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -416,17 +417,20 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
} }
if (status & SEEQSTAT_WINDOW_INT) { if (status & SEEQSTAT_WINDOW_INT) {
handled = 1;
outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
if (net_debug) { if (net_debug) {
printk("%s: window int!\n",dev->name); printk("%s: window int!\n",dev->name);
} }
} }
if (status & SEEQSTAT_TX_INT) { if (status & SEEQSTAT_TX_INT) {
handled = 1;
outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
lp->stats.tx_packets++; lp->stats.tx_packets++;
netif_wake_queue(dev); /* Inform upper layers. */ netif_wake_queue(dev); /* Inform upper layers. */
} }
if (status & SEEQSTAT_RX_INT) { if (status & SEEQSTAT_RX_INT) {
handled = 1;
/* Got a packet(s). */ /* Got a packet(s). */
seeq8005_rx(dev); seeq8005_rx(dev);
} }
...@@ -436,6 +440,7 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -436,6 +440,7 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if(net_debug>2) { if(net_debug>2) {
printk("%s: eoi\n",dev->name); printk("%s: eoi\n",dev->name);
} }
return IRQ_RETVAL(handled);
} }
/* We have a good packet(s), get it/them out of the buffers. */ /* We have a good packet(s), get it/them out of the buffers. */
......
...@@ -124,6 +124,7 @@ static void qe_init_rings(struct sunqe *qep) ...@@ -124,6 +124,7 @@ static void qe_init_rings(struct sunqe *qep)
qb->qe_rxd[i].rx_flags = qb->qe_rxd[i].rx_flags =
(RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH)); (RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH));
} }
return IRQ_HANDLED;
} }
static int qe_init(struct sunqe *qep, int from_irq) static int qe_init(struct sunqe *qep, int from_irq)
......
...@@ -201,7 +201,7 @@ static int streamer_open(struct net_device *dev); ...@@ -201,7 +201,7 @@ static int streamer_open(struct net_device *dev);
static int streamer_xmit(struct sk_buff *skb, struct net_device *dev); static int streamer_xmit(struct sk_buff *skb, struct net_device *dev);
static int streamer_close(struct net_device *dev); static int streamer_close(struct net_device *dev);
static void streamer_set_rx_mode(struct net_device *dev); static void streamer_set_rx_mode(struct net_device *dev);
static void streamer_interrupt(int irq, void *dev_id, static irqreturn_t streamer_interrupt(int irq, void *dev_id,
struct pt_regs *regs); struct pt_regs *regs);
static struct net_device_stats *streamer_get_stats(struct net_device *dev); static struct net_device_stats *streamer_get_stats(struct net_device *dev);
static int streamer_set_mac_address(struct net_device *dev, void *addr); static int streamer_set_mac_address(struct net_device *dev, void *addr);
...@@ -1021,7 +1021,7 @@ static void streamer_rx(struct net_device *dev) ...@@ -1021,7 +1021,7 @@ static void streamer_rx(struct net_device *dev)
} /* end for all completed rx descriptors */ } /* end for all completed rx descriptors */
} }
static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *) dev_id; struct net_device *dev = (struct net_device *) dev_id;
struct streamer_private *streamer_priv = struct streamer_private *streamer_priv =
...@@ -1142,6 +1142,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1142,6 +1142,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} /* while() */ } /* while() */
spin_unlock(&streamer_priv->streamer_lock) ; spin_unlock(&streamer_priv->streamer_lock) ;
return IRQ_HANDLED;
} }
static int streamer_xmit(struct sk_buff *skb, struct net_device *dev) static int streamer_xmit(struct sk_buff *skb, struct net_device *dev)
......
...@@ -2027,7 +2027,7 @@ set_multicast_list(struct net_device *dev) ...@@ -2027,7 +2027,7 @@ set_multicast_list(struct net_device *dev)
} }
} }
return; return IRQ_HANDLED;
} }
/* /*
......
...@@ -117,7 +117,7 @@ static int lmc_rx (struct net_device *dev); ...@@ -117,7 +117,7 @@ static int lmc_rx (struct net_device *dev);
static int lmc_open(struct net_device *dev); static int lmc_open(struct net_device *dev);
static int lmc_close(struct net_device *dev); static int lmc_close(struct net_device *dev);
static struct net_device_stats *lmc_get_stats(struct net_device *dev); static struct net_device_stats *lmc_get_stats(struct net_device *dev);
static void lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static int lmc_set_config(struct net_device *dev, struct ifmap *map); static int lmc_set_config(struct net_device *dev, struct ifmap *map);
static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size); static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
static void lmc_softreset(lmc_softc_t * const); static void lmc_softreset(lmc_softc_t * const);
...@@ -1388,7 +1388,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ ...@@ -1388,7 +1388,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/
/* Interrupt handling routine. This will take an incoming packet, or clean /* Interrupt handling routine. This will take an incoming packet, or clean
* up after a trasmit. * up after a trasmit.
*/ */
static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/ static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
{ {
struct net_device *dev = (struct net_device *) dev_instance; struct net_device *dev = (struct net_device *) dev_instance;
lmc_softc_t *sc; lmc_softc_t *sc;
...@@ -1398,6 +1398,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /* ...@@ -1398,6 +1398,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
unsigned int badtx; unsigned int badtx;
u32 firstcsr; u32 firstcsr;
int max_work = LMC_RXDESCS; int max_work = LMC_RXDESCS;
int handled = 0;
lmc_trace(dev, "lmc_interrupt in"); lmc_trace(dev, "lmc_interrupt in");
...@@ -1421,6 +1422,8 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /* ...@@ -1421,6 +1422,8 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
/* always go through this loop at least once */ /* always go through this loop at least once */
while (csr & sc->lmc_intrmask) { while (csr & sc->lmc_intrmask) {
handled = 1;
/* /*
* Clear interrupt bits, we handle all case below * Clear interrupt bits, we handle all case below
*/ */
...@@ -1580,6 +1583,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /* ...@@ -1580,6 +1583,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
spin_unlock(&sc->lmc_lock); spin_unlock(&sc->lmc_lock);
lmc_trace(dev, "lmc_interrupt out"); lmc_trace(dev, "lmc_interrupt out");
return IRQ_RETVAL(handled);
} }
static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/
......
...@@ -275,15 +275,11 @@ init_airport(void) ...@@ -275,15 +275,11 @@ init_airport(void)
printk(KERN_DEBUG "%s\n", version); printk(KERN_DEBUG "%s\n", version);
MOD_INC_USE_COUNT;
/* Lookup card in device tree */ /* Lookup card in device tree */
airport_node = find_devices("radio"); airport_node = find_devices("radio");
if (airport_node && !strcmp(airport_node->parent->name, "mac-io")) if (airport_node && !strcmp(airport_node->parent->name, "mac-io"))
airport_dev = airport_attach(airport_node); airport_dev = airport_attach(airport_node);
MOD_DEC_USE_COUNT;
return airport_dev ? 0 : -ENODEV; return airport_dev ? 0 : -ENODEV;
} }
......
...@@ -329,7 +329,7 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc); ...@@ -329,7 +329,7 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc);
#endif #endif
void arcnet_unregister_proto(struct ArcProto *proto); void arcnet_unregister_proto(struct ArcProto *proto);
void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs); irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
void arcdev_setup(struct net_device *dev); void arcdev_setup(struct net_device *dev);
void arcnet_rx(struct net_device *dev, int bufnum); void arcnet_rx(struct net_device *dev, int bufnum);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment