aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c143
1 files changed, 106 insertions, 37 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 8c24cd72aaca..a70827793086 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -729,6 +729,7 @@ static void b43_synchronize_irq(struct b43_wldev *dev)
729 */ 729 */
730void b43_dummy_transmission(struct b43_wldev *dev) 730void b43_dummy_transmission(struct b43_wldev *dev)
731{ 731{
732 struct b43_wl *wl = dev->wl;
732 struct b43_phy *phy = &dev->phy; 733 struct b43_phy *phy = &dev->phy;
733 unsigned int i, max_loop; 734 unsigned int i, max_loop;
734 u16 value; 735 u16 value;
@@ -755,6 +756,9 @@ void b43_dummy_transmission(struct b43_wldev *dev)
755 return; 756 return;
756 } 757 }
757 758
759 spin_lock_irq(&wl->irq_lock);
760 write_lock(&wl->tx_lock);
761
758 for (i = 0; i < 5; i++) 762 for (i = 0; i < 5; i++)
759 b43_ram_write(dev, i * 4, buffer[i]); 763 b43_ram_write(dev, i * 4, buffer[i]);
760 764
@@ -795,6 +799,9 @@ void b43_dummy_transmission(struct b43_wldev *dev)
795 } 799 }
796 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) 800 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
797 b43_radio_write16(dev, 0x0051, 0x0037); 801 b43_radio_write16(dev, 0x0051, 0x0037);
802
803 write_unlock(&wl->tx_lock);
804 spin_unlock_irq(&wl->irq_lock);
798} 805}
799 806
800static void key_write(struct b43_wldev *dev, 807static void key_write(struct b43_wldev *dev,
@@ -1138,7 +1145,6 @@ static void b43_generate_noise_sample(struct b43_wldev *dev)
1138 b43_jssi_write(dev, 0x7F7F7F7F); 1145 b43_jssi_write(dev, 0x7F7F7F7F);
1139 b43_write32(dev, B43_MMIO_MACCMD, 1146 b43_write32(dev, B43_MMIO_MACCMD,
1140 b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE); 1147 b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE);
1141 B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);
1142} 1148}
1143 1149
1144static void b43_calculate_link_quality(struct b43_wldev *dev) 1150static void b43_calculate_link_quality(struct b43_wldev *dev)
@@ -1147,7 +1153,6 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
1147 1153
1148 if (dev->noisecalc.calculation_running) 1154 if (dev->noisecalc.calculation_running)
1149 return; 1155 return;
1150 dev->noisecalc.channel_at_start = dev->phy.channel;
1151 dev->noisecalc.calculation_running = 1; 1156 dev->noisecalc.calculation_running = 1;
1152 dev->noisecalc.nr_samples = 0; 1157 dev->noisecalc.nr_samples = 0;
1153 1158
@@ -1164,9 +1169,16 @@ static void handle_irq_noise(struct b43_wldev *dev)
1164 1169
1165 /* Bottom half of Link Quality calculation. */ 1170 /* Bottom half of Link Quality calculation. */
1166 1171
1172 /* Possible race condition: It might be possible that the user
1173 * changed to a different channel in the meantime since we
1174 * started the calculation. We ignore that fact, since it's
1175 * not really that much of a problem. The background noise is
1176 * an estimation only anyway. Slightly wrong results will get damped
1177 * by the averaging of the 8 sample rounds. Additionally the
1178 * value is shortlived. So it will be replaced by the next noise
1179 * calculation round soon. */
1180
1167 B43_WARN_ON(!dev->noisecalc.calculation_running); 1181 B43_WARN_ON(!dev->noisecalc.calculation_running);
1168 if (dev->noisecalc.channel_at_start != phy->channel)
1169 goto drop_calculation;
1170 *((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev)); 1182 *((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev));
1171 if (noise[0] == 0x7F || noise[1] == 0x7F || 1183 if (noise[0] == 0x7F || noise[1] == 0x7F ||
1172 noise[2] == 0x7F || noise[3] == 0x7F) 1184 noise[2] == 0x7F || noise[3] == 0x7F)
@@ -1207,11 +1219,10 @@ static void handle_irq_noise(struct b43_wldev *dev)
1207 average -= 48; 1219 average -= 48;
1208 1220
1209 dev->stats.link_noise = average; 1221 dev->stats.link_noise = average;
1210 drop_calculation:
1211 dev->noisecalc.calculation_running = 0; 1222 dev->noisecalc.calculation_running = 0;
1212 return; 1223 return;
1213 } 1224 }
1214 generate_new: 1225generate_new:
1215 b43_generate_noise_sample(dev); 1226 b43_generate_noise_sample(dev);
1216} 1227}
1217 1228
@@ -1537,6 +1548,30 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
1537 kfree(probe_resp_data); 1548 kfree(probe_resp_data);
1538} 1549}
1539 1550
1551static void b43_upload_beacon0(struct b43_wldev *dev)
1552{
1553 struct b43_wl *wl = dev->wl;
1554
1555 if (wl->beacon0_uploaded)
1556 return;
1557 b43_write_beacon_template(dev, 0x68, 0x18);
1558 /* FIXME: Probe resp upload doesn't really belong here,
1559 * but we don't use that feature anyway. */
1560 b43_write_probe_resp_template(dev, 0x268, 0x4A,
1561 &__b43_ratetable[3]);
1562 wl->beacon0_uploaded = 1;
1563}
1564
1565static void b43_upload_beacon1(struct b43_wldev *dev)
1566{
1567 struct b43_wl *wl = dev->wl;
1568
1569 if (wl->beacon1_uploaded)
1570 return;
1571 b43_write_beacon_template(dev, 0x468, 0x1A);
1572 wl->beacon1_uploaded = 1;
1573}
1574
1540static void handle_irq_beacon(struct b43_wldev *dev) 1575static void handle_irq_beacon(struct b43_wldev *dev)
1541{ 1576{
1542 struct b43_wl *wl = dev->wl; 1577 struct b43_wl *wl = dev->wl;
@@ -1561,24 +1596,27 @@ static void handle_irq_beacon(struct b43_wldev *dev)
1561 return; 1596 return;
1562 } 1597 }
1563 1598
1564 if (!beacon0_valid) { 1599 if (unlikely(wl->beacon_templates_virgin)) {
1565 if (!wl->beacon0_uploaded) { 1600 /* We never uploaded a beacon before.
1566 b43_write_beacon_template(dev, 0x68, 0x18); 1601 * Upload both templates now, but only mark one valid. */
1567 b43_write_probe_resp_template(dev, 0x268, 0x4A, 1602 wl->beacon_templates_virgin = 0;
1568 &__b43_ratetable[3]); 1603 b43_upload_beacon0(dev);
1569 wl->beacon0_uploaded = 1; 1604 b43_upload_beacon1(dev);
1570 }
1571 cmd = b43_read32(dev, B43_MMIO_MACCMD); 1605 cmd = b43_read32(dev, B43_MMIO_MACCMD);
1572 cmd |= B43_MACCMD_BEACON0_VALID; 1606 cmd |= B43_MACCMD_BEACON0_VALID;
1573 b43_write32(dev, B43_MMIO_MACCMD, cmd); 1607 b43_write32(dev, B43_MMIO_MACCMD, cmd);
1574 } else if (!beacon1_valid) { 1608 } else {
1575 if (!wl->beacon1_uploaded) { 1609 if (!beacon0_valid) {
1576 b43_write_beacon_template(dev, 0x468, 0x1A); 1610 b43_upload_beacon0(dev);
1577 wl->beacon1_uploaded = 1; 1611 cmd = b43_read32(dev, B43_MMIO_MACCMD);
1612 cmd |= B43_MACCMD_BEACON0_VALID;
1613 b43_write32(dev, B43_MMIO_MACCMD, cmd);
1614 } else if (!beacon1_valid) {
1615 b43_upload_beacon1(dev);
1616 cmd = b43_read32(dev, B43_MMIO_MACCMD);
1617 cmd |= B43_MACCMD_BEACON1_VALID;
1618 b43_write32(dev, B43_MMIO_MACCMD, cmd);
1578 } 1619 }
1579 cmd = b43_read32(dev, B43_MMIO_MACCMD);
1580 cmd |= B43_MACCMD_BEACON1_VALID;
1581 b43_write32(dev, B43_MMIO_MACCMD, cmd);
1582 } 1620 }
1583} 1621}
1584 1622
@@ -2840,26 +2878,37 @@ static int b43_op_tx(struct ieee80211_hw *hw,
2840{ 2878{
2841 struct b43_wl *wl = hw_to_b43_wl(hw); 2879 struct b43_wl *wl = hw_to_b43_wl(hw);
2842 struct b43_wldev *dev = wl->current_dev; 2880 struct b43_wldev *dev = wl->current_dev;
2843 int err = -ENODEV; 2881 unsigned long flags;
2882 int err;
2844 2883
2845 if (unlikely(skb->len < 2 + 2 + 6)) { 2884 if (unlikely(skb->len < 2 + 2 + 6)) {
2846 /* Too short, this can't be a valid frame. */ 2885 /* Too short, this can't be a valid frame. */
2847 return -EINVAL; 2886 goto drop_packet;
2848 } 2887 }
2849 B43_WARN_ON(skb_shinfo(skb)->nr_frags); 2888 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
2850
2851 if (unlikely(!dev)) 2889 if (unlikely(!dev))
2852 goto out; 2890 goto drop_packet;
2853 if (unlikely(b43_status(dev) < B43_STAT_STARTED)) 2891
2854 goto out; 2892 /* Transmissions on seperate queues can run concurrently. */
2855 /* TX is done without a global lock. */ 2893 read_lock_irqsave(&wl->tx_lock, flags);
2856 if (b43_using_pio_transfers(dev)) 2894
2857 err = b43_pio_tx(dev, skb, ctl); 2895 err = -ENODEV;
2858 else 2896 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
2859 err = b43_dma_tx(dev, skb, ctl); 2897 if (b43_using_pio_transfers(dev))
2860out: 2898 err = b43_pio_tx(dev, skb, ctl);
2899 else
2900 err = b43_dma_tx(dev, skb, ctl);
2901 }
2902
2903 read_unlock_irqrestore(&wl->tx_lock, flags);
2904
2861 if (unlikely(err)) 2905 if (unlikely(err))
2862 return NETDEV_TX_BUSY; 2906 goto drop_packet;
2907 return NETDEV_TX_OK;
2908
2909drop_packet:
2910 /* We can not transmit this packet. Drop it. */
2911 dev_kfree_skb_any(skb);
2863 return NETDEV_TX_OK; 2912 return NETDEV_TX_OK;
2864} 2913}
2865 2914
@@ -3476,7 +3525,9 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
3476 spin_unlock_irqrestore(&wl->irq_lock, flags); 3525 spin_unlock_irqrestore(&wl->irq_lock, flags);
3477 b43_synchronize_irq(dev); 3526 b43_synchronize_irq(dev);
3478 3527
3528 write_lock_irqsave(&wl->tx_lock, flags);
3479 b43_set_status(dev, B43_STAT_INITIALIZED); 3529 b43_set_status(dev, B43_STAT_INITIALIZED);
3530 write_unlock_irqrestore(&wl->tx_lock, flags);
3480 3531
3481 b43_pio_stop(dev); 3532 b43_pio_stop(dev);
3482 mutex_unlock(&wl->mutex); 3533 mutex_unlock(&wl->mutex);
@@ -3485,8 +3536,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
3485 cancel_delayed_work_sync(&dev->periodic_work); 3536 cancel_delayed_work_sync(&dev->periodic_work);
3486 mutex_lock(&wl->mutex); 3537 mutex_lock(&wl->mutex);
3487 3538
3488 ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy.
3489
3490 b43_mac_suspend(dev); 3539 b43_mac_suspend(dev);
3491 free_irq(dev->dev->irq, dev); 3540 free_irq(dev->dev->irq, dev);
3492 b43dbg(wl, "Wireless interface stopped\n"); 3541 b43dbg(wl, "Wireless interface stopped\n");
@@ -4059,6 +4108,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
4059 wl->filter_flags = 0; 4108 wl->filter_flags = 0;
4060 wl->radiotap_enabled = 0; 4109 wl->radiotap_enabled = 0;
4061 b43_qos_clear(wl); 4110 b43_qos_clear(wl);
4111 wl->beacon0_uploaded = 0;
4112 wl->beacon1_uploaded = 0;
4113 wl->beacon_templates_virgin = 1;
4062 4114
4063 /* First register RFkill. 4115 /* First register RFkill.
4064 * LEDs that are registered later depend on it. */ 4116 * LEDs that are registered later depend on it. */
@@ -4227,7 +4279,9 @@ static void b43_chip_reset(struct work_struct *work)
4227 goto out; 4279 goto out;
4228 } 4280 }
4229 } 4281 }
4230 out: 4282out:
4283 if (err)
4284 wl->current_dev = NULL; /* Failed to init the dev. */
4231 mutex_unlock(&wl->mutex); 4285 mutex_unlock(&wl->mutex);
4232 if (err) 4286 if (err)
4233 b43err(wl, "Controller restart FAILED\n"); 4287 b43err(wl, "Controller restart FAILED\n");
@@ -4326,6 +4380,14 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
4326 err = -EOPNOTSUPP; 4380 err = -EOPNOTSUPP;
4327 goto err_powerdown; 4381 goto err_powerdown;
4328 } 4382 }
4383 if (1 /* disable A-PHY */) {
4384 /* FIXME: For now we disable the A-PHY on multi-PHY devices. */
4385 if (dev->phy.type != B43_PHYTYPE_N) {
4386 have_2ghz_phy = 1;
4387 have_5ghz_phy = 0;
4388 }
4389 }
4390
4329 dev->phy.gmode = have_2ghz_phy; 4391 dev->phy.gmode = have_2ghz_phy;
4330 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; 4392 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
4331 b43_wireless_core_reset(dev, tmp); 4393 b43_wireless_core_reset(dev, tmp);
@@ -4360,9 +4422,11 @@ static void b43_one_core_detach(struct ssb_device *dev)
4360 struct b43_wldev *wldev; 4422 struct b43_wldev *wldev;
4361 struct b43_wl *wl; 4423 struct b43_wl *wl;
4362 4424
4425 /* Do not cancel ieee80211-workqueue based work here.
4426 * See comment in b43_remove(). */
4427
4363 wldev = ssb_get_drvdata(dev); 4428 wldev = ssb_get_drvdata(dev);
4364 wl = wldev->wl; 4429 wl = wldev->wl;
4365 cancel_work_sync(&wldev->restart_work);
4366 b43_debugfs_remove_device(wldev); 4430 b43_debugfs_remove_device(wldev);
4367 b43_wireless_core_detach(wldev); 4431 b43_wireless_core_detach(wldev);
4368 list_del(&wldev->list); 4432 list_del(&wldev->list);
@@ -4490,6 +4554,7 @@ static int b43_wireless_init(struct ssb_device *dev)
4490 memset(wl, 0, sizeof(*wl)); 4554 memset(wl, 0, sizeof(*wl));
4491 wl->hw = hw; 4555 wl->hw = hw;
4492 spin_lock_init(&wl->irq_lock); 4556 spin_lock_init(&wl->irq_lock);
4557 rwlock_init(&wl->tx_lock);
4493 spin_lock_init(&wl->leds_lock); 4558 spin_lock_init(&wl->leds_lock);
4494 spin_lock_init(&wl->shm_lock); 4559 spin_lock_init(&wl->shm_lock);
4495 mutex_init(&wl->mutex); 4560 mutex_init(&wl->mutex);
@@ -4546,6 +4611,10 @@ static void b43_remove(struct ssb_device *dev)
4546 struct b43_wl *wl = ssb_get_devtypedata(dev); 4611 struct b43_wl *wl = ssb_get_devtypedata(dev);
4547 struct b43_wldev *wldev = ssb_get_drvdata(dev); 4612 struct b43_wldev *wldev = ssb_get_drvdata(dev);
4548 4613
4614 /* We must cancel any work here before unregistering from ieee80211,
4615 * as the ieee80211 unreg will destroy the workqueue. */
4616 cancel_work_sync(&wldev->restart_work);
4617
4549 B43_WARN_ON(!wl); 4618 B43_WARN_ON(!wl);
4550 if (wl->current_dev == wldev) 4619 if (wl->current_dev == wldev)
4551 ieee80211_unregister_hw(wl->hw); 4620 ieee80211_unregister_hw(wl->hw);