diff options
Diffstat (limited to 'drivers/net/b44.c')
-rw-r--r-- | drivers/net/b44.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 49e91728a1d9..ea2a2b548e3c 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -128,6 +128,8 @@ static void b44_init_rings(struct b44 *); | |||
128 | #define B44_FULL_RESET 1 | 128 | #define B44_FULL_RESET 1 |
129 | #define B44_FULL_RESET_SKIP_PHY 2 | 129 | #define B44_FULL_RESET_SKIP_PHY 2 |
130 | #define B44_PARTIAL_RESET 3 | 130 | #define B44_PARTIAL_RESET 3 |
131 | #define B44_CHIP_RESET_FULL 4 | ||
132 | #define B44_CHIP_RESET_PARTIAL 5 | ||
131 | 133 | ||
132 | static void b44_init_hw(struct b44 *, int); | 134 | static void b44_init_hw(struct b44 *, int); |
133 | 135 | ||
@@ -1259,7 +1261,7 @@ static void b44_clear_stats(struct b44 *bp) | |||
1259 | } | 1261 | } |
1260 | 1262 | ||
1261 | /* bp->lock is held. */ | 1263 | /* bp->lock is held. */ |
1262 | static void b44_chip_reset(struct b44 *bp) | 1264 | static void b44_chip_reset(struct b44 *bp, int reset_kind) |
1263 | { | 1265 | { |
1264 | struct ssb_device *sdev = bp->sdev; | 1266 | struct ssb_device *sdev = bp->sdev; |
1265 | 1267 | ||
@@ -1281,6 +1283,13 @@ static void b44_chip_reset(struct b44 *bp) | |||
1281 | ssb_device_enable(bp->sdev, 0); | 1283 | ssb_device_enable(bp->sdev, 0); |
1282 | b44_clear_stats(bp); | 1284 | b44_clear_stats(bp); |
1283 | 1285 | ||
1286 | /* | ||
1287 | * Don't enable PHY if we are doing a partial reset | ||
1288 | * we are probably going to power down | ||
1289 | */ | ||
1290 | if (reset_kind == B44_CHIP_RESET_PARTIAL) | ||
1291 | return; | ||
1292 | |||
1284 | switch (sdev->bus->bustype) { | 1293 | switch (sdev->bus->bustype) { |
1285 | case SSB_BUSTYPE_SSB: | 1294 | case SSB_BUSTYPE_SSB: |
1286 | bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE | | 1295 | bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE | |
@@ -1316,7 +1325,14 @@ static void b44_chip_reset(struct b44 *bp) | |||
1316 | static void b44_halt(struct b44 *bp) | 1325 | static void b44_halt(struct b44 *bp) |
1317 | { | 1326 | { |
1318 | b44_disable_ints(bp); | 1327 | b44_disable_ints(bp); |
1319 | b44_chip_reset(bp); | 1328 | /* reset PHY */ |
1329 | b44_phy_reset(bp); | ||
1330 | /* power down PHY */ | ||
1331 | printk(KERN_INFO PFX "%s: powering down PHY\n", bp->dev->name); | ||
1332 | bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN); | ||
1333 | /* now reset the chip, but without enabling the MAC&PHY | ||
1334 | * part of it. This has to be done _after_ we shut down the PHY */ | ||
1335 | b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL); | ||
1320 | } | 1336 | } |
1321 | 1337 | ||
1322 | /* bp->lock is held. */ | 1338 | /* bp->lock is held. */ |
@@ -1365,7 +1381,7 @@ static void b44_init_hw(struct b44 *bp, int reset_kind) | |||
1365 | { | 1381 | { |
1366 | u32 val; | 1382 | u32 val; |
1367 | 1383 | ||
1368 | b44_chip_reset(bp); | 1384 | b44_chip_reset(bp, B44_CHIP_RESET_FULL); |
1369 | if (reset_kind == B44_FULL_RESET) { | 1385 | if (reset_kind == B44_FULL_RESET) { |
1370 | b44_phy_reset(bp); | 1386 | b44_phy_reset(bp); |
1371 | b44_setup_phy(bp); | 1387 | b44_setup_phy(bp); |
@@ -1422,7 +1438,7 @@ static int b44_open(struct net_device *dev) | |||
1422 | err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); | 1438 | err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); |
1423 | if (unlikely(err < 0)) { | 1439 | if (unlikely(err < 0)) { |
1424 | napi_disable(&bp->napi); | 1440 | napi_disable(&bp->napi); |
1425 | b44_chip_reset(bp); | 1441 | b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL); |
1426 | b44_free_rings(bp); | 1442 | b44_free_rings(bp); |
1427 | b44_free_consistent(bp); | 1443 | b44_free_consistent(bp); |
1428 | goto out; | 1444 | goto out; |
@@ -2188,7 +2204,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev, | |||
2188 | /* Chip reset provides power to the b44 MAC & PCI cores, which | 2204 | /* Chip reset provides power to the b44 MAC & PCI cores, which |
2189 | * is necessary for MAC register access. | 2205 | * is necessary for MAC register access. |
2190 | */ | 2206 | */ |
2191 | b44_chip_reset(bp); | 2207 | b44_chip_reset(bp, B44_CHIP_RESET_FULL); |
2192 | 2208 | ||
2193 | printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n", | 2209 | printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n", |
2194 | dev->name, print_mac(mac, dev->dev_addr)); | 2210 | dev->name, print_mac(mac, dev->dev_addr)); |
@@ -2212,6 +2228,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev) | |||
2212 | unregister_netdev(dev); | 2228 | unregister_netdev(dev); |
2213 | ssb_bus_may_powerdown(sdev->bus); | 2229 | ssb_bus_may_powerdown(sdev->bus); |
2214 | free_netdev(dev); | 2230 | free_netdev(dev); |
2231 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); | ||
2215 | ssb_set_drvdata(sdev, NULL); | 2232 | ssb_set_drvdata(sdev, NULL); |
2216 | } | 2233 | } |
2217 | 2234 | ||
@@ -2240,6 +2257,7 @@ static int b44_suspend(struct ssb_device *sdev, pm_message_t state) | |||
2240 | b44_setup_wol(bp); | 2257 | b44_setup_wol(bp); |
2241 | } | 2258 | } |
2242 | 2259 | ||
2260 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); | ||
2243 | return 0; | 2261 | return 0; |
2244 | } | 2262 | } |
2245 | 2263 | ||