diff options
Diffstat (limited to 'drivers/net/wireless/b43legacy/main.c')
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 150 |
1 files changed, 99 insertions, 51 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 20f02437af8c..75e70bce40f6 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -722,9 +722,9 @@ void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags) macctl &= ~B43legacy_MACCTL_GMODE; if (flags & B43legacy_TMSLOW_GMODE) { macctl |= B43legacy_MACCTL_GMODE; - dev->phy.gmode = 1; + dev->phy.gmode = true; } else - dev->phy.gmode = 0; + dev->phy.gmode = false; macctl |= B43legacy_MACCTL_IHR_ENABLED; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); } @@ -811,7 +811,7 @@ static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev) if (dev->noisecalc.calculation_running) return; dev->noisecalc.channel_at_start = dev->phy.channel; - dev->noisecalc.calculation_running = 1; + dev->noisecalc.calculation_running = true; dev->noisecalc.nr_samples = 0; b43legacy_generate_noise_sample(dev); @@ -873,7 +873,7 @@ static void handle_irq_noise(struct b43legacy_wldev *dev) dev->stats.link_noise = average; drop_calculation: - dev->noisecalc.calculation_running = 0; + dev->noisecalc.calculation_running = false; return; } generate_new: @@ -889,7 +889,7 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev) b43legacy_power_saving_ctl_bits(dev, -1, -1); } if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) - dev->dfq_valid = 1; + dev->dfq_valid = true; } static void handle_irq_atim_end(struct b43legacy_wldev *dev) @@ -898,7 +898,7 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev) b43legacy_write32(dev, B43legacy_MMIO_MACCMD, b43legacy_read32(dev, B43legacy_MMIO_MACCMD) | B43legacy_MACCMD_DFQ_VALID); - dev->dfq_valid = 0; + dev->dfq_valid = false; } } @@ -971,7 +971,7 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, unsigned int i, len, variable_len; const struct ieee80211_mgmt *bcn; const u8 *ie; - bool tim_found = 0; + bool tim_found = false; unsigned int rate; u16 ctl; int antenna; @@ -1019,7 +1019,7 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, /* A valid TIM is at least 4 bytes long. */ if (ie_len < 4) break; - tim_found = 1; + tim_found = true; tim_position = sizeof(struct b43legacy_plcp_hdr6); tim_position += offsetof(struct ieee80211_mgmt, @@ -1172,7 +1172,7 @@ static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev) * but we don't use that feature anyway. */ b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, &__b43legacy_ratetable[3]); - wl->beacon0_uploaded = 1; + wl->beacon0_uploaded = true; } static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev) @@ -1182,7 +1182,7 @@ static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev) if (wl->beacon1_uploaded) return; b43legacy_write_beacon_template(dev, 0x468, 0x1A); - wl->beacon1_uploaded = 1; + wl->beacon1_uploaded = true; } static void handle_irq_beacon(struct b43legacy_wldev *dev) @@ -1212,7 +1212,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) if (unlikely(wl->beacon_templates_virgin)) { /* We never uploaded a beacon before. * Upload both templates now, but only mark one valid. */ - wl->beacon_templates_virgin = 0; + wl->beacon_templates_virgin = false; b43legacy_upload_beacon0(dev); b43legacy_upload_beacon1(dev); cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); @@ -1275,8 +1275,8 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl) if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; + wl->beacon0_uploaded = false; + wl->beacon1_uploaded = false; ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); } @@ -2440,30 +2440,64 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl) return err; } +static void b43legacy_tx_work(struct work_struct *work) +{ + struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, + tx_work); + struct b43legacy_wldev *dev; + struct sk_buff *skb; + int queue_num; + int err = 0; + + mutex_lock(&wl->mutex); + dev = wl->current_dev; + if (unlikely(!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)) { + mutex_unlock(&wl->mutex); + return; + } + + for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { + while (skb_queue_len(&wl->tx_queue[queue_num])) { + skb = skb_dequeue(&wl->tx_queue[queue_num]); + if (b43legacy_using_pio(dev)) + err = b43legacy_pio_tx(dev, skb); + else + err = b43legacy_dma_tx(dev, skb); + if (err == -ENOSPC) { + wl->tx_queue_stopped[queue_num] = 1; + ieee80211_stop_queue(wl->hw, queue_num); + skb_queue_head(&wl->tx_queue[queue_num], skb); + break; + } + if (unlikely(err)) + dev_kfree_skb(skb); /* Drop it */ + err = 0; + } + + if (!err) + wl->tx_queue_stopped[queue_num] = 0; + } + + mutex_unlock(&wl->mutex); +} + static void b43legacy_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - int err = -ENODEV; - unsigned long flags; - if (unlikely(!dev)) - goto out; - if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED)) - goto out; - /* DMA-TX is done without a global lock. */ - if (b43legacy_using_pio(dev)) { - spin_lock_irqsave(&wl->irq_lock, flags); - err = b43legacy_pio_tx(dev, skb); - spin_unlock_irqrestore(&wl->irq_lock, flags); - } else - err = b43legacy_dma_tx(dev, skb); -out: - if (unlikely(err)) { - /* Drop the packet. */ + if (unlikely(skb->len < 2 + 2 + 6)) { + /* Too short, this can't be a valid frame. */ dev_kfree_skb_any(skb); + return; } + B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags); + + skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb); + if (!wl->tx_queue_stopped[skb->queue_mapping]) + ieee80211_queue_work(wl->hw, &wl->tx_work); + else + ieee80211_stop_queue(wl->hw, skb->queue_mapping); } static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, @@ -2510,7 +2544,7 @@ static int find_wldev_for_phymode(struct b43legacy_wl *wl, if (d->phy.possible_phymodes & phymode) { /* Ok, this device supports the PHY-mode. * Set the gmode bit. */ - *gmode = 1; + *gmode = true; *dev = d; return 0; @@ -2546,7 +2580,7 @@ static int b43legacy_switch_phymode(struct b43legacy_wl *wl, struct b43legacy_wldev *uninitialized_var(up_dev); struct b43legacy_wldev *down_dev; int err; - bool gmode = 0; + bool gmode = false; int prev_status; err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode); @@ -2879,6 +2913,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) { struct b43legacy_wl *wl = dev->wl; unsigned long flags; + int queue_num; if (b43legacy_status(dev) < B43legacy_STAT_STARTED) return; @@ -2898,11 +2933,16 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) /* Must unlock as it would otherwise deadlock. No races here. * Cancel the possibly running self-rearming periodic work. */ cancel_delayed_work_sync(&dev->periodic_work); + cancel_work_sync(&wl->tx_work); mutex_lock(&wl->mutex); - ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ + /* Drain all TX queues. */ + for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { + while (skb_queue_len(&wl->tx_queue[queue_num])) + dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num])); + } - b43legacy_mac_suspend(dev); +b43legacy_mac_suspend(dev); free_irq(dev->dev->irq, dev); b43legacydbg(wl, "Wireless interface stopped\n"); } @@ -3044,12 +3084,12 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev, /* Assume the radio is enabled. If it's not enabled, the state will * immediately get fixed on the first periodic work run. */ - dev->radio_hw_enable = 1; + dev->radio_hw_enable = true; phy->savedpctlreg = 0xFFFF; - phy->aci_enable = 0; - phy->aci_wlan_automatic = 0; - phy->aci_hw_rssi = 0; + phy->aci_enable = false; + phy->aci_wlan_automatic = false; + phy->aci_hw_rssi = false; lo = phy->_lo_pairs; if (lo) @@ -3081,7 +3121,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev, static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) { /* Flags */ - dev->dfq_valid = 0; + dev->dfq_valid = false; /* Stats */ memset(&dev->stats, 0, sizeof(dev->stats)); @@ -3187,9 +3227,9 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev) phy->lofcal = 0xFFFF; phy->initval = 0xFFFF; - phy->aci_enable = 0; - phy->aci_wlan_automatic = 0; - phy->aci_hw_rssi = 0; + phy->aci_enable = false; + phy->aci_wlan_automatic = false; + phy->aci_hw_rssi = false; phy->antenna_diversity = 0xFFFF; memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); @@ -3355,7 +3395,7 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, b43legacydbg(wl, "Adding Interface type %d\n", vif->type); dev = wl->current_dev; - wl->operating = 1; + wl->operating = true; wl->vif = vif; wl->if_type = vif->type; memcpy(wl->mac_addr, vif->addr, ETH_ALEN); @@ -3389,7 +3429,7 @@ static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, B43legacy_WARN_ON(wl->vif != vif); wl->vif = NULL; - wl->operating = 0; + wl->operating = false; spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_adjust_opmode(dev); @@ -3413,10 +3453,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) memset(wl->bssid, 0, ETH_ALEN); memset(wl->mac_addr, 0, ETH_ALEN); wl->filter_flags = 0; - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; - wl->beacon_templates_virgin = 1; - wl->radio_enabled = 1; + wl->beacon0_uploaded = false; + wl->beacon1_uploaded = false; + wl->beacon_templates_virgin = true; + wl->radio_enabled = true; mutex_lock(&wl->mutex); @@ -3455,7 +3495,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) b43legacy_wireless_core_stop(dev); b43legacy_wireless_core_exit(dev); - wl->radio_enabled = 0; + wl->radio_enabled = false; mutex_unlock(&wl->mutex); } @@ -3614,7 +3654,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) have_bphy = 1; dev->phy.gmode = (have_gphy || have_bphy); - dev->phy.radio_on = 1; + dev->phy.radio_on = true; tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; b43legacy_wireless_core_reset(dev, tmp); @@ -3705,7 +3745,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, (void (*)(unsigned long))b43legacy_interrupt_tasklet, (unsigned long)wldev); if (modparam_pio) - wldev->__using_pio = 1; + wldev->__using_pio = true; INIT_LIST_HEAD(&wldev->list); err = b43legacy_wireless_core_attach(wldev); @@ -3748,6 +3788,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) struct ieee80211_hw *hw; struct b43legacy_wl *wl; int err = -ENOMEM; + int queue_num; b43legacy_sprom_fixup(dev->bus); @@ -3782,6 +3823,13 @@ static int b43legacy_wireless_init(struct ssb_device *dev) mutex_init(&wl->mutex); INIT_LIST_HEAD(&wl->devlist); INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); + INIT_WORK(&wl->tx_work, b43legacy_tx_work); + + /* Initialize queues and flags. */ + for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { + skb_queue_head_init(&wl->tx_queue[queue_num]); + wl->tx_queue_stopped[queue_num] = 0; + } ssb_set_devtypedata(dev, wl); b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n", |