diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 47731cb0d815..2c9088633ec6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1262,6 +1262,23 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | |||
1262 | flags |= B43_BCMA_IOCTL_GMODE; | 1262 | flags |= B43_BCMA_IOCTL_GMODE; |
1263 | b43_device_enable(dev, flags); | 1263 | b43_device_enable(dev, flags); |
1264 | 1264 | ||
1265 | if (dev->phy.type == B43_PHYTYPE_AC) { | ||
1266 | u16 tmp; | ||
1267 | |||
1268 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1269 | tmp &= ~B43_BCMA_IOCTL_DAC; | ||
1270 | tmp |= 0x100; | ||
1271 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1272 | |||
1273 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1274 | tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; | ||
1275 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1276 | |||
1277 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1278 | tmp |= B43_BCMA_IOCTL_PHY_CLKEN; | ||
1279 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1280 | } | ||
1281 | |||
1265 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); | 1282 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); |
1266 | b43_bcma_phy_reset(dev); | 1283 | b43_bcma_phy_reset(dev); |
1267 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); | 1284 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); |
@@ -1601,12 +1618,26 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1601 | unsigned int rate; | 1618 | unsigned int rate; |
1602 | u16 ctl; | 1619 | u16 ctl; |
1603 | int antenna; | 1620 | int antenna; |
1604 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); | 1621 | struct ieee80211_tx_info *info; |
1622 | unsigned long flags; | ||
1623 | struct sk_buff *beacon_skb; | ||
1605 | 1624 | ||
1606 | bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); | 1625 | spin_lock_irqsave(&dev->wl->beacon_lock, flags); |
1607 | len = min_t(size_t, dev->wl->current_beacon->len, | 1626 | info = IEEE80211_SKB_CB(dev->wl->current_beacon); |
1608 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
1609 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; | 1627 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; |
1628 | /* Clone the beacon, so it cannot go away, while we write it to hw. */ | ||
1629 | beacon_skb = skb_clone(dev->wl->current_beacon, GFP_ATOMIC); | ||
1630 | spin_unlock_irqrestore(&dev->wl->beacon_lock, flags); | ||
1631 | |||
1632 | if (!beacon_skb) { | ||
1633 | b43dbg(dev->wl, "Could not upload beacon. " | ||
1634 | "Failed to clone beacon skb."); | ||
1635 | return; | ||
1636 | } | ||
1637 | |||
1638 | bcn = (const struct ieee80211_mgmt *)(beacon_skb->data); | ||
1639 | len = min_t(size_t, beacon_skb->len, | ||
1640 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
1610 | 1641 | ||
1611 | b43_write_template_common(dev, (const u8 *)bcn, | 1642 | b43_write_template_common(dev, (const u8 *)bcn, |
1612 | len, ram_offset, shm_size_offset, rate); | 1643 | len, ram_offset, shm_size_offset, rate); |
@@ -1674,6 +1705,8 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1674 | B43_SHM_SH_DTIMPER, 0); | 1705 | B43_SHM_SH_DTIMPER, 0); |
1675 | } | 1706 | } |
1676 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); | 1707 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); |
1708 | |||
1709 | dev_kfree_skb_any(beacon_skb); | ||
1677 | } | 1710 | } |
1678 | 1711 | ||
1679 | static void b43_upload_beacon0(struct b43_wldev *dev) | 1712 | static void b43_upload_beacon0(struct b43_wldev *dev) |
@@ -1790,13 +1823,13 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
1790 | mutex_unlock(&wl->mutex); | 1823 | mutex_unlock(&wl->mutex); |
1791 | } | 1824 | } |
1792 | 1825 | ||
1793 | /* Asynchronously update the packet templates in template RAM. | 1826 | /* Asynchronously update the packet templates in template RAM. */ |
1794 | * Locking: Requires wl->mutex to be locked. */ | ||
1795 | static void b43_update_templates(struct b43_wl *wl) | 1827 | static void b43_update_templates(struct b43_wl *wl) |
1796 | { | 1828 | { |
1797 | struct sk_buff *beacon; | 1829 | struct sk_buff *beacon, *old_beacon; |
1830 | unsigned long flags; | ||
1798 | 1831 | ||
1799 | /* This is the top half of the ansynchronous beacon update. | 1832 | /* This is the top half of the asynchronous beacon update. |
1800 | * The bottom half is the beacon IRQ. | 1833 | * The bottom half is the beacon IRQ. |
1801 | * Beacon update must be asynchronous to avoid sending an | 1834 | * Beacon update must be asynchronous to avoid sending an |
1802 | * invalid beacon. This can happen for example, if the firmware | 1835 | * invalid beacon. This can happen for example, if the firmware |
@@ -1810,12 +1843,17 @@ static void b43_update_templates(struct b43_wl *wl) | |||
1810 | if (unlikely(!beacon)) | 1843 | if (unlikely(!beacon)) |
1811 | return; | 1844 | return; |
1812 | 1845 | ||
1813 | if (wl->current_beacon) | 1846 | spin_lock_irqsave(&wl->beacon_lock, flags); |
1814 | dev_kfree_skb_any(wl->current_beacon); | 1847 | old_beacon = wl->current_beacon; |
1815 | wl->current_beacon = beacon; | 1848 | wl->current_beacon = beacon; |
1816 | wl->beacon0_uploaded = false; | 1849 | wl->beacon0_uploaded = false; |
1817 | wl->beacon1_uploaded = false; | 1850 | wl->beacon1_uploaded = false; |
1851 | spin_unlock_irqrestore(&wl->beacon_lock, flags); | ||
1852 | |||
1818 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); | 1853 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); |
1854 | |||
1855 | if (old_beacon) | ||
1856 | dev_kfree_skb_any(old_beacon); | ||
1819 | } | 1857 | } |
1820 | 1858 | ||
1821 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) | 1859 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) |
@@ -4318,6 +4356,7 @@ redo: | |||
4318 | mutex_unlock(&wl->mutex); | 4356 | mutex_unlock(&wl->mutex); |
4319 | cancel_delayed_work_sync(&dev->periodic_work); | 4357 | cancel_delayed_work_sync(&dev->periodic_work); |
4320 | cancel_work_sync(&wl->tx_work); | 4358 | cancel_work_sync(&wl->tx_work); |
4359 | b43_leds_stop(dev); | ||
4321 | mutex_lock(&wl->mutex); | 4360 | mutex_lock(&wl->mutex); |
4322 | dev = wl->current_dev; | 4361 | dev = wl->current_dev; |
4323 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { | 4362 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { |
@@ -4505,6 +4544,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4505 | unsupported = 1; | 4544 | unsupported = 1; |
4506 | break; | 4545 | break; |
4507 | #endif | 4546 | #endif |
4547 | #ifdef CONFIG_B43_PHY_AC | ||
4548 | case B43_PHYTYPE_AC: | ||
4549 | if (phy_rev > 1) | ||
4550 | unsupported = 1; | ||
4551 | break; | ||
4552 | #endif | ||
4508 | default: | 4553 | default: |
4509 | unsupported = 1; | 4554 | unsupported = 1; |
4510 | } | 4555 | } |
@@ -4601,6 +4646,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4601 | if (radio_id != 0x2064) | 4646 | if (radio_id != 0x2064) |
4602 | unsupported = 1; | 4647 | unsupported = 1; |
4603 | break; | 4648 | break; |
4649 | case B43_PHYTYPE_AC: | ||
4650 | if (radio_id != 0x2069) | ||
4651 | unsupported = 1; | ||
4652 | break; | ||
4604 | default: | 4653 | default: |
4605 | B43_WARN_ON(1); | 4654 | B43_WARN_ON(1); |
4606 | } | 4655 | } |
@@ -5094,7 +5143,6 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, | |||
5094 | { | 5143 | { |
5095 | struct b43_wl *wl = hw_to_b43_wl(hw); | 5144 | struct b43_wl *wl = hw_to_b43_wl(hw); |
5096 | 5145 | ||
5097 | /* FIXME: add locking */ | ||
5098 | b43_update_templates(wl); | 5146 | b43_update_templates(wl); |
5099 | 5147 | ||
5100 | return 0; | 5148 | return 0; |
@@ -5584,6 +5632,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | |||
5584 | wl->hw = hw; | 5632 | wl->hw = hw; |
5585 | mutex_init(&wl->mutex); | 5633 | mutex_init(&wl->mutex); |
5586 | spin_lock_init(&wl->hardirq_lock); | 5634 | spin_lock_init(&wl->hardirq_lock); |
5635 | spin_lock_init(&wl->beacon_lock); | ||
5587 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); | 5636 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); |
5588 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | 5637 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); |
5589 | INIT_WORK(&wl->tx_work, b43_tx_work); | 5638 | INIT_WORK(&wl->tx_work, b43_tx_work); |