diff options
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
| -rw-r--r-- | drivers/net/e1000/e1000_main.c | 54 | 
1 files changed, 37 insertions, 17 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ddc5c533e89..b1419e21b46 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -156,8 +156,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);  static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);  static void e1000_restore_vlan(struct e1000_adapter *adapter); -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);  #ifdef CONFIG_PM +static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);  static int e1000_resume(struct pci_dev *pdev);  #endif  static void e1000_shutdown(struct pci_dev *pdev); @@ -3738,7 +3738,7 @@ static irqreturn_t e1000_intr(int irq, void *data)  	struct e1000_hw *hw = &adapter->hw;  	u32 rctl, icr = er32(ICR); -	if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags))) +	if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))  		return IRQ_NONE;  /* Not our interrupt */  	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is @@ -3834,7 +3834,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,  	struct e1000_buffer *buffer_info;  	unsigned int i, eop;  	unsigned int count = 0; -	bool cleaned;  	unsigned int total_tx_bytes=0, total_tx_packets=0;  	i = tx_ring->next_to_clean; @@ -3843,7 +3842,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,  	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&  	       (count < tx_ring->count)) { -		for (cleaned = false; !cleaned; count++) { +		bool cleaned = false; +		for ( ; !cleaned; count++) {  			tx_desc = E1000_TX_DESC(*tx_ring, i);  			buffer_info = &tx_ring->buffer_info[i];  			cleaned = (i == eop); @@ -3871,7 +3871,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,  	tx_ring->next_to_clean = i;  #define TX_WAKE_THRESHOLD 32 -	if (unlikely(cleaned && netif_carrier_ok(netdev) && +	if (unlikely(count && netif_carrier_ok(netdev) &&  		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {  		/* Make sure that anybody stopping the queue after this  		 * sees the new next_to_clean. @@ -4601,7 +4601,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)  	return 0;  } -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) +static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)  {  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct e1000_adapter *adapter = netdev_priv(netdev); @@ -4664,22 +4664,18 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)  		ew32(WUC, E1000_WUC_PME_EN);  		ew32(WUFC, wufc); -		pci_enable_wake(pdev, PCI_D3hot, 1); -		pci_enable_wake(pdev, PCI_D3cold, 1);  	} else {  		ew32(WUC, 0);  		ew32(WUFC, 0); -		pci_enable_wake(pdev, PCI_D3hot, 0); -		pci_enable_wake(pdev, PCI_D3cold, 0);  	}  	e1000_release_manageability(adapter); +	*enable_wake = !!wufc; +  	/* make sure adapter isn't asleep if manageability is enabled */ -	if (adapter->en_mng_pt) { -		pci_enable_wake(pdev, PCI_D3hot, 1); -		pci_enable_wake(pdev, PCI_D3cold, 1); -	} +	if (adapter->en_mng_pt) +		*enable_wake = true;  	if (hw->phy_type == e1000_phy_igp_3)  		e1000_phy_powerdown_workaround(hw); @@ -4693,12 +4689,29 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)  	pci_disable_device(pdev); -	pci_set_power_state(pdev, pci_choose_state(pdev, state)); -  	return 0;  }  #ifdef CONFIG_PM +static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) +{ +	int retval; +	bool wake; + +	retval = __e1000_shutdown(pdev, &wake); +	if (retval) +		return retval; + +	if (wake) { +		pci_prepare_to_sleep(pdev); +	} else { +		pci_wake_from_d3(pdev, false); +		pci_set_power_state(pdev, PCI_D3hot); +	} + +	return 0; +} +  static int e1000_resume(struct pci_dev *pdev)  {  	struct net_device *netdev = pci_get_drvdata(pdev); @@ -4753,7 +4766,14 @@ static int e1000_resume(struct pci_dev *pdev)  static void e1000_shutdown(struct pci_dev *pdev)  { -	e1000_suspend(pdev, PMSG_SUSPEND); +	bool wake; + +	__e1000_shutdown(pdev, &wake); + +	if (system_state == SYSTEM_POWER_OFF) { +		pci_wake_from_d3(pdev, wake); +		pci_set_power_state(pdev, PCI_D3hot); +	}  }  #ifdef CONFIG_NET_POLL_CONTROLLER  |