diff options
author | Michael Chan <mchan@broadcom.com> | 2006-03-20 20:48:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:48:03 -0500 |
commit | bc1c756741b065cfebf850e4164c0e2aae9d527f (patch) | |
tree | e462b85564a66b0c4f41e0d9f1ccde7c98ba00a9 /drivers | |
parent | 4e3a7aaa28db952392814f889dfbd25672266d29 (diff) |
[TG3]: Support shutdown WoL.
Support WoL during shutdown by calling
tg3_set_power_state(tp, PCI_D3hot) during tg3_close().
Change the power state parameter to pci_power_t type and use
constants defined in pci.h.
Certain ethtool operations cannot be performed after tg3_close()
because the device will go to low power state. Add return -EAGAIN
in such cases where appropriate.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7deebd74223e..01fed17d076f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -1042,9 +1042,11 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1042 | struct net_device *dev_peer; | 1042 | struct net_device *dev_peer; |
1043 | 1043 | ||
1044 | dev_peer = pci_get_drvdata(tp->pdev_peer); | 1044 | dev_peer = pci_get_drvdata(tp->pdev_peer); |
1045 | /* remove_one() may have been run on the peer. */ | ||
1045 | if (!dev_peer) | 1046 | if (!dev_peer) |
1046 | BUG(); | 1047 | tp_peer = tp; |
1047 | tp_peer = netdev_priv(dev_peer); | 1048 | else |
1049 | tp_peer = netdev_priv(dev_peer); | ||
1048 | } | 1050 | } |
1049 | 1051 | ||
1050 | if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || | 1052 | if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || |
@@ -1135,7 +1137,7 @@ static int tg3_halt_cpu(struct tg3 *, u32); | |||
1135 | static int tg3_nvram_lock(struct tg3 *); | 1137 | static int tg3_nvram_lock(struct tg3 *); |
1136 | static void tg3_nvram_unlock(struct tg3 *); | 1138 | static void tg3_nvram_unlock(struct tg3 *); |
1137 | 1139 | ||
1138 | static int tg3_set_power_state(struct tg3 *tp, int state) | 1140 | static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) |
1139 | { | 1141 | { |
1140 | u32 misc_host_ctrl; | 1142 | u32 misc_host_ctrl; |
1141 | u16 power_control, power_caps; | 1143 | u16 power_control, power_caps; |
@@ -1154,7 +1156,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1154 | power_control |= PCI_PM_CTRL_PME_STATUS; | 1156 | power_control |= PCI_PM_CTRL_PME_STATUS; |
1155 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); | 1157 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); |
1156 | switch (state) { | 1158 | switch (state) { |
1157 | case 0: | 1159 | case PCI_D0: |
1158 | power_control |= 0; | 1160 | power_control |= 0; |
1159 | pci_write_config_word(tp->pdev, | 1161 | pci_write_config_word(tp->pdev, |
1160 | pm + PCI_PM_CTRL, | 1162 | pm + PCI_PM_CTRL, |
@@ -1167,15 +1169,15 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1167 | 1169 | ||
1168 | return 0; | 1170 | return 0; |
1169 | 1171 | ||
1170 | case 1: | 1172 | case PCI_D1: |
1171 | power_control |= 1; | 1173 | power_control |= 1; |
1172 | break; | 1174 | break; |
1173 | 1175 | ||
1174 | case 2: | 1176 | case PCI_D2: |
1175 | power_control |= 2; | 1177 | power_control |= 2; |
1176 | break; | 1178 | break; |
1177 | 1179 | ||
1178 | case 3: | 1180 | case PCI_D3hot: |
1179 | power_control |= 3; | 1181 | power_control |= 3; |
1180 | break; | 1182 | break; |
1181 | 1183 | ||
@@ -6206,7 +6208,7 @@ static int tg3_init_hw(struct tg3 *tp) | |||
6206 | int err; | 6208 | int err; |
6207 | 6209 | ||
6208 | /* Force the chip into D0. */ | 6210 | /* Force the chip into D0. */ |
6209 | err = tg3_set_power_state(tp, 0); | 6211 | err = tg3_set_power_state(tp, PCI_D0); |
6210 | if (err) | 6212 | if (err) |
6211 | goto out; | 6213 | goto out; |
6212 | 6214 | ||
@@ -6493,6 +6495,10 @@ static int tg3_open(struct net_device *dev) | |||
6493 | 6495 | ||
6494 | tg3_full_lock(tp, 0); | 6496 | tg3_full_lock(tp, 0); |
6495 | 6497 | ||
6498 | err = tg3_set_power_state(tp, PCI_D0); | ||
6499 | if (err) | ||
6500 | return err; | ||
6501 | |||
6496 | tg3_disable_ints(tp); | 6502 | tg3_disable_ints(tp); |
6497 | tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; | 6503 | tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; |
6498 | 6504 | ||
@@ -6872,7 +6878,6 @@ static int tg3_close(struct net_device *dev) | |||
6872 | tp->tg3_flags &= | 6878 | tp->tg3_flags &= |
6873 | ~(TG3_FLAG_INIT_COMPLETE | | 6879 | ~(TG3_FLAG_INIT_COMPLETE | |
6874 | TG3_FLAG_GOT_SERDES_FLOWCTL); | 6880 | TG3_FLAG_GOT_SERDES_FLOWCTL); |
6875 | netif_carrier_off(tp->dev); | ||
6876 | 6881 | ||
6877 | tg3_full_unlock(tp); | 6882 | tg3_full_unlock(tp); |
6878 | 6883 | ||
@@ -6889,6 +6894,10 @@ static int tg3_close(struct net_device *dev) | |||
6889 | 6894 | ||
6890 | tg3_free_consistent(tp); | 6895 | tg3_free_consistent(tp); |
6891 | 6896 | ||
6897 | tg3_set_power_state(tp, PCI_D3hot); | ||
6898 | |||
6899 | netif_carrier_off(tp->dev); | ||
6900 | |||
6892 | return 0; | 6901 | return 0; |
6893 | } | 6902 | } |
6894 | 6903 | ||
@@ -7207,6 +7216,9 @@ static void tg3_get_regs(struct net_device *dev, | |||
7207 | 7216 | ||
7208 | memset(p, 0, TG3_REGDUMP_LEN); | 7217 | memset(p, 0, TG3_REGDUMP_LEN); |
7209 | 7218 | ||
7219 | if (tp->link_config.phy_is_low_power) | ||
7220 | return; | ||
7221 | |||
7210 | tg3_full_lock(tp, 0); | 7222 | tg3_full_lock(tp, 0); |
7211 | 7223 | ||
7212 | #define __GET_REG32(reg) (*(p)++ = tr32(reg)) | 7224 | #define __GET_REG32(reg) (*(p)++ = tr32(reg)) |
@@ -7281,6 +7293,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
7281 | u8 *pd; | 7293 | u8 *pd; |
7282 | u32 i, offset, len, val, b_offset, b_count; | 7294 | u32 i, offset, len, val, b_offset, b_count; |
7283 | 7295 | ||
7296 | if (tp->link_config.phy_is_low_power) | ||
7297 | return -EAGAIN; | ||
7298 | |||
7284 | offset = eeprom->offset; | 7299 | offset = eeprom->offset; |
7285 | len = eeprom->len; | 7300 | len = eeprom->len; |
7286 | eeprom->len = 0; | 7301 | eeprom->len = 0; |
@@ -7342,6 +7357,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
7342 | u32 offset, len, b_offset, odd_len, start, end; | 7357 | u32 offset, len, b_offset, odd_len, start, end; |
7343 | u8 *buf; | 7358 | u8 *buf; |
7344 | 7359 | ||
7360 | if (tp->link_config.phy_is_low_power) | ||
7361 | return -EAGAIN; | ||
7362 | |||
7345 | if (eeprom->magic != TG3_EEPROM_MAGIC) | 7363 | if (eeprom->magic != TG3_EEPROM_MAGIC) |
7346 | return -EINVAL; | 7364 | return -EINVAL; |
7347 | 7365 | ||
@@ -8262,6 +8280,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
8262 | { | 8280 | { |
8263 | struct tg3 *tp = netdev_priv(dev); | 8281 | struct tg3 *tp = netdev_priv(dev); |
8264 | 8282 | ||
8283 | if (tp->link_config.phy_is_low_power) | ||
8284 | tg3_set_power_state(tp, PCI_D0); | ||
8285 | |||
8265 | memset(data, 0, sizeof(u64) * TG3_NUM_TEST); | 8286 | memset(data, 0, sizeof(u64) * TG3_NUM_TEST); |
8266 | 8287 | ||
8267 | if (tg3_test_nvram(tp) != 0) { | 8288 | if (tg3_test_nvram(tp) != 0) { |
@@ -8319,6 +8340,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
8319 | 8340 | ||
8320 | tg3_full_unlock(tp); | 8341 | tg3_full_unlock(tp); |
8321 | } | 8342 | } |
8343 | if (tp->link_config.phy_is_low_power) | ||
8344 | tg3_set_power_state(tp, PCI_D3hot); | ||
8345 | |||
8322 | } | 8346 | } |
8323 | 8347 | ||
8324 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 8348 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
@@ -8338,6 +8362,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
8338 | if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) | 8362 | if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) |
8339 | break; /* We have no PHY */ | 8363 | break; /* We have no PHY */ |
8340 | 8364 | ||
8365 | if (tp->link_config.phy_is_low_power) | ||
8366 | return -EAGAIN; | ||
8367 | |||
8341 | spin_lock_bh(&tp->lock); | 8368 | spin_lock_bh(&tp->lock); |
8342 | err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); | 8369 | err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); |
8343 | spin_unlock_bh(&tp->lock); | 8370 | spin_unlock_bh(&tp->lock); |
@@ -8354,6 +8381,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
8354 | if (!capable(CAP_NET_ADMIN)) | 8381 | if (!capable(CAP_NET_ADMIN)) |
8355 | return -EPERM; | 8382 | return -EPERM; |
8356 | 8383 | ||
8384 | if (tp->link_config.phy_is_low_power) | ||
8385 | return -EAGAIN; | ||
8386 | |||
8357 | spin_lock_bh(&tp->lock); | 8387 | spin_lock_bh(&tp->lock); |
8358 | err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); | 8388 | err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); |
8359 | spin_unlock_bh(&tp->lock); | 8389 | spin_unlock_bh(&tp->lock); |
@@ -9805,7 +9835,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9805 | tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; | 9835 | tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; |
9806 | 9836 | ||
9807 | /* Force the chip into D0. */ | 9837 | /* Force the chip into D0. */ |
9808 | err = tg3_set_power_state(tp, 0); | 9838 | err = tg3_set_power_state(tp, PCI_D0); |
9809 | if (err) { | 9839 | if (err) { |
9810 | printk(KERN_ERR PFX "(%s) transition to D0 failed\n", | 9840 | printk(KERN_ERR PFX "(%s) transition to D0 failed\n", |
9811 | pci_name(tp->pdev)); | 9841 | pci_name(tp->pdev)); |
@@ -11078,7 +11108,7 @@ static int tg3_resume(struct pci_dev *pdev) | |||
11078 | 11108 | ||
11079 | pci_restore_state(tp->pdev); | 11109 | pci_restore_state(tp->pdev); |
11080 | 11110 | ||
11081 | err = tg3_set_power_state(tp, 0); | 11111 | err = tg3_set_power_state(tp, PCI_D0); |
11082 | if (err) | 11112 | if (err) |
11083 | return err; | 11113 | return err; |
11084 | 11114 | ||