From: Stefan Assmann <sassmann@redhat.com> Date: Wed, 24 Feb 2010 07:41:08 -0500 Subject: [net] igb: fix WoL initialization when disabled in eeprom Message-id: <4B84D814.9040807@redhat.com> Patchwork-id: 23415 O-Subject: [RHEL 5.5 PATCH] igb: fix WoL initialization when WoL is disabled in the eeprom Bugzilla: 564102 RH-Acked-by: Andy Gospodarek <gospo@redhat.com> RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Jiri Pirko <jpirko@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=564102 Description: When WoL is disabled in the EEPROM (adapter->wol=0) the device_init_wakeup() function will disable both can/should_wakeup flags. >From include/linux/pm.h: do { \ device_can_wakeup(dev) = !!(val); \ device_set_wakeup_enable(dev,val); \ } while(0) So basically WoL will appear as unsupported to the driver on any port for which WoL was disabled in the EEPROM. Fix this by forcing device_can_wakeup = 1 and restoring WoL EEPROM setting afterwards. Additionally ethtool code for enabling Wake on Lan was not correctly checking the status register bits so as a result ports 0 and 2 were both being allowed to set WoL to enabled even though it is only supported on the first port for our adapters. Upstream Status: http://git.kernel.org/linus/e1b86d8479f90aadee57a3d07d8e61c815c202d9 http://git.kernel.org/linus/58b8b042509f53955ba660a4245e221c5405f124 Brew Build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2275908 Test Status: Fix has been verified by Intel and myself. Stefan diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 4b5c78a..0fa46b0 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1843,7 +1843,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, /* dual port cards only support WoL on port A from now on * unless it was enabled in the eeprom for port B * so exclude FUNC_1 ports from having WoL enabled */ - if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1 && + if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) && !adapter->eeprom_wol) { wol->supported = 0; break; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1a4ece2..a570003 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1514,7 +1514,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* initialize the wol settings based on the eeprom settings */ adapter->wol = adapter->eeprom_wol; - device_init_wakeup(&adapter->pdev->dev, adapter->wol); + /* set can_wakeup = 1 by calling device_init_wakeup and restore + * wol eeprom setting afterwards. */ + device_init_wakeup(&adapter->pdev->dev, true); + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); /* reset the hardware with the new settings */ igb_reset(adapter);