]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/b43/main.c
b43: rewrite A PHY initialization
[linux-2.6] / drivers / net / wireless / b43 / main.c
index 2b17c1dc46f1e69e30535a74f6b69ed5053ea9a4..979e82267d0d873d9754d3bd0e2020109a01d8e9 100644 (file)
@@ -75,14 +75,6 @@ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
 MODULE_PARM_DESC(bad_frames_preempt,
                 "enable(1) / disable(0) Bad Frames Preemption");
 
-static int modparam_short_retry = B43_DEFAULT_SHORT_RETRY_LIMIT;
-module_param_named(short_retry, modparam_short_retry, int, 0444);
-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
-
-static int modparam_long_retry = B43_DEFAULT_LONG_RETRY_LIMIT;
-module_param_named(long_retry, modparam_long_retry, int, 0444);
-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-
 static char modparam_fwpostfix[16];
 module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
 MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
@@ -1566,7 +1558,7 @@ static void b43_release_firmware(struct b43_wldev *dev)
 static void b43_print_fw_helptext(struct b43_wl *wl)
 {
        b43err(wl, "You must go to "
-              "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware "
+              "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
               "and download the correct firmware (version 4).\n");
 }
 
@@ -2163,7 +2155,6 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
 static void b43_chip_exit(struct b43_wldev *dev)
 {
        b43_radio_turn_off(dev, 1);
-       b43_leds_exit(dev);
        b43_gpio_cleanup(dev);
        /* firmware is released later */
 }
@@ -2191,11 +2182,10 @@ static int b43_chip_init(struct b43_wldev *dev)
        err = b43_gpio_init(dev);
        if (err)
                goto out;       /* firmware is released later */
-       b43_leds_init(dev);
 
        err = b43_upload_initvals(dev);
        if (err)
-               goto err_leds_exit;
+               goto err_gpio_clean;
        b43_radio_turn_on(dev);
 
        b43_write16(dev, 0x03E6, 0x0000);
@@ -2264,6 +2254,9 @@ static int b43_chip_init(struct b43_wldev *dev)
        b43_write16(dev, B43_MMIO_POWERUP_DELAY,
                    dev->dev->bus->chipco.fast_pwrup_delay);
 
+       /* OFDM address caching. */
+       phy->ofdm_valid = 0;
+
        err = 0;
        b43dbg(dev->wl, "Chip initialized\n");
 out:
@@ -2271,8 +2264,7 @@ out:
 
 err_radio_off:
        b43_radio_turn_off(dev, 1);
-err_leds_exit:
-       b43_leds_exit(dev);
+err_gpio_clean:
        b43_gpio_cleanup(dev);
        return err;
 }
@@ -2494,8 +2486,9 @@ static int b43_rng_init(struct b43_wl *wl)
        return err;
 }
 
-static int b43_tx(struct ieee80211_hw *hw,
-                 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+static int b43_op_tx(struct ieee80211_hw *hw,
+                    struct sk_buff *skb,
+                    struct ieee80211_tx_control *ctl)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
@@ -2513,21 +2506,21 @@ static int b43_tx(struct ieee80211_hw *hw,
                spin_unlock_irqrestore(&wl->irq_lock, flags);
        } else
                err = b43_dma_tx(dev, skb, ctl);
-      out:
+out:
        if (unlikely(err))
                return NETDEV_TX_BUSY;
        return NETDEV_TX_OK;
 }
 
-static int b43_conf_tx(struct ieee80211_hw *hw,
-                      int queue,
-                      const struct ieee80211_tx_queue_params *params)
+static int b43_op_conf_tx(struct ieee80211_hw *hw,
+                         int queue,
+                         const struct ieee80211_tx_queue_params *params)
 {
        return 0;
 }
 
-static int b43_get_tx_stats(struct ieee80211_hw *hw,
-                           struct ieee80211_tx_queue_stats *stats)
+static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
+                              struct ieee80211_tx_queue_stats *stats)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
@@ -2545,12 +2538,12 @@ static int b43_get_tx_stats(struct ieee80211_hw *hw,
                err = 0;
        }
        spin_unlock_irqrestore(&wl->irq_lock, flags);
-      out:
+out:
        return err;
 }
 
-static int b43_get_stats(struct ieee80211_hw *hw,
-                        struct ieee80211_low_level_stats *stats)
+static int b43_op_get_stats(struct ieee80211_hw *hw,
+                           struct ieee80211_low_level_stats *stats)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        unsigned long flags;
@@ -2703,7 +2696,7 @@ static int b43_antenna_from_ieee80211(u8 antenna)
        }
 }
 
-static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
@@ -2808,23 +2801,30 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
        return err;
 }
 
-static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                           const u8 *local_addr, const u8 *addr,
                           struct ieee80211_key_conf *key)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
-       struct b43_wldev *dev = wl->current_dev;
+       struct b43_wldev *dev;
        unsigned long flags;
        u8 algorithm;
        u8 index;
-       int err = -EINVAL;
+       int err;
        DECLARE_MAC_BUF(mac);
 
        if (modparam_nohwcrypt)
                return -ENOSPC; /* User disabled HW-crypto */
 
-       if (!dev)
-               return -ENODEV;
+       mutex_lock(&wl->mutex);
+       spin_lock_irqsave(&wl->irq_lock, flags);
+
+       dev = wl->current_dev;
+       err = -ENODEV;
+       if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
+               goto out_unlock;
+
+       err = -EINVAL;
        switch (key->alg) {
        case ALG_WEP:
                if (key->keylen == 5)
@@ -2840,20 +2840,11 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                break;
        default:
                B43_WARN_ON(1);
-               goto out;
+               goto out_unlock;
        }
-
        index = (u8) (key->keyidx);
        if (index > 3)
-               goto out;
-
-       mutex_lock(&wl->mutex);
-       spin_lock_irqsave(&wl->irq_lock, flags);
-
-       if (b43_status(dev) < B43_STAT_INITIALIZED) {
-               err = -ENODEV;
                goto out_unlock;
-       }
 
        switch (cmd) {
        case SET_KEY:
@@ -2899,7 +2890,6 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 out_unlock:
        spin_unlock_irqrestore(&wl->irq_lock, flags);
        mutex_unlock(&wl->mutex);
-out:
        if (!err) {
                b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
                       "mac: %s\n",
@@ -2909,9 +2899,9 @@ out:
        return err;
 }
 
-static void b43_configure_filter(struct ieee80211_hw *hw,
-                                unsigned int changed, unsigned int *fflags,
-                                int mc_count, struct dev_addr_list *mc_list)
+static void b43_op_configure_filter(struct ieee80211_hw *hw,
+                                   unsigned int changed, unsigned int *fflags,
+                                   int mc_count, struct dev_addr_list *mc_list)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
@@ -2946,8 +2936,9 @@ static void b43_configure_filter(struct ieee80211_hw *hw,
        spin_unlock_irqrestore(&wl->irq_lock, flags);
 }
 
-static int b43_config_interface(struct ieee80211_hw *hw,
-                               int if_id, struct ieee80211_if_conf *conf)
+static int b43_op_config_interface(struct ieee80211_hw *hw,
+                                  int if_id,
+                                  struct ieee80211_if_conf *conf)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
@@ -3262,6 +3253,22 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
 #endif /* CONFIG_SSB_DRIVER_PCICORE */
 }
 
+/* Write the short and long frame retry limit values. */
+static void b43_set_retry_limits(struct b43_wldev *dev,
+                                unsigned int short_retry,
+                                unsigned int long_retry)
+{
+       /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+        * the chip-internal counter. */
+       short_retry = min(short_retry, (unsigned int)0xF);
+       long_retry = min(long_retry, (unsigned int)0xF);
+
+       b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
+                       short_retry);
+       b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
+                       long_retry);
+}
+
 /* Shutdown a wireless core */
 /* Locking: wl->mutex */
 static void b43_wireless_core_exit(struct b43_wldev *dev)
@@ -3273,10 +3280,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
                return;
        b43_set_status(dev, B43_STAT_UNINIT);
 
-       mutex_unlock(&dev->wl->mutex);
-       b43_rfkill_exit(dev);
-       mutex_lock(&dev->wl->mutex);
-
+       b43_leds_exit(dev);
        b43_rng_exit(dev->wl);
        b43_pio_free(dev);
        b43_dma_free(dev);
@@ -3350,15 +3354,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        }
        b43_hf_write(dev, hf);
 
-       /* Short/Long Retry Limit.
-        * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
-        * the chip-internal counter.
-        */
-       tmp = limit_value(modparam_short_retry, 0, 0xF);
-       b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, tmp);
-       tmp = limit_value(modparam_long_retry, 0, 0xF);
-       b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, tmp);
-
+       b43_set_retry_limits(dev, B43_DEFAULT_SHORT_RETRY_LIMIT,
+                            B43_DEFAULT_LONG_RETRY_LIMIT);
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3);
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2);
 
@@ -3405,12 +3402,12 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        memset(wl->mac_addr, 0, ETH_ALEN);
        b43_upload_card_macaddress(dev);
        b43_security_init(dev);
-       b43_rfkill_init(dev);
        b43_rng_init(wl);
 
        b43_set_status(dev, B43_STAT_INITIALIZED);
 
-      out:
+       b43_leds_init(dev);
+out:
        return err;
 
       err_chip_exit:
@@ -3427,8 +3424,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        return err;
 }
 
-static int b43_add_interface(struct ieee80211_hw *hw,
-                            struct ieee80211_if_init_conf *conf)
+static int b43_op_add_interface(struct ieee80211_hw *hw,
+                               struct ieee80211_if_init_conf *conf)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
@@ -3467,8 +3464,8 @@ static int b43_add_interface(struct ieee80211_hw *hw,
        return err;
 }
 
-static void b43_remove_interface(struct ieee80211_hw *hw,
-                                struct ieee80211_if_init_conf *conf)
+static void b43_op_remove_interface(struct ieee80211_hw *hw,
+                                   struct ieee80211_if_init_conf *conf)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
@@ -3492,13 +3489,17 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
        mutex_unlock(&wl->mutex);
 }
 
-static int b43_start(struct ieee80211_hw *hw)
+static int b43_op_start(struct ieee80211_hw *hw)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
        int did_init = 0;
        int err = 0;
 
+       /* First register RFkill.
+        * LEDs that are registered later depend on it. */
+       b43_rfkill_init(dev);
+
        mutex_lock(&wl->mutex);
 
        if (b43_status(dev) < B43_STAT_INITIALIZED) {
@@ -3523,11 +3524,13 @@ static int b43_start(struct ieee80211_hw *hw)
        return err;
 }
 
-static void b43_stop(struct ieee80211_hw *hw)
+static void b43_op_stop(struct ieee80211_hw *hw)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
 
+       b43_rfkill_exit(dev);
+
        mutex_lock(&wl->mutex);
        if (b43_status(dev) >= B43_STAT_STARTED)
                b43_wireless_core_stop(dev);
@@ -3535,19 +3538,40 @@ static void b43_stop(struct ieee80211_hw *hw)
        mutex_unlock(&wl->mutex);
 }
 
+static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
+                                 u32 short_retry_limit, u32 long_retry_limit)
+{
+       struct b43_wl *wl = hw_to_b43_wl(hw);
+       struct b43_wldev *dev;
+       int err = 0;
+
+       mutex_lock(&wl->mutex);
+       dev = wl->current_dev;
+       if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) {
+               err = -ENODEV;
+               goto out_unlock;
+       }
+       b43_set_retry_limits(dev, short_retry_limit, long_retry_limit);
+out_unlock:
+       mutex_unlock(&wl->mutex);
+
+       return err;
+}
+
 static const struct ieee80211_ops b43_hw_ops = {
-       .tx = b43_tx,
-       .conf_tx = b43_conf_tx,
-       .add_interface = b43_add_interface,
-       .remove_interface = b43_remove_interface,
-       .config = b43_dev_config,
-       .config_interface = b43_config_interface,
-       .configure_filter = b43_configure_filter,
-       .set_key = b43_dev_set_key,
-       .get_stats = b43_get_stats,
-       .get_tx_stats = b43_get_tx_stats,
-       .start = b43_start,
-       .stop = b43_stop,
+       .tx                     = b43_op_tx,
+       .conf_tx                = b43_op_conf_tx,
+       .add_interface          = b43_op_add_interface,
+       .remove_interface       = b43_op_remove_interface,
+       .config                 = b43_op_config,
+       .config_interface       = b43_op_config_interface,
+       .configure_filter       = b43_op_configure_filter,
+       .set_key                = b43_op_set_key,
+       .get_stats              = b43_op_get_stats,
+       .get_tx_stats           = b43_op_get_tx_stats,
+       .start                  = b43_op_start,
+       .stop                   = b43_op_stop,
+       .set_retry_limit        = b43_op_set_retry_limit,
 };
 
 /* Hard-reset the chip. Do not call this directly.