diff options
author | Michael Chan <mchan@broadcom.com> | 2005-12-14 00:15:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-12-14 00:15:53 -0500 |
commit | 6921d201f77e14848df2eaa597e26525f468abea (patch) | |
tree | cef66b131fd1cb980d209c5ecb590a0783fdf985 /drivers/net/tg3.c | |
parent | 16fe9d74f14ed74af778c5db7f9129e29916f4a7 (diff) |
[TG3]: Fix low power state
Fix the following bugs in tg3_set_power_state():
1. Both WOL and ASF flags require switching to aux power.
2. Add a missing handshake with firmware to enable WOL.
3. Turn off the PHY if both WOL and ASF are disabled.
4. Add nvram arbitration before halting the firmware.
5. Fix tg3_setup_copper_phy() to switch to 100Mbps when
changing to low power state.
Update revision and date.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a143c18c7bc6..a23ed28a72b8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -68,8 +68,8 @@ | |||
68 | 68 | ||
69 | #define DRV_MODULE_NAME "tg3" | 69 | #define DRV_MODULE_NAME "tg3" |
70 | #define PFX DRV_MODULE_NAME ": " | 70 | #define PFX DRV_MODULE_NAME ": " |
71 | #define DRV_MODULE_VERSION "3.44" | 71 | #define DRV_MODULE_VERSION "3.45" |
72 | #define DRV_MODULE_RELDATE "Dec 6, 2005" | 72 | #define DRV_MODULE_RELDATE "Dec 13, 2005" |
73 | 73 | ||
74 | #define TG3_DEF_MAC_MODE 0 | 74 | #define TG3_DEF_MAC_MODE 0 |
75 | #define TG3_DEF_RX_MODE 0 | 75 | #define TG3_DEF_RX_MODE 0 |
@@ -1025,7 +1025,9 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1025 | 1025 | ||
1026 | 1026 | ||
1027 | if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || | 1027 | if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || |
1028 | (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) { | 1028 | (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 || |
1029 | (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || | ||
1030 | (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { | ||
1029 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || | 1031 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || |
1030 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { | 1032 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { |
1031 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1033 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
@@ -1105,6 +1107,8 @@ static int tg3_setup_phy(struct tg3 *, int); | |||
1105 | 1107 | ||
1106 | static void tg3_write_sig_post_reset(struct tg3 *, int); | 1108 | static void tg3_write_sig_post_reset(struct tg3 *, int); |
1107 | static int tg3_halt_cpu(struct tg3 *, u32); | 1109 | static int tg3_halt_cpu(struct tg3 *, u32); |
1110 | static int tg3_nvram_lock(struct tg3 *); | ||
1111 | static void tg3_nvram_unlock(struct tg3 *); | ||
1108 | 1112 | ||
1109 | static int tg3_set_power_state(struct tg3 *tp, int state) | 1113 | static int tg3_set_power_state(struct tg3 *tp, int state) |
1110 | { | 1114 | { |
@@ -1179,6 +1183,21 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1179 | tg3_setup_phy(tp, 0); | 1183 | tg3_setup_phy(tp, 0); |
1180 | } | 1184 | } |
1181 | 1185 | ||
1186 | if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { | ||
1187 | int i; | ||
1188 | u32 val; | ||
1189 | |||
1190 | for (i = 0; i < 200; i++) { | ||
1191 | tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val); | ||
1192 | if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) | ||
1193 | break; | ||
1194 | msleep(1); | ||
1195 | } | ||
1196 | } | ||
1197 | tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE | | ||
1198 | WOL_DRV_STATE_SHUTDOWN | | ||
1199 | WOL_DRV_WOL | WOL_SET_MAGIC_PKT); | ||
1200 | |||
1182 | pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps); | 1201 | pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps); |
1183 | 1202 | ||
1184 | if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { | 1203 | if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { |
@@ -1268,6 +1287,17 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1268 | } | 1287 | } |
1269 | } | 1288 | } |
1270 | 1289 | ||
1290 | if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && | ||
1291 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { | ||
1292 | /* Turn off the PHY */ | ||
1293 | if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { | ||
1294 | tg3_writephy(tp, MII_TG3_EXT_CTRL, | ||
1295 | MII_TG3_EXT_CTRL_FORCE_LED_OFF); | ||
1296 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); | ||
1297 | tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1271 | tg3_frob_aux_power(tp); | 1301 | tg3_frob_aux_power(tp); |
1272 | 1302 | ||
1273 | /* Workaround for unstable PLL clock */ | 1303 | /* Workaround for unstable PLL clock */ |
@@ -1277,8 +1307,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1277 | 1307 | ||
1278 | val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); | 1308 | val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); |
1279 | tw32(0x7d00, val); | 1309 | tw32(0x7d00, val); |
1280 | if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) | 1310 | if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { |
1311 | tg3_nvram_lock(tp); | ||
1281 | tg3_halt_cpu(tp, RX_CPU_BASE); | 1312 | tg3_halt_cpu(tp, RX_CPU_BASE); |
1313 | tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0); | ||
1314 | tg3_nvram_unlock(tp); | ||
1315 | } | ||
1282 | } | 1316 | } |
1283 | 1317 | ||
1284 | /* Finally, set the new power state. */ | 1318 | /* Finally, set the new power state. */ |
@@ -1812,7 +1846,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) | |||
1812 | } | 1846 | } |
1813 | } | 1847 | } |
1814 | relink: | 1848 | relink: |
1815 | if (current_link_up == 0) { | 1849 | if (current_link_up == 0 || tp->link_config.phy_is_low_power) { |
1816 | u32 tmp; | 1850 | u32 tmp; |
1817 | 1851 | ||
1818 | tg3_phy_copper_begin(tp); | 1852 | tg3_phy_copper_begin(tp); |