diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
| -rw-r--r-- | drivers/net/wireless/b43/main.c | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8fdba9415c04..6c3d9ea0a9f8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -1544,6 +1544,30 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, | |||
| 1544 | kfree(probe_resp_data); | 1544 | kfree(probe_resp_data); |
| 1545 | } | 1545 | } |
| 1546 | 1546 | ||
| 1547 | static void b43_upload_beacon0(struct b43_wldev *dev) | ||
| 1548 | { | ||
| 1549 | struct b43_wl *wl = dev->wl; | ||
| 1550 | |||
| 1551 | if (wl->beacon0_uploaded) | ||
| 1552 | return; | ||
| 1553 | b43_write_beacon_template(dev, 0x68, 0x18); | ||
| 1554 | /* FIXME: Probe resp upload doesn't really belong here, | ||
| 1555 | * but we don't use that feature anyway. */ | ||
| 1556 | b43_write_probe_resp_template(dev, 0x268, 0x4A, | ||
| 1557 | &__b43_ratetable[3]); | ||
| 1558 | wl->beacon0_uploaded = 1; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | static void b43_upload_beacon1(struct b43_wldev *dev) | ||
| 1562 | { | ||
| 1563 | struct b43_wl *wl = dev->wl; | ||
| 1564 | |||
| 1565 | if (wl->beacon1_uploaded) | ||
| 1566 | return; | ||
| 1567 | b43_write_beacon_template(dev, 0x468, 0x1A); | ||
| 1568 | wl->beacon1_uploaded = 1; | ||
| 1569 | } | ||
| 1570 | |||
| 1547 | static void handle_irq_beacon(struct b43_wldev *dev) | 1571 | static void handle_irq_beacon(struct b43_wldev *dev) |
| 1548 | { | 1572 | { |
| 1549 | struct b43_wl *wl = dev->wl; | 1573 | struct b43_wl *wl = dev->wl; |
| @@ -1568,24 +1592,27 @@ static void handle_irq_beacon(struct b43_wldev *dev) | |||
| 1568 | return; | 1592 | return; |
| 1569 | } | 1593 | } |
| 1570 | 1594 | ||
| 1571 | if (!beacon0_valid) { | 1595 | if (unlikely(wl->beacon_templates_virgin)) { |
| 1572 | if (!wl->beacon0_uploaded) { | 1596 | /* We never uploaded a beacon before. |
| 1573 | b43_write_beacon_template(dev, 0x68, 0x18); | 1597 | * Upload both templates now, but only mark one valid. */ |
| 1574 | b43_write_probe_resp_template(dev, 0x268, 0x4A, | 1598 | wl->beacon_templates_virgin = 0; |
| 1575 | &__b43_ratetable[3]); | 1599 | b43_upload_beacon0(dev); |
| 1576 | wl->beacon0_uploaded = 1; | 1600 | b43_upload_beacon1(dev); |
| 1577 | } | ||
| 1578 | cmd = b43_read32(dev, B43_MMIO_MACCMD); | 1601 | cmd = b43_read32(dev, B43_MMIO_MACCMD); |
| 1579 | cmd |= B43_MACCMD_BEACON0_VALID; | 1602 | cmd |= B43_MACCMD_BEACON0_VALID; |
| 1580 | b43_write32(dev, B43_MMIO_MACCMD, cmd); | 1603 | b43_write32(dev, B43_MMIO_MACCMD, cmd); |
| 1581 | } else if (!beacon1_valid) { | 1604 | } else { |
| 1582 | if (!wl->beacon1_uploaded) { | 1605 | if (!beacon0_valid) { |
| 1583 | b43_write_beacon_template(dev, 0x468, 0x1A); | 1606 | b43_upload_beacon0(dev); |
| 1584 | wl->beacon1_uploaded = 1; | 1607 | cmd = b43_read32(dev, B43_MMIO_MACCMD); |
| 1608 | cmd |= B43_MACCMD_BEACON0_VALID; | ||
| 1609 | b43_write32(dev, B43_MMIO_MACCMD, cmd); | ||
| 1610 | } else if (!beacon1_valid) { | ||
| 1611 | b43_upload_beacon1(dev); | ||
| 1612 | cmd = b43_read32(dev, B43_MMIO_MACCMD); | ||
| 1613 | cmd |= B43_MACCMD_BEACON1_VALID; | ||
| 1614 | b43_write32(dev, B43_MMIO_MACCMD, cmd); | ||
| 1585 | } | 1615 | } |
| 1586 | cmd = b43_read32(dev, B43_MMIO_MACCMD); | ||
| 1587 | cmd |= B43_MACCMD_BEACON1_VALID; | ||
| 1588 | b43_write32(dev, B43_MMIO_MACCMD, cmd); | ||
| 1589 | } | 1616 | } |
| 1590 | } | 1617 | } |
| 1591 | 1618 | ||
| @@ -4073,6 +4100,9 @@ static int b43_op_start(struct ieee80211_hw *hw) | |||
| 4073 | wl->filter_flags = 0; | 4100 | wl->filter_flags = 0; |
| 4074 | wl->radiotap_enabled = 0; | 4101 | wl->radiotap_enabled = 0; |
| 4075 | b43_qos_clear(wl); | 4102 | b43_qos_clear(wl); |
| 4103 | wl->beacon0_uploaded = 0; | ||
| 4104 | wl->beacon1_uploaded = 0; | ||
| 4105 | wl->beacon_templates_virgin = 1; | ||
| 4076 | 4106 | ||
| 4077 | /* First register RFkill. | 4107 | /* First register RFkill. |
| 4078 | * LEDs that are registered later depend on it. */ | 4108 | * LEDs that are registered later depend on it. */ |
| @@ -4241,7 +4271,9 @@ static void b43_chip_reset(struct work_struct *work) | |||
| 4241 | goto out; | 4271 | goto out; |
| 4242 | } | 4272 | } |
| 4243 | } | 4273 | } |
| 4244 | out: | 4274 | out: |
| 4275 | if (err) | ||
| 4276 | wl->current_dev = NULL; /* Failed to init the dev. */ | ||
| 4245 | mutex_unlock(&wl->mutex); | 4277 | mutex_unlock(&wl->mutex); |
| 4246 | if (err) | 4278 | if (err) |
| 4247 | b43err(wl, "Controller restart FAILED\n"); | 4279 | b43err(wl, "Controller restart FAILED\n"); |
| @@ -4382,9 +4414,11 @@ static void b43_one_core_detach(struct ssb_device *dev) | |||
| 4382 | struct b43_wldev *wldev; | 4414 | struct b43_wldev *wldev; |
| 4383 | struct b43_wl *wl; | 4415 | struct b43_wl *wl; |
| 4384 | 4416 | ||
| 4417 | /* Do not cancel ieee80211-workqueue based work here. | ||
| 4418 | * See comment in b43_remove(). */ | ||
| 4419 | |||
| 4385 | wldev = ssb_get_drvdata(dev); | 4420 | wldev = ssb_get_drvdata(dev); |
| 4386 | wl = wldev->wl; | 4421 | wl = wldev->wl; |
| 4387 | cancel_work_sync(&wldev->restart_work); | ||
| 4388 | b43_debugfs_remove_device(wldev); | 4422 | b43_debugfs_remove_device(wldev); |
| 4389 | b43_wireless_core_detach(wldev); | 4423 | b43_wireless_core_detach(wldev); |
| 4390 | list_del(&wldev->list); | 4424 | list_del(&wldev->list); |
| @@ -4569,6 +4603,10 @@ static void b43_remove(struct ssb_device *dev) | |||
| 4569 | struct b43_wl *wl = ssb_get_devtypedata(dev); | 4603 | struct b43_wl *wl = ssb_get_devtypedata(dev); |
| 4570 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | 4604 | struct b43_wldev *wldev = ssb_get_drvdata(dev); |
| 4571 | 4605 | ||
| 4606 | /* We must cancel any work here before unregistering from ieee80211, | ||
| 4607 | * as the ieee80211 unreg will destroy the workqueue. */ | ||
| 4608 | cancel_work_sync(&wldev->restart_work); | ||
| 4609 | |||
| 4572 | B43_WARN_ON(!wl); | 4610 | B43_WARN_ON(!wl); |
| 4573 | if (wl->current_dev == wldev) | 4611 | if (wl->current_dev == wldev) |
| 4574 | ieee80211_unregister_hw(wl->hw); | 4612 | ieee80211_unregister_hw(wl->hw); |
