]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/b43/main.c
mac80211: use hardware flags for signal/noise units
[linux-2.6] / drivers / net / wireless / b43 / main.c
index 94a0cdeb39a8dfb62a7221ae1795f99af5d9488a..fc23ba5309bd08aaa579fec578f0d75e644904da 100644 (file)
@@ -729,6 +729,7 @@ static void b43_synchronize_irq(struct b43_wldev *dev)
  */
 void b43_dummy_transmission(struct b43_wldev *dev)
 {
+       struct b43_wl *wl = dev->wl;
        struct b43_phy *phy = &dev->phy;
        unsigned int i, max_loop;
        u16 value;
@@ -755,6 +756,9 @@ void b43_dummy_transmission(struct b43_wldev *dev)
                return;
        }
 
+       spin_lock_irq(&wl->irq_lock);
+       write_lock(&wl->tx_lock);
+
        for (i = 0; i < 5; i++)
                b43_ram_write(dev, i * 4, buffer[i]);
 
@@ -795,6 +799,9 @@ void b43_dummy_transmission(struct b43_wldev *dev)
        }
        if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
                b43_radio_write16(dev, 0x0051, 0x0037);
+
+       write_unlock(&wl->tx_lock);
+       spin_unlock_irq(&wl->irq_lock);
 }
 
 static void key_write(struct b43_wldev *dev,
@@ -1175,10 +1182,10 @@ static void handle_irq_noise(struct b43_wldev *dev)
        /* Get the noise samples. */
        B43_WARN_ON(dev->noisecalc.nr_samples >= 8);
        i = dev->noisecalc.nr_samples;
-       noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
-       noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
-       noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
-       noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+       noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+       noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+       noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+       noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
        dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
        dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
        dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
@@ -2171,7 +2178,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
                                goto err_format;
                        array_size -= sizeof(iv->data.d32);
 
-                       value = be32_to_cpu(get_unaligned(&iv->data.d32));
+                       value = get_unaligned_be32(&iv->data.d32);
                        b43_write32(dev, offset, value);
 
                        iv = (const struct b43_iv *)((const uint8_t *)iv +
@@ -2301,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
 }
 
 /* http://bcm-specs.sipsolutions.net/EnableMac */
-static void b43_mac_enable(struct b43_wldev *dev)
+void b43_mac_enable(struct b43_wldev *dev)
 {
        dev->mac_suspended--;
        B43_WARN_ON(dev->mac_suspended < 0);
@@ -2315,16 +2322,11 @@ static void b43_mac_enable(struct b43_wldev *dev)
                b43_read32(dev, B43_MMIO_MACCTL);
                b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
                b43_power_saving_ctl_bits(dev, 0);
-
-               /* Re-enable IRQs. */
-               spin_lock_irq(&dev->wl->irq_lock);
-               b43_interrupt_enable(dev, dev->irq_savedstate);
-               spin_unlock_irq(&dev->wl->irq_lock);
        }
 }
 
 /* http://bcm-specs.sipsolutions.net/SuspendMAC */
-static void b43_mac_suspend(struct b43_wldev *dev)
+void b43_mac_suspend(struct b43_wldev *dev)
 {
        int i;
        u32 tmp;
@@ -2333,14 +2335,6 @@ static void b43_mac_suspend(struct b43_wldev *dev)
        B43_WARN_ON(dev->mac_suspended < 0);
 
        if (dev->mac_suspended == 0) {
-               /* Mask IRQs before suspending MAC. Otherwise
-                * the MAC stays busy and won't suspend. */
-               spin_lock_irq(&dev->wl->irq_lock);
-               tmp = b43_interrupt_disable(dev, B43_IRQ_ALL);
-               spin_unlock_irq(&dev->wl->irq_lock);
-               b43_synchronize_irq(dev);
-               dev->irq_savedstate = tmp;
-
                b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
                b43_write32(dev, B43_MMIO_MACCTL,
                            b43_read32(dev, B43_MMIO_MACCTL)
@@ -2496,6 +2490,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
 {
        b43_radio_turn_off(dev, 1);
        b43_gpio_cleanup(dev);
+       b43_lo_g_cleanup(dev);
        /* firmware is released later */
 }
 
@@ -2602,28 +2597,12 @@ err_gpio_clean:
        return err;
 }
 
-static void b43_periodic_every120sec(struct b43_wldev *dev)
-{
-       struct b43_phy *phy = &dev->phy;
-
-       if (phy->type != B43_PHYTYPE_G || phy->rev < 2)
-               return;
-
-       b43_mac_suspend(dev);
-       b43_lo_g_measure(dev);
-       b43_mac_enable(dev);
-       if (b43_has_hardware_pctl(phy))
-               b43_lo_g_ctl_mark_all_unused(dev);
-}
-
 static void b43_periodic_every60sec(struct b43_wldev *dev)
 {
        struct b43_phy *phy = &dev->phy;
 
        if (phy->type != B43_PHYTYPE_G)
                return;
-       if (!b43_has_hardware_pctl(phy))
-               b43_lo_g_ctl_mark_all_unused(dev);
        if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
                b43_mac_suspend(dev);
                b43_calc_nrssi_slope(dev);
@@ -2675,6 +2654,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
                }
        }
        b43_phy_xmitpower(dev); //FIXME: unless scanning?
+       b43_lo_g_maintanance_work(dev);
        //TODO for APHY (temperature?)
 
        atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
@@ -2686,8 +2666,6 @@ static void do_periodic_work(struct b43_wldev *dev)
        unsigned int state;
 
        state = dev->periodic_state;
-       if (state % 8 == 0)
-               b43_periodic_every120sec(dev);
        if (state % 4 == 0)
                b43_periodic_every60sec(dev);
        if (state % 2 == 0)
@@ -2808,10 +2786,10 @@ static int b43_rng_read(struct hwrng *rng, u32 * data)
        return (sizeof(u16));
 }
 
-static void b43_rng_exit(struct b43_wl *wl, bool suspended)
+static void b43_rng_exit(struct b43_wl *wl)
 {
        if (wl->rng_initialized)
-               __hwrng_unregister(&wl->rng, suspended);
+               hwrng_unregister(&wl->rng);
 }
 
 static int b43_rng_init(struct b43_wl *wl)
@@ -2840,24 +2818,31 @@ static int b43_op_tx(struct ieee80211_hw *hw,
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
-       int err = -ENODEV;
+       unsigned long flags;
+       int err;
 
        if (unlikely(skb->len < 2 + 2 + 6)) {
                /* Too short, this can't be a valid frame. */
-               return -EINVAL;
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
        }
        B43_WARN_ON(skb_shinfo(skb)->nr_frags);
-
        if (unlikely(!dev))
-               goto out;
-       if (unlikely(b43_status(dev) < B43_STAT_STARTED))
-               goto out;
-       /* TX is done without a global lock. */
-       if (b43_using_pio_transfers(dev))
-               err = b43_pio_tx(dev, skb, ctl);
-       else
-               err = b43_dma_tx(dev, skb, ctl);
-out:
+               return NETDEV_TX_BUSY;
+
+       /* Transmissions on seperate queues can run concurrently. */
+       read_lock_irqsave(&wl->tx_lock, flags);
+
+       err = -ENODEV;
+       if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
+               if (b43_using_pio_transfers(dev))
+                       err = b43_pio_tx(dev, skb, ctl);
+               else
+                       err = b43_dma_tx(dev, skb, ctl);
+       }
+
+       read_unlock_irqrestore(&wl->tx_lock, flags);
+
        if (unlikely(err))
                return NETDEV_TX_BUSY;
        return NETDEV_TX_OK;
@@ -3011,8 +2996,7 @@ static void b43_qos_update_work(struct work_struct *work)
        mutex_unlock(&wl->mutex);
 }
 
-static int b43_op_conf_tx(struct ieee80211_hw *hw,
-                         int _queue,
+static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
                          const struct ieee80211_tx_queue_params *params)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3476,7 +3460,9 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
        spin_unlock_irqrestore(&wl->irq_lock, flags);
        b43_synchronize_irq(dev);
 
+       write_lock_irqsave(&wl->tx_lock, flags);
        b43_set_status(dev, B43_STAT_INITIALIZED);
+       write_unlock_irqrestore(&wl->tx_lock, flags);
 
        b43_pio_stop(dev);
        mutex_unlock(&wl->mutex);
@@ -3485,8 +3471,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
        cancel_delayed_work_sync(&dev->periodic_work);
        mutex_lock(&wl->mutex);
 
-       ieee80211_stop_queues(wl->hw);  //FIXME this could cause a deadlock, as mac80211 seems buggy.
-
        b43_mac_suspend(dev);
        free_irq(dev->dev->irq, dev);
        b43dbg(wl, "Wireless interface stopped\n");
@@ -3654,8 +3638,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
        lo = phy->lo_control;
        if (lo) {
                memset(lo, 0, sizeof(*(phy->lo_control)));
-               lo->rebuild = 1;
                lo->tx_bias = 0xFF;
+               INIT_LIST_HEAD(&lo->calib_list);
        }
        phy->max_lb_gain = 0;
        phy->trsw_rx_gain = 0;
@@ -3832,7 +3816,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
 
        if (!dev->suspend_in_progress) {
                b43_leds_exit(dev);
-               b43_rng_exit(dev->wl, false);
+               b43_rng_exit(dev->wl);
        }
        b43_dma_free(dev);
        b43_pio_free(dev);
@@ -4326,6 +4310,14 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
                err = -EOPNOTSUPP;
                goto err_powerdown;
        }
+       if (1 /* disable A-PHY */) {
+               /* FIXME: For now we disable the A-PHY on multi-PHY devices. */
+               if (dev->phy.type != B43_PHYTYPE_N) {
+                       have_2ghz_phy = 1;
+                       have_5ghz_phy = 0;
+               }
+       }
+
        dev->phy.gmode = have_2ghz_phy;
        tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
        b43_wireless_core_reset(dev, tmp);
@@ -4474,10 +4466,10 @@ static int b43_wireless_init(struct ssb_device *dev)
 
        /* fill hw info */
        hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-                   IEEE80211_HW_RX_INCLUDES_FCS;
-       hw->max_signal = 100;
-       hw->max_rssi = -110;
-       hw->max_noise = -110;
+                   IEEE80211_HW_RX_INCLUDES_FCS |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
+
        hw->queues = b43_modparam_qos ? 4 : 1;
        SET_IEEE80211_DEV(hw, dev->dev);
        if (is_valid_ether_addr(sprom->et1mac))
@@ -4490,6 +4482,7 @@ static int b43_wireless_init(struct ssb_device *dev)
        memset(wl, 0, sizeof(*wl));
        wl->hw = hw;
        spin_lock_init(&wl->irq_lock);
+       rwlock_init(&wl->tx_lock);
        spin_lock_init(&wl->leds_lock);
        spin_lock_init(&wl->shm_lock);
        mutex_init(&wl->mutex);
@@ -4613,7 +4606,7 @@ static int b43_resume(struct ssb_device *dev)
                err = b43_wireless_core_start(wldev);
                if (err) {
                        b43_leds_exit(wldev);
-                       b43_rng_exit(wldev->wl, true);
+                       b43_rng_exit(wldev->wl);
                        b43_wireless_core_exit(wldev);
                        b43err(wl, "Resume failed at core start\n");
                        goto out;