Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / b43legacy / main.c
index 82953dd..5f533b9 100644 (file)
@@ -846,10 +846,10 @@ static void handle_irq_noise(struct b43legacy_wldev *dev)
        /* Get the noise samples. */
        B43legacy_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]];
@@ -1516,6 +1516,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
        }
        if (!fw->initvals) {
                switch (dev->phy.type) {
+               case B43legacy_PHYTYPE_B:
                case B43legacy_PHYTYPE_G:
                        if ((rev >= 5) && (rev <= 10))
                                filename = "b0g0initvals5";
@@ -1533,6 +1534,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
        }
        if (!fw->initvals_band) {
                switch (dev->phy.type) {
+               case B43legacy_PHYTYPE_B:
                case B43legacy_PHYTYPE_G:
                        if ((rev >= 5) && (rev <= 10))
                                filename = "b0g0bsinitvals5";
@@ -1718,7 +1720,7 @@ static int b43legacy_write_initvals(struct b43legacy_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);
                        b43legacy_write32(dev, offset, value);
 
                        iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
@@ -2356,8 +2358,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
 }
 
 static int b43legacy_op_tx(struct ieee80211_hw *hw,
-                          struct sk_buff *skb,
-                          struct ieee80211_tx_control *ctl)
+                          struct sk_buff *skb)
 {
        struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
        struct b43legacy_wldev *dev = wl->current_dev;
@@ -2371,18 +2372,17 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw,
        /* 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, ctl);
+               err = b43legacy_pio_tx(dev, skb);
                spin_unlock_irqrestore(&wl->irq_lock, flags);
        } else
-               err = b43legacy_dma_tx(dev, skb, ctl);
+               err = b43legacy_dma_tx(dev, skb);
 out:
        if (unlikely(err))
                return NETDEV_TX_BUSY;
        return NETDEV_TX_OK;
 }
 
-static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
-                               int queue,
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
                                const struct ieee80211_tx_queue_params *params)
 {
        return 0;
@@ -2793,7 +2793,6 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
        /* Start data flow (TX/RX) */
        b43legacy_mac_enable(dev);
        b43legacy_interrupt_enable(dev, dev->irq_savedstate);
-       ieee80211_start_queues(dev->wl->hw);
 
        /* Start maintenance work */
        b43legacy_periodic_tasks_setup(dev);
@@ -3005,11 +3004,38 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
        b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
 }
 
+static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
+                                         bool idle) {
+       u16 pu_delay = 1050;
+
+       if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
+               pu_delay = 500;
+       if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
+               pu_delay = max(pu_delay, (u16)2400);
+
+       b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+                             B43legacy_SHM_SH_SPUWKUP, pu_delay);
+}
+
+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
+static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
+{
+       u16 pretbtt;
+
+       /* The time value is in microseconds. */
+       if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+               pretbtt = 2;
+       else
+               pretbtt = 250;
+       b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+                             B43legacy_SHM_SH_PRETBTT, pretbtt);
+       b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
+}
+
 /* Shutdown a wireless core */
 /* Locking: wl->mutex */
 static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
 {
-       struct b43legacy_wl *wl = dev->wl;
        struct b43legacy_phy *phy = &dev->phy;
        u32 macctl;
 
@@ -3024,12 +3050,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
        macctl |= B43legacy_MACCTL_PSM_JMP0;
        b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
-       mutex_unlock(&wl->mutex);
-       /* Must unlock as it would otherwise deadlock. No races here.
-        * Cancel possibly pending workqueues. */
-       cancel_work_sync(&dev->restart_work);
-       mutex_lock(&wl->mutex);
-
        b43legacy_leds_exit(dev);
        b43legacy_rng_exit(dev->wl);
        b43legacy_pio_free(dev);
@@ -3191,9 +3211,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
        if (err)
                goto err_chip_exit;
 
-       b43legacy_write16(dev, 0x0612, 0x0050);
-       b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050);
-       b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
+       b43legacy_set_synth_pu_delay(dev, 1);
 
        ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
        b43legacy_upload_card_macaddress(dev);
@@ -3249,6 +3267,8 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
 
        spin_lock_irqsave(&wl->irq_lock, flags);
        b43legacy_adjust_opmode(dev);
+       b43legacy_set_pretbtt(dev);
+       b43legacy_set_synth_pu_delay(dev, 0);
        b43legacy_upload_card_macaddress(dev);
        spin_unlock_irqrestore(&wl->irq_lock, flags);
 
@@ -3381,7 +3401,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
         * field, but that would probably require resizing and moving of data
         * within the beacon template. Simply request a new beacon and let
         * mac80211 do the hard work. */
-       beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
+       beacon = ieee80211_beacon_get(hw, wl->vif);
        if (unlikely(!beacon))
                return -ENOMEM;
        spin_lock_irqsave(&wl->irq_lock, flags);
@@ -3392,8 +3412,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
 }
 
 static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
-                                          struct sk_buff *beacon,
-                                          struct ieee80211_tx_control *ctl)
+                                          struct sk_buff *beacon)
 {
        struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
        unsigned long flags;
@@ -3456,6 +3475,8 @@ static void b43legacy_chip_reset(struct work_struct *work)
                }
        }
 out:
+       if (err)
+               wl->current_dev = NULL; /* Failed to init the dev. */
        mutex_unlock(&wl->mutex);
        if (err)
                b43legacyerr(wl, "Controller restart FAILED\n");
@@ -3588,9 +3609,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev)
        struct b43legacy_wldev *wldev;
        struct b43legacy_wl *wl;
 
+       /* Do not cancel ieee80211-workqueue based work here.
+        * See comment in b43legacy_remove(). */
+
        wldev = ssb_get_drvdata(dev);
        wl = wldev->wl;
-       cancel_work_sync(&wldev->restart_work);
        b43legacy_debugfs_remove_device(wldev);
        b43legacy_wireless_core_detach(wldev);
        list_del(&wldev->list);
@@ -3689,10 +3712,9 @@ static int b43legacy_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 = 1; /* FIXME: hardware has more queues */
        SET_IEEE80211_DEV(hw, dev->dev);
        if (is_valid_ether_addr(sprom->et1mac))
@@ -3759,6 +3781,10 @@ static void b43legacy_remove(struct ssb_device *dev)
        struct b43legacy_wl *wl = ssb_get_devtypedata(dev);
        struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
 
+       /* We must cancel any work here before unregistering from ieee80211,
+        * as the ieee80211 unreg will destroy the workqueue. */
+       cancel_work_sync(&wldev->restart_work);
+
        B43legacy_WARN_ON(!wl);
        if (wl->current_dev == wldev)
                ieee80211_unregister_hw(wl->hw);
@@ -3870,7 +3896,7 @@ static void b43legacy_print_driverinfo(void)
 #ifdef CONFIG_B43LEGACY_DMA
        feat_dma = "D";
 #endif
-       printk(KERN_INFO "Broadcom 43xx driver loaded "
+       printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
               "[ Features: %s%s%s%s%s, Firmware-ID: "
               B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
               feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);