Commit 7949d93e authored by Scott Feldman's avatar Scott Feldman Committed by Jeff Garzik

e1000 net driver update 3/4:

* Added four new device IDs: 82545EM_COPPER, 82545EM_FIBER,
82546EB_COPPER, 82546EB_FIBER.
* Added a couple magic number definitions for DMA addressable bits.
* Added Power Management Suspend/Resume support.
* Added reboot notifier registration to setup WOL when shutting down.
parent a8ea92e8
...@@ -107,17 +107,21 @@ ...@@ -107,17 +107,21 @@
#include <linux/udp.h> #include <linux/udp.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/reboot.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#ifdef NETIF_F_HW_VLAN_TX #ifdef NETIF_F_HW_VLAN_TX
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#endif #endif
#define BAR_0 0
#define PCI_DMA_64BIT 0xffffffffffffffffULL
#define PCI_DMA_32BIT 0x00000000ffffffffULL
struct e1000_adapter; struct e1000_adapter;
#include "e1000_hw.h" #include "e1000_hw.h"
#define BAR_0 0
#if DBG #if DBG
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
#else #else
...@@ -233,5 +237,7 @@ struct e1000_adapter { ...@@ -233,5 +237,7 @@ struct e1000_adapter {
struct e1000_phy_stats phy_stats; struct e1000_phy_stats phy_stats;
uint32_t pci_state[16];
}; };
#endif /* _E1000_H_ */ #endif /* _E1000_H_ */
...@@ -82,7 +82,6 @@ extern char e1000_driver_version[]; ...@@ -82,7 +82,6 @@ extern char e1000_driver_version[];
extern int e1000_up(struct e1000_adapter *adapter); extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_enable_WOL(struct e1000_adapter *adapter);
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)
...@@ -127,6 +126,10 @@ e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) ...@@ -127,6 +126,10 @@ e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
SUPPORTED_Autoneg); SUPPORTED_Autoneg);
ecmd->port = PORT_FIBRE; ecmd->port = PORT_FIBRE;
if(hw->mac_type >= e1000_82545)
ecmd->transceiver = XCVR_INTERNAL;
else
ecmd->transceiver = XCVR_EXTERNAL; ecmd->transceiver = XCVR_EXTERNAL;
} }
...@@ -264,12 +267,33 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -264,12 +267,33 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if(hw->mac_type < e1000_82544) { switch(adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER:
default:
wol->supported = 0; wol->supported = 0;
wol->wolopts = 0; wol->wolopts = 0;
return; return;
}
case E1000_DEV_ID_82546EB_FIBER:
/* Wake events only supported on port A for dual fiber */
if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
wol->wolopts = 0;
return;
}
/* Fall Through */
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
wol->supported = WAKE_PHY | WAKE_UCAST | wol->supported = WAKE_PHY | WAKE_UCAST |
WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
...@@ -284,6 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -284,6 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
wol->wolopts |= WAKE_BCAST; wol->wolopts |= WAKE_BCAST;
if(adapter->wol & E1000_WUFC_MAG) if(adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC; wol->wolopts |= WAKE_MAGIC;
return;
}
} }
static int static int
...@@ -291,8 +317,30 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -291,8 +317,30 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if(hw->mac_type < e1000_82544) switch(adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER:
default:
return wol->wolopts ? -EOPNOTSUPP : 0;
case E1000_DEV_ID_82546EB_FIBER:
/* Wake events only supported on port A for dual fiber */
if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0; return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
if(wol->wolopts & WAKE_ARP)
return -EOPNOTSUPP;
adapter->wol = 0; adapter->wol = 0;
...@@ -306,8 +354,8 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -306,8 +354,8 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
adapter->wol |= E1000_WUFC_BC; adapter->wol |= E1000_WUFC_BC;
if(wol->wolopts & WAKE_MAGIC) if(wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG; adapter->wol |= E1000_WUFC_MAG;
}
e1000_enable_WOL(adapter);
return 0; return 0;
} }
......
...@@ -2070,6 +2070,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw) ...@@ -2070,6 +2070,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
break; break;
case e1000_82540: case e1000_82540:
case e1000_82545:
case e1000_82546:
if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
break; break;
default: default:
...@@ -2530,6 +2532,13 @@ e1000_read_mac_addr(struct e1000_hw * hw) ...@@ -2530,6 +2532,13 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
} }
if((hw->mac_type == e1000_82546) &&
(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
if(hw->perm_mac_addr[5] & 0x01)
hw->perm_mac_addr[5] &= ~(0x01);
else
hw->perm_mac_addr[5] |= 0x01;
}
for(i = 0; i < NODE_ADDRESS_SIZE; i++) for(i = 0; i < NODE_ADDRESS_SIZE; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i]; hw->mac_addr[i] = hw->perm_mac_addr[i];
return 0; return 0;
...@@ -2884,8 +2893,22 @@ e1000_setup_led(struct e1000_hw *hw) ...@@ -2884,8 +2893,22 @@ e1000_setup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82544GC_LOM: case E1000_DEV_ID_82544GC_LOM:
/* No setup necessary */ /* No setup necessary */
break; break;
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ledctl = E1000_READ_REG(hw, LEDCTL);
/* Save current LEDCTL settings */
hw->ledctl_default = ledctl;
/* Turn off LED0 */
ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
E1000_LEDCTL_LED0_BLINK |
E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT);
E1000_WRITE_REG(hw, LEDCTL, ledctl);
break;
case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break; break;
default: default:
...@@ -2917,6 +2940,10 @@ e1000_cleanup_led(struct e1000_hw *hw) ...@@ -2917,6 +2940,10 @@ e1000_cleanup_led(struct e1000_hw *hw)
break; break;
case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER:
/* Restore LEDCTL settings */ /* Restore LEDCTL settings */
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
break; break;
...@@ -2953,6 +2980,8 @@ e1000_led_on(struct e1000_hw *hw) ...@@ -2953,6 +2980,8 @@ e1000_led_on(struct e1000_hw *hw)
case E1000_DEV_ID_82544EI_COPPER: case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER: case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM: case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ctrl = E1000_READ_REG(hw, CTRL); ctrl = E1000_READ_REG(hw, CTRL);
/* Clear SW Defineable Pin 0 to turn on the LED */ /* Clear SW Defineable Pin 0 to turn on the LED */
ctrl &= ~E1000_CTRL_SWDPIN0; ctrl &= ~E1000_CTRL_SWDPIN0;
...@@ -2961,6 +2990,8 @@ e1000_led_on(struct e1000_hw *hw) ...@@ -2961,6 +2990,8 @@ e1000_led_on(struct e1000_hw *hw)
break; break;
case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
break; break;
default: default:
...@@ -2996,6 +3027,8 @@ e1000_led_off(struct e1000_hw *hw) ...@@ -2996,6 +3027,8 @@ e1000_led_off(struct e1000_hw *hw)
case E1000_DEV_ID_82544EI_COPPER: case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER: case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM: case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ctrl = E1000_READ_REG(hw, CTRL); ctrl = E1000_READ_REG(hw, CTRL);
/* Set SW Defineable Pin 0 to turn off the LED */ /* Set SW Defineable Pin 0 to turn off the LED */
ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIN0;
...@@ -3004,6 +3037,8 @@ e1000_led_off(struct e1000_hw *hw) ...@@ -3004,6 +3037,8 @@ e1000_led_off(struct e1000_hw *hw)
break; break;
case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break; break;
default: default:
......
...@@ -92,6 +92,8 @@ typedef enum { ...@@ -92,6 +92,8 @@ typedef enum {
e1000_82543, e1000_82543,
e1000_82544, e1000_82544,
e1000_82540, e1000_82540,
e1000_82545,
e1000_82546,
e1000_num_macs e1000_num_macs
} e1000_mac_type; } e1000_mac_type;
...@@ -272,7 +274,11 @@ void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); ...@@ -272,7 +274,11 @@ void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
#define E1000_DEV_ID_82544GC_LOM 0x100D #define E1000_DEV_ID_82544GC_LOM 0x100D
#define E1000_DEV_ID_82540EM 0x100E #define E1000_DEV_ID_82540EM 0x100E
#define E1000_DEV_ID_82540EM_LOM 0x1015 #define E1000_DEV_ID_82540EM_LOM 0x1015
#define NUM_DEV_IDS 9 #define E1000_DEV_ID_82545EM_COPPER 0x100F
#define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012
#define NUM_DEV_IDS 13
#define NODE_ADDRESS_SIZE 6 #define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6 #define ETH_LENGTH_OF_ADDRESS 6
......
...@@ -114,6 +114,10 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { ...@@ -114,6 +114,10 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */ /* required last entry */
{0,} {0,}
}; };
...@@ -169,13 +173,24 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter); ...@@ -169,13 +173,24 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static inline void e1000_rx_checksum(struct e1000_adapter *adapter, static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
struct e1000_rx_desc *rx_desc, struct e1000_rx_desc *rx_desc,
struct sk_buff *skb); struct sk_buff *skb);
void e1000_enable_WOL(struct e1000_adapter *adapter);
#ifdef NETIF_F_HW_VLAN_TX #ifdef NETIF_F_HW_VLAN_TX
static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
#endif #endif
static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
static int e1000_suspend(struct pci_dev *pdev, uint32_t state);
#ifdef CONFIG_PM
static int e1000_resume(struct pci_dev *pdev);
#endif
struct notifier_block e1000_notifier = {
notifier_call: e1000_notify_reboot,
next: NULL,
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);
...@@ -189,8 +204,10 @@ static struct pci_driver e1000_driver = { ...@@ -189,8 +204,10 @@ static struct pci_driver e1000_driver = {
probe: e1000_probe, probe: e1000_probe,
remove: __devexit_p(e1000_remove), remove: __devexit_p(e1000_remove),
/* Power Managment Hooks */ /* Power Managment Hooks */
suspend: NULL, #ifdef CONFIG_PM
resume: NULL suspend: e1000_suspend,
resume: e1000_resume
#endif
}; };
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
...@@ -207,12 +224,16 @@ MODULE_LICENSE("Dual BSD/GPL"); ...@@ -207,12 +224,16 @@ MODULE_LICENSE("Dual BSD/GPL");
static int __init static int __init
e1000_init_module(void) e1000_init_module(void)
{ {
int ret;
printk(KERN_INFO "%s - version %s\n", printk(KERN_INFO "%s - version %s\n",
e1000_driver_string, e1000_driver_version); e1000_driver_string, e1000_driver_version);
printk(KERN_INFO "%s\n", e1000_copyright); printk(KERN_INFO "%s\n", e1000_copyright);
return pci_module_init(&e1000_driver); ret = pci_module_init(&e1000_driver);
if(ret >= 0)
register_reboot_notifier(&e1000_notifier);
return ret;
} }
module_init(e1000_init_module); module_init(e1000_init_module);
...@@ -227,6 +248,7 @@ module_init(e1000_init_module); ...@@ -227,6 +248,7 @@ module_init(e1000_init_module);
static void __exit static void __exit
e1000_exit_module(void) e1000_exit_module(void)
{ {
unregister_reboot_notifier(&e1000_notifier);
pci_unregister_driver(&e1000_driver); pci_unregister_driver(&e1000_driver);
} }
...@@ -290,11 +312,11 @@ e1000_reset(struct e1000_adapter *adapter) ...@@ -290,11 +312,11 @@ e1000_reset(struct e1000_adapter *adapter)
adapter->hw.fc = adapter->hw.original_fc; adapter->hw.fc = adapter->hw.original_fc;
e1000_reset_hw(&adapter->hw); e1000_reset_hw(&adapter->hw);
if(adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
e1000_init_hw(&adapter->hw); e1000_init_hw(&adapter->hw);
e1000_reset_adaptive(&adapter->hw); e1000_reset_adaptive(&adapter->hw);
e1000_phy_get_info(&adapter->hw, &adapter->phy_info); e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
e1000_enable_WOL(adapter);
} }
/** /**
...@@ -324,10 +346,10 @@ e1000_probe(struct pci_dev *pdev, ...@@ -324,10 +346,10 @@ e1000_probe(struct pci_dev *pdev,
if((i = pci_enable_device(pdev))) if((i = pci_enable_device(pdev)))
return i; return i;
if(!(i = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff))) { if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
pci_using_dac = 1; pci_using_dac = 1;
} else { } else {
if((i = pci_set_dma_mask(pdev, (u64) 0xffffffff))) { if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
E1000_ERR("No usable DMA configuration, aborting\n"); E1000_ERR("No usable DMA configuration, aborting\n");
return i; return i;
} }
...@@ -447,6 +469,15 @@ e1000_probe(struct pci_dev *pdev, ...@@ -447,6 +469,15 @@ e1000_probe(struct pci_dev *pdev,
e1000_check_options(adapter); e1000_check_options(adapter);
e1000_proc_dev_setup(adapter); e1000_proc_dev_setup(adapter);
/* Initial Wake on LAN setting
* If APM wake is enabled in the EEPROM,
* enable the ACPI Magic Packet filter
*/
if((adapter->hw.mac_type >= e1000_82544) &&
(E1000_READ_REG(&adapter->hw, WUC) & E1000_WUC_APME))
adapter->wol |= E1000_WUFC_MAG;
/* reset the hardware with the new settings */ /* reset the hardware with the new settings */
e1000_reset(adapter); e1000_reset(adapter);
...@@ -557,6 +588,14 @@ e1000_sw_init(struct e1000_adapter *adapter) ...@@ -557,6 +588,14 @@ e1000_sw_init(struct e1000_adapter *adapter)
case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM:
hw->mac_type = e1000_82540; hw->mac_type = e1000_82540;
break; break;
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
hw->mac_type = e1000_82545;
break;
case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER:
hw->mac_type = e1000_82546;
break;
default: default:
/* should never have loaded on this device */ /* should never have loaded on this device */
BUG(); BUG();
...@@ -1981,29 +2020,6 @@ e1000_rx_checksum(struct e1000_adapter *adapter, ...@@ -1981,29 +2020,6 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
} }
} }
/**
* e1000_enable_WOL - Wake On Lan Support (Magic Pkt)
* @adapter: Adapter structure
**/
void
e1000_enable_WOL(struct e1000_adapter *adapter)
{
uint32_t wuc;
if(adapter->hw.mac_type < e1000_82544)
return;
if(adapter->wol) {
wuc = E1000_WUC_APME | E1000_WUC_PME_EN |
E1000_WUC_PME_STATUS | E1000_WUC_APMPME;
E1000_WRITE_REG(&adapter->hw, WUC, wuc);
E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
}
}
void void
e1000_write_pci_cfg(struct e1000_hw *hw, e1000_write_pci_cfg(struct e1000_hw *hw,
uint32_t reg, uint16_t *value) uint32_t reg, uint16_t *value)
...@@ -2091,4 +2107,93 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ...@@ -2091,4 +2107,93 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
} }
#endif #endif
static int
e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
pci_for_each_dev(pdev) {
if(pci_dev_driver(pdev) == &e1000_driver)
e1000_suspend(pdev, 3);
}
}
return NOTIFY_DONE;
}
static int
e1000_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
uint32_t ctrl, ctrl_ext, rctl;
netif_device_detach(netdev);
if(netif_running(netdev))
e1000_down(adapter);
if(adapter->wol) {
e1000_setup_rctl(adapter);
e1000_set_multi(netdev);
if(adapter->wol & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
if(adapter->hw.media_type == e1000_media_type_fiber) {
#define E1000_CTRL_ADVD3WUC 0x00100000
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl |= E1000_CTRL_ADVD3WUC;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
}
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
pci_enable_wake(pdev, 3, 1);
} else {
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, 0);
pci_enable_wake(pdev, 3, 0);
}
pci_save_state(pdev, adapter->pci_state);
pci_set_power_state(pdev, 3);
return 0;
}
#ifdef CONFIG_PM
static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev, adapter->pci_state);
pci_enable_wake(pdev, 0, 0);
/* Clear the wakeup status bits */
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
if(netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
return 0;
}
#endif
/* e1000_main.c */ /* e1000_main.c */
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