b43: Fix ofdmtab write regression
[deliverable/linux.git] / drivers / net / wireless / b43 / main.c
index 178ad9120107d17edb36994b5e12d101a0592694..d7ea671394a8cb84204a2d2be6ef5a415cb9412d 100644 (file)
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
-  Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
   Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -93,6 +93,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
+       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
        SSB_DEVTABLE_END
 };
 
@@ -1394,8 +1395,17 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
        if (unlikely(reason & B43_IRQ_MAC_TXERR))
                b43err(dev->wl, "MAC transmission error\n");
 
-       if (unlikely(reason & B43_IRQ_PHY_TXERR))
+       if (unlikely(reason & B43_IRQ_PHY_TXERR)) {
                b43err(dev->wl, "PHY transmission error\n");
+               rmb();
+               if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+                       atomic_set(&dev->phy.txerr_cnt,
+                                  B43_PHY_TX_BADNESS_LIMIT);
+                       b43err(dev->wl, "Too many PHY TX errors, "
+                                       "restarting the controller\n");
+                       b43_controller_restart(dev, "PHY TX errors");
+               }
+       }
 
        if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
                                          B43_DMAIRQ_NONFATALMASK))) {
@@ -1924,7 +1934,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
                mask |= 0x0180;
                set |= 0x0180;
        }
-       if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL) {
+       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
                b43_write16(dev, B43_MMIO_GPIO_MASK,
                            b43_read16(dev, B43_MMIO_GPIO_MASK)
                            | 0x0200);
@@ -2286,7 +2296,7 @@ static void b43_periodic_every60sec(struct b43_wldev *dev)
 
        if (!b43_has_hardware_pctl(phy))
                b43_lo_g_ctl_mark_all_unused(dev);
-       if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
                b43_mac_suspend(dev);
                b43_calc_nrssi_slope(dev);
                if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
@@ -2338,6 +2348,9 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
        }
        b43_phy_xmitpower(dev); //FIXME: unless scanning?
        //TODO for APHY (temperature?)
+
+       atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+       wmb();
 }
 
 static void do_periodic_work(struct b43_wldev *dev)
@@ -2483,8 +2496,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;
@@ -2502,21 +2516,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;
@@ -2534,12 +2548,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;
@@ -2692,7 +2706,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;
@@ -2756,6 +2770,8 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
                        b43_short_slot_timing_disable(dev);
        }
 
+       dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
        /* Adjust the desired TX power level. */
        if (conf->power_level != 0) {
                if (conf->power_level != phy->power_level) {
@@ -2797,7 +2813,7 @@ 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)
 {
@@ -2886,7 +2902,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",
@@ -2896,9 +2911,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;
@@ -2933,8 +2948,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;
@@ -3057,7 +3073,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                        unsupported = 1;
                break;
        case B43_PHYTYPE_G:
-               if (phy_rev > 8)
+               if (phy_rev > 9)
                        unsupported = 1;
                break;
        default:
@@ -3173,6 +3189,12 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
        phy->channel = 0xFF;
 
        phy->hardware_power_control = !!modparam_hwpctl;
+
+       /* PHY TX errors counter. */
+       atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+
+       /* OFDM-table address caching. */
+       phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
 }
 
 static void setup_struct_wldev_for_init(struct b43_wldev *dev)
@@ -3204,13 +3226,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
        struct ssb_sprom *sprom = &dev->dev->bus->sprom;
        u32 hf;
 
-       if (!(sprom->r1.boardflags_lo & B43_BFL_BTCOEXIST))
+       if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
                return;
        if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
                return;
 
        hf = b43_hf_read(dev);
-       if (sprom->r1.boardflags_lo & B43_BFL_BTCMOD)
+       if (sprom->boardflags_lo & B43_BFL_BTCMOD)
                hf |= B43_HF_BTCOEXALT;
        else
                hf |= B43_HF_BTCOEX;
@@ -3341,7 +3363,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
                hf |= B43_HF_SYMW;
                if (phy->rev == 1)
                        hf |= B43_HF_GDCW;
-               if (sprom->r1.boardflags_lo & B43_BFL_PACTRL)
+               if (sprom->boardflags_lo & B43_BFL_PACTRL)
                        hf |= B43_HF_OFDMPABOOST;
        } else if (phy->type == B43_PHYTYPE_B) {
                hf |= B43_HF_SYMW;
@@ -3420,8 +3442,8 @@ out:
        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;
@@ -3460,8 +3482,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;
@@ -3485,7 +3507,7 @@ 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;
@@ -3520,7 +3542,7 @@ 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;
@@ -3555,18 +3577,18 @@ out_unlock:
 }
 
 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,
 };
 
@@ -3858,20 +3880,20 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
        /* boardflags workarounds */
        if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
            bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
-               bus->sprom.r1.boardflags_lo |= B43_BFL_BTCOEXIST;
+               bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
        if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
            bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
-               bus->sprom.r1.boardflags_lo |= B43_BFL_PACTRL;
+               bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
 
        /* Handle case when gain is not set in sprom */
-       if (bus->sprom.r1.antenna_gain_a == 0xFF)
-               bus->sprom.r1.antenna_gain_a = 2;
-       if (bus->sprom.r1.antenna_gain_bg == 0xFF)
-               bus->sprom.r1.antenna_gain_bg = 2;
+       if (bus->sprom.antenna_gain_a == 0xFF)
+               bus->sprom.antenna_gain_a = 2;
+       if (bus->sprom.antenna_gain_bg == 0xFF)
+               bus->sprom.antenna_gain_bg = 2;
 
        /* Convert Antennagain values to Q5.2 */
-       bus->sprom.r1.antenna_gain_a <<= 2;
-       bus->sprom.r1.antenna_gain_bg <<= 2;
+       bus->sprom.antenna_gain_a <<= 2;
+       bus->sprom.antenna_gain_bg <<= 2;
 }
 
 static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
@@ -3898,16 +3920,17 @@ static int b43_wireless_init(struct ssb_device *dev)
        }
 
        /* fill hw info */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+       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;
        hw->queues = 1;         /* FIXME: hardware has more queues */
        SET_IEEE80211_DEV(hw, dev->dev);
-       if (is_valid_ether_addr(sprom->r1.et1mac))
-               SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+       if (is_valid_ether_addr(sprom->et1mac))
+               SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
        else
-               SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+               SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
 
        /* Get and initialize struct b43_wl */
        wl = hw_to_b43_wl(hw);
This page took 0.033798 seconds and 5 git commands to generate.