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 | |
| 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>
| -rw-r--r-- | drivers/net/tg3.c | 44 | ||||
| -rw-r--r-- | drivers/net/tg3.h | 7 |
2 files changed, 46 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); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index fb7e2a5f4a08..94dbcf3537ec 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
| @@ -1529,6 +1529,12 @@ | |||
| 1529 | #define NIC_SRAM_MAC_ADDR_HIGH_MBOX 0x00000c14 | 1529 | #define NIC_SRAM_MAC_ADDR_HIGH_MBOX 0x00000c14 |
| 1530 | #define NIC_SRAM_MAC_ADDR_LOW_MBOX 0x00000c18 | 1530 | #define NIC_SRAM_MAC_ADDR_LOW_MBOX 0x00000c18 |
| 1531 | 1531 | ||
| 1532 | #define NIC_SRAM_WOL_MBOX 0x00000d30 | ||
| 1533 | #define WOL_SIGNATURE 0x474c0000 | ||
| 1534 | #define WOL_DRV_STATE_SHUTDOWN 0x00000001 | ||
| 1535 | #define WOL_DRV_WOL 0x00000002 | ||
| 1536 | #define WOL_SET_MAGIC_PKT 0x00000004 | ||
| 1537 | |||
| 1532 | #define NIC_SRAM_DATA_CFG_2 0x00000d38 | 1538 | #define NIC_SRAM_DATA_CFG_2 0x00000d38 |
| 1533 | 1539 | ||
| 1534 | #define SHASTA_EXT_LED_MODE_MASK 0x00018000 | 1540 | #define SHASTA_EXT_LED_MODE_MASK 0x00018000 |
| @@ -1565,6 +1571,7 @@ | |||
| 1565 | #define MII_TG3_EXT_CTRL 0x10 /* Extended control register */ | 1571 | #define MII_TG3_EXT_CTRL 0x10 /* Extended control register */ |
| 1566 | #define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001 | 1572 | #define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001 |
| 1567 | #define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 | 1573 | #define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 |
| 1574 | #define MII_TG3_EXT_CTRL_FORCE_LED_OFF 0x0008 | ||
| 1568 | #define MII_TG3_EXT_CTRL_TBI 0x8000 | 1575 | #define MII_TG3_EXT_CTRL_TBI 0x8000 |
| 1569 | 1576 | ||
| 1570 | #define MII_TG3_EXT_STAT 0x11 /* Extended status register */ | 1577 | #define MII_TG3_EXT_STAT 0x11 /* Extended status register */ |
