diff -Naurp linux-2.4.20-pre4-e1000-3/drivers/net/e1000/e1000.h linux-2.4.20-pre4-e1000-4/drivers/net/e1000/e1000.h --- linux-2.4.20-pre4-e1000-3/drivers/net/e1000/e1000.h Fri Aug 23 05:52:48 2002 +++ linux-2.4.20-pre4-e1000-4/drivers/net/e1000/e1000.h Fri Aug 23 06:48:03 2002 @@ -195,5 +195,8 @@ struct e1000_adapter { uint32_t pci_state[16]; + + /* Semaphore for locking HW access vs. i2c-i8254x SMBUS driver */ + struct semaphore smbus_lock; }; #endif /* _E1000_H_ */ diff -Naurp linux-2.4.20-pre4-e1000-3/drivers/net/e1000/e1000_main.c linux-2.4.20-pre4-e1000-4/drivers/net/e1000/e1000_main.c --- linux-2.4.20-pre4-e1000-3/drivers/net/e1000/e1000_main.c Fri Aug 23 05:52:48 2002 +++ linux-2.4.20-pre4-e1000-4/drivers/net/e1000/e1000_main.c Fri Aug 23 06:48:03 2002 @@ -113,6 +113,7 @@ static char *e1000_strings[] = { int e1000_up(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter); void e1000_reset(struct e1000_adapter *adapter); +void e1000_smbus_lock(struct pci_dev *pdev, boolean_t lock); static int e1000_init_module(void); static void e1000_exit_module(void); @@ -150,6 +151,8 @@ static void e1000_leave_82542_rst(struct static inline void e1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb); +static boolean_t e1000_smbus_arp_enable(struct e1000_adapter *adapter, + boolean_t arp_enable); static void e1000_tx_timeout(struct net_device *dev); static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); @@ -191,6 +194,10 @@ MODULE_AUTHOR("Intel Corporation, hw, PBA, E1000_DEFAULT_PBA); adapter->hw.fc = adapter->hw.original_fc; + down(&adapter->smbus_lock); e1000_reset_hw(&adapter->hw); + up(&adapter->smbus_lock); if(adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); e1000_init_hw(&adapter->hw); @@ -490,16 +499,9 @@ e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; - - if(adapter->hw.mac_type >= e1000_82540) { - manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { - manc |= E1000_MANC_ARP_EN; - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } - } - + + e1000_smbus_arp_enable(adapter, TRUE); + unregister_netdev(netdev); e1000_phy_hw_reset(&adapter->hw); @@ -623,6 +625,7 @@ e1000_sw_init(struct e1000_adapter *adap atomic_set(&adapter->irq_sem, 1); spin_lock_init(&adapter->stats_lock); + init_MUTEX(&adapter->smbus_lock); } /** @@ -2141,7 +2144,7 @@ e1000_suspend(struct pci_dev *pdev, uint { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t ctrl, ctrl_ext, rctl, manc; + uint32_t ctrl, ctrl_ext, rctl; netif_device_detach(netdev); @@ -2180,13 +2183,7 @@ e1000_suspend(struct pci_dev *pdev, uint pci_save_state(pdev, adapter->pci_state); - if(adapter->hw.mac_type >= e1000_82540) { - manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { - manc |= E1000_MANC_ARP_EN; - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } - } else + if(!e1000_smbus_arp_enable(adapter, TRUE)) pci_set_power_state(pdev, 3); return 0; @@ -2198,7 +2195,6 @@ e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; pci_set_power_state(pdev, 0); pci_restore_state(pdev, adapter->pci_state); @@ -2213,14 +2209,53 @@ e1000_resume(struct pci_dev *pdev) netif_device_attach(netdev); - if(adapter->hw.mac_type >= e1000_82540) { - manc = E1000_READ_REG(&adapter->hw, MANC); - manc &= ~(E1000_MANC_ARP_EN); - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } + e1000_smbus_arp_enable(adapter, FALSE); return 0; } #endif +/** + * e1000_smbus_lock - Exported for lock/unlock external smbus hw access + * @pdev: PCI device information struct + * @lock: TRUE to lock hw access; FALSE to unlock + * + * e1000_smbus_lock is designed to allow synchronization between e1000 + * driver and i2c-i8254x SMBUS bus driver when accessing e1000 hardware + **/ +void +e1000_smbus_lock(struct pci_dev *pdev, boolean_t lock) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + + if (lock) + down(&adapter->smbus_lock); + else + up(&adapter->smbus_lock); +} + +static boolean_t +e1000_smbus_arp_enable(struct e1000_adapter *adapter, boolean_t arp_enable) +{ + uint32_t manc; + boolean_t ret_val = FALSE; + + if(adapter->hw.mac_type < e1000_82540) + return ret_val; + + down(&adapter->smbus_lock); + manc = E1000_READ_REG(&adapter->hw, MANC); + if(!arp_enable) { + manc &= ~(E1000_MANC_ARP_EN); + } else if(manc & E1000_MANC_SMBUS_EN) { + manc |= E1000_MANC_ARP_EN; + ret_val = TRUE; + } + E1000_WRITE_REG(&adapter->hw, MANC, manc); + up(&adapter->smbus_lock); + + return ret_val; +} + /* e1000_main.c */ .