]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/b43/main.c
[B43]: LED triggers support
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / b43 / main.c
index 66c89df51fb8f8ac5d209f49457c81b285308137..2b81bd6165d8105edc418561666747d65faed0d2 100644 (file)
@@ -84,22 +84,10 @@ 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 int modparam_noleds;
-module_param_named(noleds, modparam_noleds, int, 0444);
-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
-
 static char modparam_fwpostfix[16];
 module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
 MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
 
-static int modparam_mon_keep_bad;
-module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444);
-MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode");
-
-static int modparam_mon_keep_badplcp;
-module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444);
-MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode");
-
 static int modparam_hwpctl;
 module_param_named(hwpctl, modparam_hwpctl, int, 0444);
 MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)");
@@ -561,15 +549,10 @@ static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
        }
 }
 
-static void b43_upload_card_macaddress(struct b43_wldev *dev,
-                                      const u8 * mac_addr)
+static void b43_upload_card_macaddress(struct b43_wldev *dev)
 {
-       if (mac_addr)
-               memcpy(dev->wl->mac_addr, mac_addr, ETH_ALEN);
-       else
-               memset(dev->wl->mac_addr, 0, ETH_ALEN);
        b43_write_mac_bssid_templates(dev);
-       b43_macfilter_set(dev, B43_MACFILTER_SELF, mac_addr);
+       b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
 }
 
 static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
@@ -1404,7 +1387,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
        u32 reason;
        u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
        u32 merged_dma_reason = 0;
-       int i, activity = 0;
+       int i;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->wl->irq_lock, flags);
@@ -1457,8 +1440,9 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
                handle_irq_beacon(dev);
        if (reason & B43_IRQ_PMQ)
                handle_irq_pmq(dev);
-       if (reason & B43_IRQ_TXFIFO_FLUSH_OK) ;
-       /*TODO*/ if (reason & B43_IRQ_NOISESAMPLE_OK)
+       if (reason & B43_IRQ_TXFIFO_FLUSH_OK)
+               ;/* TODO */
+       if (reason & B43_IRQ_NOISESAMPLE_OK)
                handle_irq_noise(dev);
 
        /* Check the DMA reason registers for received data. */
@@ -1467,7 +1451,6 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
                        b43_pio_rx(dev->pio.queue0);
                else
                        b43_dma_rx(dev->dma.rx_ring0);
-               /* We intentionally don't set "activity" to 1, here. */
        }
        B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
        B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
@@ -1476,19 +1459,13 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
                        b43_pio_rx(dev->pio.queue3);
                else
                        b43_dma_rx(dev->dma.rx_ring3);
-               activity = 1;
        }
        B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
        B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
 
-       if (reason & B43_IRQ_TX_OK) {
+       if (reason & B43_IRQ_TX_OK)
                handle_irq_transmit_status(dev);
-               activity = 1;
-               //TODO: In AP mode, this also causes sending of powersave responses.
-       }
 
-       if (!modparam_noleds)
-               b43_leds_update(dev, activity);
        b43_interrupt_enable(dev, dev->irq_savedstate);
        mmiowb();
        spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
@@ -1940,7 +1917,6 @@ static int b43_gpio_init(struct b43_wldev *dev)
        b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
                    & ~B43_MACCTL_GPOUTSMSK);
 
-       b43_leds_switch_all(dev, 0);
        b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
                    | 0x000F);
 
@@ -2052,33 +2028,25 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
        ctl &= ~B43_MACCTL_KEEP_BADPLCP;
        ctl &= ~B43_MACCTL_KEEP_BAD;
        ctl &= ~B43_MACCTL_PROMISC;
+       ctl &= ~B43_MACCTL_BEACPROMISC;
        ctl |= B43_MACCTL_INFRA;
 
-       if (wl->operating) {
-               switch (wl->if_type) {
-               case IEEE80211_IF_TYPE_AP:
-                       ctl |= B43_MACCTL_AP;
-                       break;
-               case IEEE80211_IF_TYPE_IBSS:
-                       ctl &= ~B43_MACCTL_INFRA;
-                       break;
-               case IEEE80211_IF_TYPE_STA:
-               case IEEE80211_IF_TYPE_MNTR:
-               case IEEE80211_IF_TYPE_WDS:
-                       break;
-               default:
-                       B43_WARN_ON(1);
-               }
-       }
-       if (wl->monitor) {
+       if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
+               ctl |= B43_MACCTL_AP;
+       else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
+               ctl &= ~B43_MACCTL_INFRA;
+
+       if (wl->filter_flags & FIF_CONTROL)
                ctl |= B43_MACCTL_KEEP_CTL;
-               if (modparam_mon_keep_bad)
-                       ctl |= B43_MACCTL_KEEP_BAD;
-               if (modparam_mon_keep_badplcp)
-                       ctl |= B43_MACCTL_KEEP_BADPLCP;
-       }
-       if (wl->promisc)
+       if (wl->filter_flags & FIF_FCSFAIL)
+               ctl |= B43_MACCTL_KEEP_BAD;
+       if (wl->filter_flags & FIF_PLCPFAIL)
+               ctl |= B43_MACCTL_KEEP_BADPLCP;
+       if (wl->filter_flags & FIF_PROMISC_IN_BSS)
                ctl |= B43_MACCTL_PROMISC;
+       if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
+               ctl |= B43_MACCTL_BEACPROMISC;
+
        /* Workaround: On old hardware the HW-MAC-address-filter
         * doesn't work properly, so always run promisc in filter
         * it in software. */
@@ -2175,12 +2143,26 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
 }
 
+/* Returns TRUE, if the radio is enabled in hardware. */
+static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
+{
+       if (dev->phy.rev >= 3) {
+               if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
+                     & B43_MMIO_RADIO_HWENABLED_HI_MASK))
+                       return 1;
+       } else {
+               if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
+                   & B43_MMIO_RADIO_HWENABLED_LO_MASK)
+                       return 1;
+       }
+       return 0;
+}
+
 /* This is the opposite of b43_chip_init() */
 static void b43_chip_exit(struct b43_wldev *dev)
 {
        b43_radio_turn_off(dev);
-       if (!modparam_noleds)
-               b43_leds_exit(dev);
+       b43_leds_exit(dev);
        b43_gpio_cleanup(dev);
        /* firmware is released later */
 }
@@ -2208,13 +2190,12 @@ 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_gpio_cleanup;
+               goto err_leds_exit;
        b43_radio_turn_on(dev);
-       dev->radio_hw_enable = b43_is_hw_radio_enabled(dev);
-       b43dbg(dev->wl, "Radio %s by hardware\n",
-              (dev->radio_hw_enable == 0) ? "disabled" : "enabled");
 
        b43_write16(dev, 0x03E6, 0x0000);
        err = b43_phy_init(dev);
@@ -2242,9 +2223,6 @@ static int b43_chip_init(struct b43_wldev *dev)
                    & ~B43_MACCTL_INFRA);
        b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
                    | B43_MACCTL_INFRA);
-       /* Let beacons come through */
-       b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
-                   | B43_MACCTL_BEACPROMISC);
 
        if (b43_using_pio(dev)) {
                b43_write32(dev, 0x0210, 0x00000100);
@@ -2287,14 +2265,15 @@ static int b43_chip_init(struct b43_wldev *dev)
 
        err = 0;
        b43dbg(dev->wl, "Chip initialized\n");
-      out:
+out:
        return err;
 
-      err_radio_off:
+err_radio_off:
        b43_radio_turn_off(dev);
-      err_gpio_cleanup:
+err_leds_exit:
+       b43_leds_exit(dev);
        b43_gpio_cleanup(dev);
-       goto out;
+       return err;
 }
 
 static void b43_periodic_every120sec(struct b43_wldev *dev)
@@ -2373,15 +2352,14 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
 
 static void b43_periodic_every1sec(struct b43_wldev *dev)
 {
-       int radio_hw_enable;
+       bool radio_hw_enable;
 
        /* check if radio hardware enabled status changed */
        radio_hw_enable = b43_is_hw_radio_enabled(dev);
        if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
                dev->radio_hw_enable = radio_hw_enable;
-               b43dbg(dev->wl, "Radio hardware status changed to %s\n",
-                      (radio_hw_enable == 0) ? "disabled" : "enabled");
-               b43_leds_update(dev, 0);
+               b43info(dev->wl, "Radio hardware status changed to %s\n",
+                       radio_hw_enable ? "ENABLED" : "DISABLED");
        }
 }
 
@@ -2862,6 +2840,21 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
        if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
                b43_set_beacon_int(dev, conf->beacon_int);
 
+       if (!!conf->radio_enabled != phy->radio_on) {
+               if (conf->radio_enabled) {
+                       b43_radio_turn_on(dev);
+                       b43info(dev->wl, "Radio turned on by software\n");
+                       if (!dev->radio_hw_enable) {
+                               b43info(dev->wl, "The hardware RF-kill button "
+                                       "still turns the radio physically off. "
+                                       "Press the button to turn it on.\n");
+                       }
+               } else {
+                       b43_radio_turn_off(dev);
+                       b43info(dev->wl, "Radio turned off by software\n");
+               }
+       }
+
        spin_lock_irqsave(&wl->irq_lock, flags);
        b43_interrupt_enable(dev, savedirqs);
        mmiowb();
@@ -2872,9 +2865,9 @@ 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,
-                          set_key_cmd cmd, const u8 *local_addr,
-                          const u8 *addr, struct ieee80211_key_conf *key)
+static int b43_dev_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;
@@ -2976,21 +2969,40 @@ out:
        return err;
 }
 
-static void b43_set_multicast_list(struct ieee80211_hw *hw,
-                                  unsigned short netflags, int mc_count)
+static void b43_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;
        unsigned long flags;
 
-       if (!dev)
+       if (!dev) {
+               *fflags = 0;
                return;
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       if (wl->promisc != !!(netflags & IFF_PROMISC)) {
-               wl->promisc = !!(netflags & IFF_PROMISC);
-               if (b43_status(dev) >= B43_STAT_INITIALIZED)
-                       b43_adjust_opmode(dev);
        }
+
+       spin_lock_irqsave(&wl->irq_lock, flags);
+       *fflags &= FIF_PROMISC_IN_BSS |
+                 FIF_ALLMULTI |
+                 FIF_FCSFAIL |
+                 FIF_PLCPFAIL |
+                 FIF_CONTROL |
+                 FIF_OTHER_BSS |
+                 FIF_BCN_PRBRESP_PROMISC;
+
+       changed &= FIF_PROMISC_IN_BSS |
+                  FIF_ALLMULTI |
+                  FIF_FCSFAIL |
+                  FIF_PLCPFAIL |
+                  FIF_CONTROL |
+                  FIF_OTHER_BSS |
+                  FIF_BCN_PRBRESP_PROMISC;
+
+       wl->filter_flags = *fflags;
+
+       if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
+               b43_adjust_opmode(dev);
        spin_unlock_irqrestore(&wl->irq_lock, flags);
 }
 
@@ -3005,21 +3017,19 @@ static int b43_config_interface(struct ieee80211_hw *hw,
                return -ENODEV;
        mutex_lock(&wl->mutex);
        spin_lock_irqsave(&wl->irq_lock, flags);
-       if (conf->type != IEEE80211_IF_TYPE_MNTR) {
-               B43_WARN_ON(wl->if_id != if_id);
-               if (conf->bssid)
-                       memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-               else
-                       memset(wl->bssid, 0, ETH_ALEN);
-               if (b43_status(dev) >= B43_STAT_INITIALIZED) {
-                       if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
-                               B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
-                               b43_set_ssid(dev, conf->ssid, conf->ssid_len);
-                               if (conf->beacon)
-                                       b43_refresh_templates(dev, conf->beacon);
-                       }
-                       b43_write_mac_bssid_templates(dev);
+       B43_WARN_ON(wl->if_id != if_id);
+       if (conf->bssid)
+               memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+       else
+               memset(wl->bssid, 0, ETH_ALEN);
+       if (b43_status(dev) >= B43_STAT_INITIALIZED) {
+               if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
+                       B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+                       b43_set_ssid(dev, conf->ssid, conf->ssid_len);
+                       if (conf->beacon)
+                               b43_refresh_templates(dev, conf->beacon);
                }
+               b43_write_mac_bssid_templates(dev);
        }
        spin_unlock_irqrestore(&wl->irq_lock, flags);
        mutex_unlock(&wl->mutex);
@@ -3206,6 +3216,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
        phy->aci_wlan_automatic = 0;
        phy->aci_hw_rssi = 0;
 
+       phy->radio_off_context.valid = 0;
+
        lo = phy->lo_control;
        if (lo) {
                memset(lo, 0, sizeof(*(phy->lo_control)));
@@ -3237,6 +3249,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 {
        /* Flags */
        dev->reg124_set_0x4 = 0;
+       /* 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;
 
        /* Stats */
        memset(&dev->stats, 0, sizeof(dev->stats));
@@ -3440,7 +3455,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 
        ssb_bus_powerup(bus, 1);        /* Enable dynamic PCTL */
        memset(wl->bssid, 0, ETH_ALEN);
-       b43_upload_card_macaddress(dev, NULL);
+       memset(wl->mac_addr, 0, ETH_ALEN);
+       b43_upload_card_macaddress(dev);
        b43_security_init(dev);
        b43_rng_init(wl);
 
@@ -3470,21 +3486,80 @@ static int b43_add_interface(struct ieee80211_hw *hw,
        struct b43_wldev *dev;
        unsigned long flags;
        int err = -EOPNOTSUPP;
-       int did_init = 0;
+
+       /* TODO: allow WDS/AP devices to coexist */
+
+       if (conf->type != IEEE80211_IF_TYPE_AP &&
+           conf->type != IEEE80211_IF_TYPE_STA &&
+           conf->type != IEEE80211_IF_TYPE_WDS &&
+           conf->type != IEEE80211_IF_TYPE_IBSS)
+               return -EOPNOTSUPP;
 
        mutex_lock(&wl->mutex);
-       if ((conf->type != IEEE80211_IF_TYPE_MNTR) && wl->operating)
+       if (wl->operating)
                goto out_mutex_unlock;
 
        b43dbg(wl, "Adding Interface type %d\n", conf->type);
 
        dev = wl->current_dev;
+       wl->operating = 1;
+       wl->if_id = conf->if_id;
+       wl->if_type = conf->type;
+       memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+
+       spin_lock_irqsave(&wl->irq_lock, flags);
+       b43_adjust_opmode(dev);
+       b43_upload_card_macaddress(dev);
+       spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+       err = 0;
+ out_mutex_unlock:
+       mutex_unlock(&wl->mutex);
+
+       return err;
+}
+
+static void b43_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;
+       unsigned long flags;
+
+       b43dbg(wl, "Removing Interface type %d\n", conf->type);
+
+       mutex_lock(&wl->mutex);
+
+       B43_WARN_ON(!wl->operating);
+       B43_WARN_ON(wl->if_id != conf->if_id);
+
+       wl->operating = 0;
+
+       spin_lock_irqsave(&wl->irq_lock, flags);
+       b43_adjust_opmode(dev);
+       memset(wl->mac_addr, 0, ETH_ALEN);
+       b43_upload_card_macaddress(dev);
+       spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+       mutex_unlock(&wl->mutex);
+}
+
+static int b43_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;
+
+       mutex_lock(&wl->mutex);
+
        if (b43_status(dev) < B43_STAT_INITIALIZED) {
                err = b43_wireless_core_init(dev);
                if (err)
                        goto out_mutex_unlock;
                did_init = 1;
        }
+
        if (b43_status(dev) < B43_STAT_STARTED) {
                err = b43_wireless_core_start(dev);
                if (err) {
@@ -3494,59 +3569,21 @@ static int b43_add_interface(struct ieee80211_hw *hw,
                }
        }
 
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       switch (conf->type) {
-       case IEEE80211_IF_TYPE_MNTR:
-               wl->monitor++;
-               break;
-       default:
-               wl->operating = 1;
-               wl->if_id = conf->if_id;
-               wl->if_type = conf->type;
-               b43_upload_card_macaddress(dev, conf->mac_addr);
-       }
-       b43_adjust_opmode(dev);
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-
-       err = 0;
-      out_mutex_unlock:
+ out_mutex_unlock:
        mutex_unlock(&wl->mutex);
 
        return err;
 }
 
-static void b43_remove_interface(struct ieee80211_hw *hw,
-                                struct ieee80211_if_init_conf *conf)
+void b43_stop(struct ieee80211_hw *hw)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
-       struct b43_wldev *dev;
-       unsigned long flags;
-
-       b43dbg(wl, "Removing Interface type %d\n", conf->type);
+       struct b43_wldev *dev = wl->current_dev;
 
        mutex_lock(&wl->mutex);
-       if (conf->type == IEEE80211_IF_TYPE_MNTR) {
-               wl->monitor--;
-               B43_WARN_ON(wl->monitor < 0);
-       } else {
-               B43_WARN_ON(!wl->operating);
-               wl->operating = 0;
-       }
-
-       dev = wl->current_dev;
-       if (!wl->operating && wl->monitor == 0) {
-               /* No interface left. */
-               if (b43_status(dev) >= B43_STAT_STARTED)
-                       b43_wireless_core_stop(dev);
-               b43_wireless_core_exit(dev);
-       } else {
-               /* Just monitor interfaces left. */
-               spin_lock_irqsave(&wl->irq_lock, flags);
-               b43_adjust_opmode(dev);
-               if (!wl->operating)
-                       b43_upload_card_macaddress(dev, NULL);
-               spin_unlock_irqrestore(&wl->irq_lock, flags);
-       }
+       if (b43_status(dev) >= B43_STAT_STARTED)
+               b43_wireless_core_stop(dev);
+       b43_wireless_core_exit(dev);
        mutex_unlock(&wl->mutex);
 }
 
@@ -3557,10 +3594,12 @@ static const struct ieee80211_ops b43_hw_ops = {
        .remove_interface = b43_remove_interface,
        .config = b43_dev_config,
        .config_interface = b43_config_interface,
-       .set_multicast_list = b43_set_multicast_list,
+       .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,
 };
 
 /* Hard-reset the chip. Do not call this directly.
@@ -3718,18 +3757,13 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
        } else
                have_bphy = 1;
 
-       /* Initialize LEDs structs. */
-       err = b43_leds_init(dev);
-       if (err)
-               goto err_powerdown;
-
        dev->phy.gmode = (have_gphy || have_bphy);
        tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
        b43_wireless_core_reset(dev, tmp);
 
        err = b43_phy_versioning(dev);
        if (err)
-               goto err_leds_exit;
+               goto err_powerdown;
        /* Check if this device supports multiband. */
        if (!pdev ||
            (pdev->device != 0x4312 &&
@@ -3758,10 +3792,10 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 
        err = b43_validate_chipaccess(dev);
        if (err)
-               goto err_leds_exit;
+               goto err_powerdown;
        err = b43_setup_modes(dev, have_aphy, have_bphy, have_gphy);
        if (err)
-               goto err_leds_exit;
+               goto err_powerdown;
 
        /* Now set some default "current_dev" */
        if (!wl->current_dev)
@@ -3776,8 +3810,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 out:
        return err;
 
-err_leds_exit:
-       b43_leds_exit(dev);
 err_powerdown:
        ssb_bus_may_powerdown(bus);
        return err;
@@ -3898,8 +3930,7 @@ static int b43_wireless_init(struct ssb_device *dev)
        }
 
        /* fill hw info */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-           IEEE80211_HW_MONITOR_DURING_OPER;
+       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
        hw->max_signal = 100;
        hw->max_rssi = -110;
        hw->max_noise = -110;