Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Jun 2011 19:25:51 +0000 (15:25 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Jun 2011 19:25:51 +0000 (15:25 -0400)
Conflicts:
drivers/net/wireless/rtlwifi/pci.c
include/linux/netlink.h

14 files changed:
1  2 
drivers/bcma/host_pci.c
drivers/net/b44.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/iwlegacy/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/libertas/if_spi.c
include/linux/netlink.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/netlink/af_netlink.c

diff --combined drivers/bcma/host_pci.c
@@@ -6,7 -6,6 +6,7 @@@
   */
  
  #include "bcma_private.h"
 +#include <linux/slab.h>
  #include <linux/bcma/bcma.h>
  #include <linux/pci.h>
  
@@@ -227,6 -226,7 +227,7 @@@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
        { 0, },
  };
diff --combined drivers/net/b44.c
@@@ -25,7 -25,6 +25,7 @@@
  #include <linux/pci.h>
  #include <linux/delay.h>
  #include <linux/init.h>
 +#include <linux/interrupt.h>
  #include <linux/dma-mapping.h>
  #include <linux/ssb/ssb.h>
  #include <linux/slab.h>
@@@ -2336,7 -2335,7 +2336,7 @@@ static struct ssb_driver b44_ssb_drive
        .resume         = b44_resume,
  };
  
- static inline int b44_pci_init(void)
+ static inline int __init b44_pci_init(void)
  {
        int err = 0;
  #ifdef CONFIG_B44_PCI
        return err;
  }
  
- static inline void b44_pci_exit(void)
+ static inline void __exit b44_pci_exit(void)
  {
  #ifdef CONFIG_B44_PCI
        ssb_pcihost_unregister(&b44_pci_driver);
@@@ -42,7 -42,6 +42,7 @@@
  
  #include <linux/module.h>
  #include <linux/delay.h>
 +#include <linux/dma-mapping.h>
  #include <linux/hardirq.h>
  #include <linux/if.h>
  #include <linux/io.h>
@@@ -88,8 -87,6 +88,6 @@@ MODULE_LICENSE("Dual BSD/GPL")
  static int ath5k_init(struct ieee80211_hw *hw);
  static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
                                                                bool skip_pcu);
- int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
- void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
  
  /* Known SREVs */
  static const struct ath5k_srev_name srev_names[] = {
@@@ -2162,7 -2159,7 +2160,7 @@@ ath5k_schedule_tx(struct ath5k_softc *s
        tasklet_schedule(&sc->txtq);
  }
  
- irqreturn_t
static irqreturn_t
  ath5k_intr(int irq, void *dev_id)
  {
        struct ath5k_softc *sc = dev_id;
@@@ -2616,7 -2613,7 +2614,7 @@@ done
        return ret;
  }
  
- static void stop_tasklets(struct ath5k_softc *sc)
+ static void ath5k_stop_tasklets(struct ath5k_softc *sc)
  {
        sc->rx_pending = false;
        sc->tx_pending = false;
@@@ -2670,7 -2667,7 +2668,7 @@@ ath5k_stop_hw(struct ath5k_softc *sc
        mmiowb();
        mutex_unlock(&sc->lock);
  
-       stop_tasklets(sc);
+       ath5k_stop_tasklets(sc);
  
        cancel_delayed_work_sync(&sc->tx_complete_work);
  
@@@ -2698,7 -2695,7 +2696,7 @@@ ath5k_reset(struct ath5k_softc *sc, str
  
        ath5k_hw_set_imr(ah, 0);
        synchronize_irq(sc->irq);
-       stop_tasklets(sc);
+       ath5k_stop_tasklets(sc);
  
        /* Save ani mode and disable ANI during
         * reset. If we don't we might get false
@@@ -2963,11 -2960,12 +2961,12 @@@ ath5k_deinit_softc(struct ath5k_softc *
         * state and potentially want to use them.
         */
        ath5k_hw_deinit(sc->ah);
+       kfree(sc->ah);
        free_irq(sc->irq, sc);
  }
  
  bool
- ath_any_vif_assoc(struct ath5k_softc *sc)
+ ath5k_any_vif_assoc(struct ath5k_softc *sc)
  {
        struct ath5k_vif_iter_data iter_data;
        iter_data.hw_macaddr = NULL;
  }
  
  void
- set_beacon_filter(struct ieee80211_hw *hw, bool enable)
ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
  {
        struct ath5k_softc *sc = hw->priv;
        struct ath5k_hw *ah = sc->ah;
@@@ -19,7 -19,6 +19,7 @@@
  
  #include <linux/etherdevice.h>
  #include <linux/device.h>
 +#include <linux/interrupt.h>
  #include <linux/leds.h>
  #include <linux/completion.h>
  
@@@ -55,8 -54,6 +55,6 @@@ struct ath_node
                (_l) &= ((_sz) - 1);            \
        } while (0)
  
- #define A_MAX(a, b) ((a) > (b) ? (a) : (b))
  #define TSF_TO_TU(_h,_l) \
        ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
  
@@@ -580,7 -577,7 +578,7 @@@ struct ath9k_vif_iter_data 
        int naps;      /* number of AP vifs */
        int nmeshes;   /* number of mesh vifs */
        int nstations; /* number of station vifs */
-       int nwds;      /* number of nwd vifs */
+       int nwds;      /* number of WDS vifs */
        int nadhocs;   /* number of adhoc vifs */
        int nothers;   /* number of vifs not specified above. */
  };
@@@ -14,7 -14,6 +14,7 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/dma-mapping.h>
  #include <linux/slab.h>
  #include <linux/ath9k_platform.h>
  
@@@ -246,7 -245,7 +246,7 @@@ static void setup_ht_cap(struct ath_sof
        ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
        ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
  
-       if (AR_SREV_9485(ah))
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
                max_streams = 1;
        else if (AR_SREV_9300_20_OR_LATER(ah))
                max_streams = 3;
@@@ -575,6 -574,8 +575,8 @@@ static int ath9k_init_softc(u16 devid, 
                sc->sc_ah->gpio_val = pdata->gpio_val;
                sc->sc_ah->led_pin = pdata->led_pin;
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
+               ah->get_mac_revision = pdata->get_mac_revision;
+               ah->external_reset = pdata->external_reset;
        }
  
        common = ath9k_hw_common(ah);
@@@ -14,7 -14,6 +14,7 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/dma-mapping.h>
  #include "ath9k.h"
  #include "ar9003_mac.h"
  
@@@ -40,6 -39,7 +40,7 @@@ static inline bool ath_ant_div_comb_alt
                        result = true;
                break;
        case 1:
+       case 2:
                if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
                        (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
                                (alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@@ -1076,39 -1076,39 +1077,39 @@@ static void ath_lnaconf_alt_good_scan(s
                antcomb->rssi_lna1 = main_rssi_avg;
  
        switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
-       case (0x10): /* LNA2 A-B */
+       case 0x10: /* LNA2 A-B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
                break;
-       case (0x20): /* LNA1 A-B */
+       case 0x20: /* LNA1 A-B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
                break;
-       case (0x21): /* LNA1 LNA2 */
+       case 0x21: /* LNA1 LNA2 */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                break;
-       case (0x12): /* LNA2 LNA1 */
+       case 0x12: /* LNA2 LNA1 */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                break;
-       case (0x13): /* LNA2 A+B */
+       case 0x13: /* LNA2 A+B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
                break;
-       case (0x23): /* LNA1 A+B */
+       case 0x23: /* LNA1 A+B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@@ -1325,65 -1325,148 +1326,148 @@@ static void ath_ant_div_conf_fast_divbi
                /* Adjust the fast_div_bias based on main and alt lna conf */
                switch ((ant_conf->main_lna_conf << 4) |
                                ant_conf->alt_lna_conf) {
-               case (0x01): /* A-B LNA2 */
+               case 0x01: /* A-B LNA2 */
                        ant_conf->fast_div_bias = 0x3b;
                        break;
-               case (0x02): /* A-B LNA1 */
+               case 0x02: /* A-B LNA1 */
                        ant_conf->fast_div_bias = 0x3d;
                        break;
-               case (0x03): /* A-B A+B */
+               case 0x03: /* A-B A+B */
                        ant_conf->fast_div_bias = 0x1;
                        break;
-               case (0x10): /* LNA2 A-B */
+               case 0x10: /* LNA2 A-B */
                        ant_conf->fast_div_bias = 0x7;
                        break;
-               case (0x12): /* LNA2 LNA1 */
+               case 0x12: /* LNA2 LNA1 */
                        ant_conf->fast_div_bias = 0x2;
                        break;
-               case (0x13): /* LNA2 A+B */
+               case 0x13: /* LNA2 A+B */
                        ant_conf->fast_div_bias = 0x7;
                        break;
-               case (0x20): /* LNA1 A-B */
+               case 0x20: /* LNA1 A-B */
                        ant_conf->fast_div_bias = 0x6;
                        break;
-               case (0x21): /* LNA1 LNA2 */
+               case 0x21: /* LNA1 LNA2 */
                        ant_conf->fast_div_bias = 0x0;
                        break;
-               case (0x23): /* LNA1 A+B */
+               case 0x23: /* LNA1 A+B */
                        ant_conf->fast_div_bias = 0x6;
                        break;
-               case (0x30): /* A+B A-B */
+               case 0x30: /* A+B A-B */
                        ant_conf->fast_div_bias = 0x1;
                        break;
-               case (0x31): /* A+B LNA2 */
+               case 0x31: /* A+B LNA2 */
                        ant_conf->fast_div_bias = 0x3b;
                        break;
-               case (0x32): /* A+B LNA1 */
+               case 0x32: /* A+B LNA1 */
                        ant_conf->fast_div_bias = 0x3d;
                        break;
                default:
                        break;
                }
+       } else if (ant_conf->div_group == 1) {
+               /* Adjust the fast_div_bias based on main and alt_lna_conf */
+               switch ((ant_conf->main_lna_conf << 4) |
+                       ant_conf->alt_lna_conf) {
+               case 0x01: /* A-B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x02: /* A-B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x03: /* A-B A+B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x10: /* LNA2 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x12: /* LNA2 LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x13: /* LNA2 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x20: /* LNA1 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x21: /* LNA1 LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x23: /* LNA1 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x30: /* A+B A-B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x31: /* A+B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x32: /* A+B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               default:
+                       break;
+               }
        } else if (ant_conf->div_group == 2) {
                /* Adjust the fast_div_bias based on main and alt_lna_conf */
                switch ((ant_conf->main_lna_conf << 4) |
                                ant_conf->alt_lna_conf) {
-               case (0x01): /* A-B LNA2 */
+               case 0x01: /* A-B LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x02): /* A-B LNA1 */
+               case 0x02: /* A-B LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x03): /* A-B A+B */
+               case 0x03: /* A-B A+B */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x10): /* LNA2 A-B */
+               case 0x10: /* LNA2 A-B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x12): /* LNA2 LNA1 */
+               case 0x12: /* LNA2 LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x13): /* LNA2 A+B */
+               case 0x13: /* LNA2 A+B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x20): /* LNA1 A-B */
+               case 0x20: /* LNA1 A-B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x21): /* LNA1 LNA2 */
+               case 0x21: /* LNA1 LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x23): /* LNA1 A+B */
+               case 0x23: /* LNA1 A+B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x30): /* A+B A-B */
+               case 0x30: /* A+B A-B */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x31): /* A+B LNA2 */
+               case 0x31: /* A+B LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x32): /* A+B LNA1 */
+               case 0x32: /* A+B LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                default:
                        break;
                }
        }
  }
  
  /* Antenna diversity and combining */
@@@ -123,6 -123,7 +123,7 @@@ static const struct bcma_device_id b43_
  MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
  #endif
  
+ #ifdef CONFIG_B43_SSB
  static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
        SSB_DEVTABLE_END
  };
  MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+ #endif
  
  /* Channel and ratetables are shared for all devices.
   * They can't be const, because ieee80211 puts some precalculated
@@@ -4096,10 -4097,16 +4097,16 @@@ static int b43_phy_versioning(struct b4
                if (phy_rev > 2)
                        unsupported = 1;
                break;
+ #endif
+ #ifdef CONFIG_B43_PHY_HT
+       case B43_PHYTYPE_HT:
+               if (phy_rev > 1)
+                       unsupported = 1;
+               break;
  #endif
        default:
                unsupported = 1;
 -      };
 +      }
        if (unsupported) {
                b43err(dev->wl, "FOUND UNSUPPORTED PHY "
                       "(Analog %u, Type %u, Revision %u)\n",
                if (radio_ver != 0x2062 && radio_ver != 0x2063)
                        unsupported = 1;
                break;
+       case B43_PHYTYPE_HT:
+               if (radio_ver != 0x2059)
+                       unsupported = 1;
+               break;
        default:
                B43_WARN_ON(1);
        }
@@@ -5016,6 -5027,7 +5027,7 @@@ static struct bcma_driver b43_bcma_driv
  };
  #endif
  
+ #ifdef CONFIG_B43_SSB
  static
  int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
  {
        int first = 0;
  
        dev = b43_bus_dev_ssb_init(sdev);
+       if (!dev)
+               return -ENOMEM;
  
        wl = ssb_get_devtypedata(sdev);
        if (!wl) {
@@@ -5091,6 -5105,14 +5105,14 @@@ static void b43_ssb_remove(struct ssb_d
        }
  }
  
+ static struct ssb_driver b43_ssb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = b43_ssb_tbl,
+       .probe          = b43_ssb_probe,
+       .remove         = b43_ssb_remove,
+ };
+ #endif /* CONFIG_B43_SSB */
  /* Perform a hardware reset. This can be called from any context. */
  void b43_controller_restart(struct b43_wldev *dev, const char *reason)
  {
        ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
  }
  
- static struct ssb_driver b43_ssb_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = b43_ssb_tbl,
-       .probe          = b43_ssb_probe,
-       .remove         = b43_ssb_remove,
- };
  static void b43_print_driverinfo(void)
  {
        const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@@ -5151,14 -5166,18 +5166,18 @@@ static int __init b43_init(void
        if (err)
                goto err_sdio_exit;
  #endif
+ #ifdef CONFIG_B43_SSB
        err = ssb_driver_register(&b43_ssb_driver);
        if (err)
                goto err_bcma_driver_exit;
+ #endif
        b43_print_driverinfo();
  
        return err;
  
+ #ifdef CONFIG_B43_SSB
  err_bcma_driver_exit:
+ #endif
  #ifdef CONFIG_B43_BCMA
        bcma_driver_unregister(&b43_bcma_driver);
  err_sdio_exit:
@@@ -5173,7 -5192,9 +5192,9 @@@ err_dfs_exit
  
  static void __exit b43_exit(void)
  {
+ #ifdef CONFIG_B43_SSB
        ssb_driver_unregister(&b43_ssb_driver);
+ #endif
  #ifdef CONFIG_B43_BCMA
        bcma_driver_unregister(&b43_bcma_driver);
  #endif
@@@ -32,7 -32,6 +32,7 @@@
  #ifndef __iwl_legacy_dev_h__
  #define __iwl_legacy_dev_h__
  
 +#include <linux/interrupt.h>
  #include <linux/pci.h> /* for struct pci_device_id */
  #include <linux/kernel.h>
  #include <linux/leds.h>
@@@ -855,32 -854,6 +855,6 @@@ struct traffic_stats 
  #endif
  };
  
- /*
-  * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
-  * to perform continuous uCode event logging operation if enabled
-  */
- #define UCODE_TRACE_PERIOD (100)
- /*
-  * iwl_event_log: current uCode event log position
-  *
-  * @ucode_trace: enable/disable ucode continuous trace timer
-  * @num_wraps: how many times the event buffer wraps
-  * @next_entry:  the entry just before the next one that uCode would fill
-  * @non_wraps_count: counter for no wrap detected when dump ucode events
-  * @wraps_once_count: counter for wrap once detected when dump ucode events
-  * @wraps_more_count: counter for wrap more than once detected
-  *                  when dump ucode events
-  */
- struct iwl_event_log {
-       bool ucode_trace;
-       u32 num_wraps;
-       u32 next_entry;
-       int non_wraps_count;
-       int wraps_once_count;
-       int wraps_more_count;
- };
  /*
   * host interrupt timeout value
   * used with setting interrupt coalescing timer
  #define IWL_HOST_INT_CALIB_TIMEOUT_DEF        (0x10)
  #define IWL_HOST_INT_CALIB_TIMEOUT_MIN        (0x0)
  
- /*
-  * This is the threshold value of plcp error rate per 100mSecs.  It is
-  * used to set and check for the validity of plcp_delta.
-  */
- #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN        (1)
- #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF        (50)
- #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF   (100)
- #define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF       (200)
- #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX        (255)
- #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE    (0)
- #define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
  #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
  
  /* TX queue watchdog timeouts in mSecs */
  #define IWL_LONG_WD_TIMEOUT   (10000)
  #define IWL_MAX_WD_TIMEOUT    (120000)
  
- enum iwl_reset {
-       IWL_RF_RESET = 0,
-       IWL_FW_RESET,
-       IWL_MAX_FORCE_RESET,
- };
  struct iwl_force_reset {
        int reset_request_count;
        int reset_success_count;
@@@ -1033,11 -988,8 +989,8 @@@ struct iwl_priv 
        /* track IBSS manager (last beacon) status */
        u32 ibss_manager;
  
-       /* storing the jiffies when the plcp error rate is received */
-       unsigned long plcp_jiffies;
        /* force reset */
-       struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+       struct iwl_force_reset force_reset;
  
        /* we allocate array of iwl_channel_info for NIC's valid channels.
         *    Access via channel # using indirect index array */
        enum ieee80211_band scan_band;
        struct cfg80211_scan_request *scan_request;
        struct ieee80211_vif *scan_vif;
-       bool is_internal_short_scan;
        u8 scan_tx_ant[IEEE80211_NUM_BANDS];
        u8 mgmt_tx_ant;
  
  #endif
  #if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
                struct {
-                       /*
-                        * reporting the number of tids has AGG on. 0 means
-                        * no AGGREGATION
-                        */
-                       u8 agg_tids_count;
                        struct iwl_rx_phy_res last_phy_res;
                        bool last_phy_res_valid;
  
        struct iwl_rxon_context *beacon_ctx;
        struct sk_buff *beacon_skb;
  
-       struct work_struct start_internal_scan;
        struct work_struct tx_flush;
  
        struct tasklet_struct irq_tasklet;
        u32 disable_tx_power_cal;
        struct work_struct run_time_calib_work;
        struct timer_list statistics_periodic;
-       struct timer_list ucode_trace;
        struct timer_list watchdog;
        bool hw_ready;
  
-       struct iwl_event_log event_log;
        struct led_classdev led;
        unsigned long blink_on, blink_off;
        bool led_registered;
@@@ -31,7 -31,6 +31,7 @@@
  #ifndef __iwl_dev_h__
  #define __iwl_dev_h__
  
 +#include <linux/interrupt.h>
  #include <linux/pci.h> /* for struct pci_device_id */
  #include <linux/kernel.h>
  #include <linux/wait.h>
@@@ -49,6 -48,8 +49,8 @@@
  #include "iwl-agn-rs.h"
  #include "iwl-agn-tt.h"
  
+ #define DRV_NAME        "iwlagn"
  struct iwl_tx_queue;
  
  /* CT-KILL constants */
@@@ -1169,14 -1170,63 +1171,63 @@@ enum iwl_scan_type 
        IWL_SCAN_OFFCH_TX,
  };
  
+ enum iwlagn_ucode_type {
+       IWL_UCODE_NONE,
+       IWL_UCODE_REGULAR,
+       IWL_UCODE_INIT,
+       IWL_UCODE_WOWLAN,
+ };
  #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
  struct iwl_testmode_trace {
+       u32 buff_size;
+       u32 total_size;
+       u32 num_chunks;
        u8 *cpu_addr;
        u8 *trace_addr;
        dma_addr_t dma_addr;
        bool trace_enabled;
  };
  #endif
+ struct iwl_bus;
+ /**
+  * struct iwl_bus_ops - bus specific operations
+  * @get_pm_support: must returns true if the bus can go to sleep
+  * @apm_config: will be called during the config of the APM configuration
+  * @set_drv_data: set the priv pointer to the bus layer
+  * @get_dev: returns the device struct
+  * @get_irq: returns the irq number
+  * @get_hw_id: prints the hw_id in the provided buffer
+  * @write8: write a byte to register at offset ofs
+  * @write32: write a dword to register at offset ofs
+  * @wread32: read a dword at register at offset ofs
+  */
+ struct iwl_bus_ops {
+       bool (*get_pm_support)(struct iwl_bus *bus);
+       void (*apm_config)(struct iwl_bus *bus);
+       void (*set_drv_data)(struct iwl_bus *bus, void *priv);
+       struct device *(*get_dev)(const struct iwl_bus *bus);
+       unsigned int (*get_irq)(const struct iwl_bus *bus);
+       void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
+       void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
+       void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
+       u32 (*read32)(struct iwl_bus *bus, u32 ofs);
+ };
+ struct iwl_bus {
+       /* pointer to bus specific struct */
+       void *bus_specific;
+       /* Common data to all buses */
+       struct iwl_priv *priv; /* driver's context */
+       struct device *dev;
+       struct iwl_bus_ops *ops;
+       unsigned int irq;
+ };
  struct iwl_priv {
  
        /* ieee device used by generic ieee processing code */
        spinlock_t reg_lock;    /* protect hw register access */
        struct mutex mutex;
  
-       /* basic pci-network driver stuff */
-       struct pci_dev *pci_dev;
-       /* pci hardware address support */
-       void __iomem *hw_base;
+       struct iwl_bus bus;     /* bus specific data */
  
        /* microcode/device supports multiple contexts */
        u8 valid_contexts;
  
        /* command queue number */
        u8 cmd_queue;
+       u8 last_sync_cmd_id;
  
        /* max number of station keys */
        u8 sta_key_max_num;
        struct fw_img ucode_rt;
        struct fw_img ucode_init;
  
-       enum iwlagn_ucode_subtype ucode_type;
+       enum iwlagn_ucode_type ucode_type;
        u8 ucode_write_complete;        /* the image write is complete */
        char firmware_name[25];
  
@@@ -19,8 -19,6 +19,8 @@@
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
 +#include <linux/hardirq.h>
 +#include <linux/interrupt.h>
  #include <linux/moduleparam.h>
  #include <linux/firmware.h>
  #include <linux/jiffies.h>
@@@ -1034,7 -1032,6 +1034,6 @@@ static irqreturn_t if_spi_host_interrup
  static int if_spi_init_card(struct if_spi_card *card)
  {
        struct lbs_private *priv = card->priv;
-       struct spi_device *spi = card->spi;
        int err, i;
        u32 scratch;
        const struct firmware *helper = NULL;
                                "attached to SPI bus_num %d, chip_select %d. "
                                "spi->max_speed_hz=%d\n",
                                card->card_id, card->card_rev,
-                               spi->master->bus_num, spi->chip_select,
-                               spi->max_speed_hz);
+                               card->spi->master->bus_num,
+                               card->spi->chip_select,
+                               card->spi->max_speed_hz);
                err = if_spi_prog_helper_firmware(card, helper);
                if (err)
                        goto out;
diff --combined include/linux/netlink.h
@@@ -24,7 -24,6 +24,7 @@@
  /* leave room for NETLINK_DM (DM Events) */
  #define NETLINK_SCSITRANSPORT 18      /* SCSI Transports */
  #define NETLINK_ECRYPTFS      19
 +#define NETLINK_RDMA          20
  
  #define MAX_LINKS 32          
  
@@@ -49,6 -48,7 +49,7 @@@ struct nlmsghdr 
  #define NLM_F_MULTI           2       /* Multipart message, terminated by NLMSG_DONE */
  #define NLM_F_ACK             4       /* Reply with ack, with zero or error code */
  #define NLM_F_ECHO            8       /* Echo this request            */
+ #define NLM_F_DUMP_INTR               16      /* Dump was inconsistent due to sequence change */
  
  /* Modifiers to GET request */
  #define NLM_F_ROOT    0x100   /* specify tree root    */
@@@ -221,8 -221,8 +222,9 @@@ struct netlink_callback 
        int                     (*dump)(struct sk_buff * skb,
                                        struct netlink_callback *cb);
        int                     (*done)(struct netlink_callback *cb);
 -      int                     family;
 +      u16                     family;
 +      u16                     min_dump_alloc;
+       unsigned int            prev_seq, seq;
        long                    args[6];
  };
  
@@@ -260,8 -260,7 +262,8 @@@ __nlmsg_put(struct sk_buff *skb, u32 pi
  extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
                              const struct nlmsghdr *nlh,
                              int (*dump)(struct sk_buff *skb, struct netlink_callback*),
 -                            int (*done)(struct netlink_callback*));
 +                            int (*done)(struct netlink_callback*),
 +                            u16 min_dump_alloc);
  
  
  #define NL_NONROOT_RECV 0x1
@@@ -25,7 -25,6 +25,7 @@@
  #ifndef __HCI_CORE_H
  #define __HCI_CORE_H
  
 +#include <linux/interrupt.h>
  #include <net/bluetooth/hci.h>
  
  /* HCI upper protocols */
@@@ -90,6 -89,12 +90,12 @@@ struct oob_data 
        u8 randomizer[16];
  };
  
+ struct adv_entry {
+       struct list_head list;
+       bdaddr_t bdaddr;
+       u8 bdaddr_type;
+ };
  #define NUM_REASSEMBLY 4
  struct hci_dev {
        struct list_head list;
  
        __u16                   init_last_cmd;
  
+       struct crypto_blkcipher *tfm;
        struct inquiry_cache    inq_cache;
        struct hci_conn_hash    conn_hash;
        struct list_head        blacklist;
  
        struct list_head        remote_oob_data;
  
+       struct list_head        adv_entries;
+       struct timer_list       adv_timer;
        struct hci_dev_stats    stat;
  
        struct sk_buff_head     driver_init;
@@@ -216,6 -226,7 +227,7 @@@ struct hci_conn 
        spinlock_t      lock;
  
        bdaddr_t        dst;
+       __u8            dst_type;
        __u16           handle;
        __u16           state;
        __u8            mode;
        __u8            power_save;
        __u16           disc_timeout;
        unsigned long   pend;
+       __u8            ltk[16];
  
        __u8            remote_cap;
        __u8            remote_oob;
@@@ -308,12 -320,14 +321,14 @@@ static inline long inquiry_entry_age(st
        return jiffies - e->timestamp;
  }
  
- struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+                                                       bdaddr_t *bdaddr);
  void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
  
  /* ----- HCI Connections ----- */
  enum {
        HCI_CONN_AUTH_PEND,
+       HCI_CONN_REAUTH_PEND,
        HCI_CONN_ENCRYPT_PEND,
        HCI_CONN_RSWITCH_PEND,
        HCI_CONN_MODE_CHANGE_PEND,
@@@ -421,14 -435,15 +436,15 @@@ int hci_conn_del(struct hci_conn *conn)
  void hci_conn_hash_flush(struct hci_dev *hdev);
  void hci_conn_check_pending(struct hci_dev *hdev);
  
- struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
+ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
+                                               __u8 sec_level, __u8 auth_type);
  int hci_conn_check_link_mode(struct hci_conn *conn);
  int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
  int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
  int hci_conn_change_link_key(struct hci_conn *conn);
  int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
  
- void hci_conn_enter_active_mode(struct hci_conn *conn);
+ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
  void hci_conn_enter_sniff_mode(struct hci_conn *conn);
  
  void hci_conn_hold_device(struct hci_conn *conn);
@@@ -450,10 -465,12 +466,12 @@@ static inline void hci_conn_put(struct 
                                timeo = msecs_to_jiffies(conn->disc_timeout);
                                if (!conn->out)
                                        timeo *= 2;
-                       } else
+                       } else {
                                timeo = msecs_to_jiffies(10);
-               } else
+                       }
+               } else {
                        timeo = msecs_to_jiffies(10);
+               }
                mod_timer(&conn->disc_timer, jiffies + timeo);
        }
  }
@@@ -512,6 -529,8 +530,8 @@@ int hci_inquiry(void __user *arg)
  
  struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
  int hci_blacklist_clear(struct hci_dev *hdev);
+ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
+ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
  
  int hci_uuids_clear(struct hci_dev *hdev);
  
@@@ -528,6 -547,12 +548,12 @@@ int hci_add_remote_oob_data(struct hci_
                                                                u8 *randomizer);
  int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
  
+ #define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
+ int hci_adv_entries_clear(struct hci_dev *hdev);
+ struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+ int hci_add_adv_entry(struct hci_dev *hdev,
+                                       struct hci_ev_le_advertising_info *ev);
  void hci_del_off_timer(struct hci_dev *hdev);
  
  void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@@ -562,16 -587,20 +588,20 @@@ struct hci_proto 
  
        void            *priv;
  
-       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                                               __u8 type);
        int (*connect_cfm)      (struct hci_conn *conn, __u8 status);
        int (*disconn_ind)      (struct hci_conn *conn);
        int (*disconn_cfm)      (struct hci_conn *conn, __u8 reason);
-       int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+       int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb,
+                                                               __u16 flags);
        int (*recv_scodata)     (struct hci_conn *conn, struct sk_buff *skb);
-       int (*security_cfm)     (struct hci_conn *conn, __u8 status, __u8 encrypt);
+       int (*security_cfm)     (struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt);
  };
  
- static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                                               __u8 type)
  {
        register struct hci_proto *hp;
        int mask = 0;
@@@ -657,7 -686,8 +687,8 @@@ static inline void hci_proto_auth_cfm(s
                conn->security_cfm_cb(conn, status);
  }
  
- static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt)
  {
        register struct hci_proto *hp;
  
@@@ -682,7 -712,8 +713,8 @@@ struct hci_cb 
  
        char *name;
  
-       void (*security_cfm)    (struct hci_conn *conn, __u8 status, __u8 encrypt);
+       void (*security_cfm)    (struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt);
        void (*key_change_cfm)  (struct hci_conn *conn, __u8 status);
        void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
  };
@@@ -708,13 -739,17 +740,17 @@@ static inline void hci_auth_cfm(struct 
        read_unlock_bh(&hci_cb_list_lock);
  }
  
- static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt)
  {
        struct list_head *p;
  
        if (conn->sec_level == BT_SECURITY_SDP)
                conn->sec_level = BT_SECURITY_LOW;
  
+       if (conn->pending_sec_level > conn->sec_level)
+               conn->sec_level = conn->pending_sec_level;
        hci_proto_encrypt_cfm(conn, status, encrypt);
  
        read_lock_bh(&hci_cb_list_lock);
@@@ -739,7 -774,8 +775,8 @@@ static inline void hci_key_change_cfm(s
        read_unlock_bh(&hci_cb_list_lock);
  }
  
- static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 role)
  {
        struct list_head *p;
  
@@@ -831,4 -867,9 +868,9 @@@ void hci_req_complete(struct hci_dev *h
  
  void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
                                        u16 latency, u16 to_multiplier);
+ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+                                                       __u8 ltk[16]);
+ void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+ void hci_le_ltk_neg_reply(struct hci_conn *conn);
  #endif /* __HCI_CORE_H */
diff --combined net/bluetooth/hci_core.c
@@@ -42,6 -42,7 +42,7 @@@
  #include <linux/notifier.h>
  #include <linux/rfkill.h>
  #include <linux/timer.h>
+ #include <linux/crypto.h>
  #include <net/sock.h>
  
  #include <asm/system.h>
@@@ -59,6 -60,8 +60,8 @@@ static void hci_tx_task(unsigned long a
  
  static DEFINE_RWLOCK(hci_task_lock);
  
+ static int enable_smp;
  /* HCI device list */
  LIST_HEAD(hci_dev_list);
  DEFINE_RWLOCK(hci_dev_list_lock);
@@@ -1202,6 -1205,177 +1205,177 @@@ int hci_add_remote_oob_data(struct hci_
        return 0;
  }
  
+ struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+                                               bdaddr_t *bdaddr)
+ {
+       struct list_head *p;
+       list_for_each(p, &hdev->blacklist) {
+               struct bdaddr_list *b;
+               b = list_entry(p, struct bdaddr_list, list);
+               if (bacmp(bdaddr, &b->bdaddr) == 0)
+                       return b;
+       }
+       return NULL;
+ }
+ int hci_blacklist_clear(struct hci_dev *hdev)
+ {
+       struct list_head *p, *n;
+       list_for_each_safe(p, n, &hdev->blacklist) {
+               struct bdaddr_list *b;
+               b = list_entry(p, struct bdaddr_list, list);
+               list_del(p);
+               kfree(b);
+       }
+       return 0;
+ }
+ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
+ {
+       struct bdaddr_list *entry;
+       int err;
+       if (bacmp(bdaddr, BDADDR_ANY) == 0)
+               return -EBADF;
+       hci_dev_lock(hdev);
+       if (hci_blacklist_lookup(hdev, bdaddr)) {
+               err = -EEXIST;
+               goto err;
+       }
+       entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+       if (!entry) {
+               return -ENOMEM;
+               goto err;
+       }
+       bacpy(&entry->bdaddr, bdaddr);
+       list_add(&entry->list, &hdev->blacklist);
+       err = 0;
+ err:
+       hci_dev_unlock(hdev);
+       return err;
+ }
+ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
+ {
+       struct bdaddr_list *entry;
+       int err = 0;
+       hci_dev_lock(hdev);
+       if (bacmp(bdaddr, BDADDR_ANY) == 0) {
+               hci_blacklist_clear(hdev);
+               goto done;
+       }
+       entry = hci_blacklist_lookup(hdev, bdaddr);
+       if (!entry) {
+               err = -ENOENT;
+               goto done;
+       }
+       list_del(&entry->list);
+       kfree(entry);
+ done:
+       hci_dev_unlock(hdev);
+       return err;
+ }
+ static void hci_clear_adv_cache(unsigned long arg)
+ {
+       struct hci_dev *hdev = (void *) arg;
+       hci_dev_lock(hdev);
+       hci_adv_entries_clear(hdev);
+       hci_dev_unlock(hdev);
+ }
+ int hci_adv_entries_clear(struct hci_dev *hdev)
+ {
+       struct adv_entry *entry, *tmp;
+       list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
+               list_del(&entry->list);
+               kfree(entry);
+       }
+       BT_DBG("%s adv cache cleared", hdev->name);
+       return 0;
+ }
+ struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
+ {
+       struct adv_entry *entry;
+       list_for_each_entry(entry, &hdev->adv_entries, list)
+               if (bacmp(bdaddr, &entry->bdaddr) == 0)
+                       return entry;
+       return NULL;
+ }
+ static inline int is_connectable_adv(u8 evt_type)
+ {
+       if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
+               return 1;
+       return 0;
+ }
+ int hci_add_adv_entry(struct hci_dev *hdev,
+                                       struct hci_ev_le_advertising_info *ev)
+ {
+       struct adv_entry *entry;
+       if (!is_connectable_adv(ev->evt_type))
+               return -EINVAL;
+       /* Only new entries should be added to adv_entries. So, if
+        * bdaddr was found, don't add it. */
+       if (hci_find_adv_entry(hdev, &ev->bdaddr))
+               return 0;
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry)
+               return -ENOMEM;
+       bacpy(&entry->bdaddr, &ev->bdaddr);
+       entry->bdaddr_type = ev->bdaddr_type;
+       list_add(&entry->list, &hdev->adv_entries);
+       BT_DBG("%s adv entry added: address %s type %u", hdev->name,
+                               batostr(&entry->bdaddr), entry->bdaddr_type);
+       return 0;
+ }
+ static struct crypto_blkcipher *alloc_cypher(void)
+ {
+       if (enable_smp)
+               return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+       return ERR_PTR(-ENOTSUPP);
+ }
  /* Register HCI device */
  int hci_register_dev(struct hci_dev *hdev)
  {
  
        INIT_LIST_HEAD(&hdev->remote_oob_data);
  
+       INIT_LIST_HEAD(&hdev->adv_entries);
+       setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
+                                               (unsigned long) hdev);
        INIT_WORK(&hdev->power_on, hci_power_on);
        INIT_WORK(&hdev->power_off, hci_power_off);
        setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
        if (!hdev->workqueue)
                goto nomem;
  
+       hdev->tfm = alloc_cypher();
+       if (IS_ERR(hdev->tfm))
+               BT_INFO("Failed to load transform for ecb(aes): %ld",
+                                                       PTR_ERR(hdev->tfm));
        hci_register_sysfs(hdev);
  
        hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@@ -1330,6 -1513,9 +1513,9 @@@ int hci_unregister_dev(struct hci_dev *
                                        !test_bit(HCI_SETUP, &hdev->flags))
                mgmt_index_removed(hdev->id);
  
+       if (!IS_ERR(hdev->tfm))
+               crypto_free_blkcipher(hdev->tfm);
        hci_notify(hdev, HCI_DEV_UNREG);
  
        if (hdev->rfkill) {
        hci_unregister_sysfs(hdev);
  
        hci_del_off_timer(hdev);
+       del_timer(&hdev->adv_timer);
  
        destroy_workqueue(hdev->workqueue);
  
        hci_uuids_clear(hdev);
        hci_link_keys_clear(hdev);
        hci_remote_oob_data_clear(hdev);
+       hci_adv_entries_clear(hdev);
        hci_dev_unlock_bh(hdev);
  
        __hci_dev_put(hdev);
@@@ -1519,7 -1707,7 +1707,7 @@@ int hci_recv_fragment(struct hci_dev *h
  
                data += (count - rem);
                count = rem;
 -      };
 +      }
  
        return rem;
  }
@@@ -1554,7 -1742,7 +1742,7 @@@ int hci_recv_stream_fragment(struct hci
  
                data += (count - rem);
                count = rem;
 -      };
 +      }
  
        return rem;
  }
@@@ -1891,7 -2079,7 +2079,7 @@@ static inline void hci_sched_acl(struc
                while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
                        BT_DBG("skb %p len %d", skb, skb->len);
  
-                       hci_conn_enter_active_mode(conn);
+                       hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
  
                        hci_send_frame(skb);
                        hdev->acl_last_tx = jiffies;
@@@ -2030,7 -2218,7 +2218,7 @@@ static inline void hci_acldata_packet(s
        if (conn) {
                register struct hci_proto *hp;
  
-               hci_conn_enter_active_mode(conn);
+               hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
  
                /* Send to upper protocol */
                hp = hci_proto[HCI_PROTO_L2CAP];
@@@ -2164,3 -2352,6 +2352,6 @@@ static void hci_cmd_task(unsigned long 
                }
        }
  }
+ module_param(enable_smp, bool, 0644);
+ MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
diff --combined net/netlink/af_netlink.c
@@@ -1659,10 -1659,13 +1659,10 @@@ static int netlink_dump(struct sock *sk
  {
        struct netlink_sock *nlk = nlk_sk(sk);
        struct netlink_callback *cb;
 -      struct sk_buff *skb;
 +      struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
        int len, err = -ENOBUFS;
 -
 -      skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
 -      if (!skb)
 -              goto errout;
 +      int alloc_size;
  
        mutex_lock(nlk->cb_mutex);
  
                goto errout_skb;
        }
  
 +      alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
 +
 +      skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL);
 +      if (!skb)
 +              goto errout_skb;
 +
        len = cb->dump(skb, cb);
  
        if (len > 0) {
        if (!nlh)
                goto errout_skb;
  
+       nl_dump_check_consistent(cb, nlh);
        memcpy(nlmsg_data(nlh), &len, sizeof(len));
  
        if (sk_filter(sk, skb))
  errout_skb:
        mutex_unlock(nlk->cb_mutex);
        kfree_skb(skb);
 -errout:
        return err;
  }
  
@@@ -1723,8 -1723,7 +1725,8 @@@ int netlink_dump_start(struct sock *ssk
                       const struct nlmsghdr *nlh,
                       int (*dump)(struct sk_buff *skb,
                                   struct netlink_callback *),
 -                     int (*done)(struct netlink_callback *))
 +                     int (*done)(struct netlink_callback *),
 +                     u16 min_dump_alloc)
  {
        struct netlink_callback *cb;
        struct sock *sk;
        cb->dump = dump;
        cb->done = done;
        cb->nlh = nlh;
 +      cb->min_dump_alloc = min_dump_alloc;
        atomic_inc(&skb->users);
        cb->skb = skb;