Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Feb 2013 18:55:44 +0000 (13:55 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Feb 2013 18:55:44 +0000 (13:55 -0500)
13 files changed:
drivers/bcma/bcma_private.h
drivers/bcma/driver_gpio.c
drivers/bcma/main.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/rtlwifi/base.c
drivers/ssb/driver_gpio.c
drivers/ssb/main.c
drivers/ssb/ssb_private.h
net/bluetooth/hci_conn.c
net/bluetooth/smp.c

index 19e3fbfd5757368790980dfec756135e981b0eaf..cb0c4548857282c3bc6b38cfa836ad9474370604 100644 (file)
@@ -94,11 +94,16 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #ifdef CONFIG_BCMA_DRIVER_GPIO
 /* driver_gpio.c */
 int bcma_gpio_init(struct bcma_drv_cc *cc);
+int bcma_gpio_unregister(struct bcma_drv_cc *cc);
 #else
 static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
 {
        return -ENOTSUPP;
 }
+static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return 0;
+}
 #endif /* CONFIG_BCMA_DRIVER_GPIO */
 
 #endif
index 9a6f585da2d9f21d232ac4b58cc3a36b442d9b36..71f755c06fc6637497665f31d15f6432d49c3075 100644 (file)
@@ -96,3 +96,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
 
        return gpiochip_add(chip);
 }
+
+int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return gpiochip_remove(&cc->gpio);
+}
index 4a92f647b58bdef4fa28f28b772d960036469c78..324f9debda88007ac096320dae35340db99e3fe5 100644 (file)
@@ -268,6 +268,13 @@ int bcma_bus_register(struct bcma_bus *bus)
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
        struct bcma_device *cores[3];
+       int err;
+
+       err = bcma_gpio_unregister(&bus->drv_cc);
+       if (err == -EBUSY)
+               bcma_err(bus, "Some GPIOs are still in use.\n");
+       else if (err)
+               bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
 
        cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
index 0f71d1d4339dc38ccfdd89428fdc4a62bb5b7bd9..e5fd20994bec256df4ec88f96182006e54ada0d6 100644 (file)
@@ -36,6 +36,7 @@
 #include "debug.h"
 
 #define N_TX_QUEUES    4 /* #tx queues on mac80211<->driver interface */
+#define BRCMS_FLUSH_TIMEOUT    500 /* msec */
 
 /* Flags we support */
 #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
@@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 }
 
+static bool brcms_tx_flush_completed(struct brcms_info *wl)
+{
+       bool result;
+
+       spin_lock_bh(&wl->lock);
+       result = brcms_c_tx_flush_completed(wl->wlc);
+       spin_unlock_bh(&wl->lock);
+       return result;
+}
+
 static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct brcms_info *wl = hw->priv;
+       int ret;
 
        no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
 
-       /* wait for packet queue and dma fifos to run empty */
-       spin_lock_bh(&wl->lock);
-       brcms_c_wait_for_tx_completion(wl->wlc, drop);
-       spin_unlock_bh(&wl->lock);
+       ret = wait_event_timeout(wl->tx_flush_wq,
+                                brcms_tx_flush_completed(wl),
+                                msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));
+
+       brcms_dbg_mac80211(wl->wlc->hw->d11core,
+                          "ret=%d\n", jiffies_to_msecs(ret));
 }
 
 static const struct ieee80211_ops brcms_ops = {
@@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data)
 
  done:
        spin_unlock_bh(&wl->lock);
+       wake_up(&wl->tx_flush_wq);
 }
 
 /*
@@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
 
        atomic_set(&wl->callbacks, 0);
 
+       init_waitqueue_head(&wl->tx_flush_wq);
+
        /* setup the bottom half handler */
        tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
 
@@ -1609,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
        spin_lock_bh(&wl->lock);
        return blocked;
 }
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void brcms_msleep(struct brcms_info *wl, uint ms)
-{
-       spin_unlock_bh(&wl->lock);
-       msleep(ms);
-       spin_lock_bh(&wl->lock);
-}
index 9358bd5ebd35d016058d1238d11aca6880fdae19..947ccacf43e6f498dacfaceed5c3853c00c99d96 100644 (file)
@@ -68,6 +68,8 @@ struct brcms_info {
        spinlock_t lock;        /* per-device perimeter lock */
        spinlock_t isr_lock;    /* per-device ISR synchronization lock */
 
+       /* tx flush */
+       wait_queue_head_t tx_flush_wq;
 
        /* timer related fields */
        atomic_t callbacks;     /* # outstanding callback functions */
@@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
 extern void brcms_free_timer(struct brcms_timer *timer);
 extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
 extern bool brcms_del_timer(struct brcms_timer *timer);
-extern void brcms_msleep(struct brcms_info *wl, uint ms);
 extern void brcms_dpc(unsigned long data);
 extern void brcms_timer(struct brcms_timer *t);
 extern void brcms_fatal_error(struct brcms_info *wl);
index 9f3d7e9f3bb5a7c04bb6445d65ee73936a244f2c..8b5839008af32a11afef6d4042db67a0d8a9c16d 100644 (file)
@@ -7511,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
        return wlc->band->bandunit;
 }
 
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc)
 {
-       int timeout = 20;
        int i;
 
        /* Kick DMA to send any pending AMPDU */
        for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
                if (wlc->hw->di[i])
-                       dma_txflush(wlc->hw->di[i]);
+                       dma_kick_tx(wlc->hw->di[i]);
 
-       /* wait for queue and DMA fifos to run dry */
-       while (brcms_txpktpendtot(wlc) > 0) {
-               brcms_msleep(wlc->wl, 1);
-
-               if (--timeout == 0)
-                       break;
-       }
-
-       WARN_ON_ONCE(timeout == 0);
+       return !brcms_txpktpendtot(wlc);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
index 4fb2834f4e6483f7c9321666c75598e6f9fa21fd..b0f14b7b8616e63ed5f2ed954ff47eddab7ff0d0 100644 (file)
@@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
 extern void brcms_c_scan_start(struct brcms_c_info *wlc);
 extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
 extern int brcms_c_get_curband(struct brcms_c_info *wlc);
-extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
-                                          bool drop);
 extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
 extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
 extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
@@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
 extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
 extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
+extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
 
 #endif                         /* _BRCM_PUB_H_ */
index 4494d130b37cb0d0ad585eea5142e0c312c86b26..0f8b05185edaeacb6ef686e5e5a1ca0151866916 100644 (file)
@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                                         is_tx ? "Tx" : "Rx");
 
                                if (is_tx) {
-                                       rtl_lps_leave(hw);
+                                       schedule_work(&rtlpriv->
+                                                     works.lps_leave_work);
                                        ppsc->last_delaylps_stamp_jiffies =
                                            jiffies;
                                }
@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                }
        } else if (ETH_P_ARP == ether_type) {
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                         "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
 
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
index 97ac0a38e3d0c7277aaab702078d2878db20f1cd..eb2753008ef0550b6c3bfeda984ca9dfe47d26bd 100644 (file)
@@ -174,3 +174,15 @@ int ssb_gpio_init(struct ssb_bus *bus)
 
        return -1;
 }
+
+int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       if (ssb_chipco_available(&bus->chipco) ||
+           ssb_extif_available(&bus->extif)) {
+               return gpiochip_remove(&bus->gpio);
+       } else {
+               SSB_WARN_ON(1);
+       }
+
+       return -1;
+}
index 772ad9b5c304fc986b459c4f4c6c5513e70ecd16..24dc331b4701efd796381882e635c6ef791c45cf 100644 (file)
@@ -443,6 +443,15 @@ static void ssb_devices_unregister(struct ssb_bus *bus)
 
 void ssb_bus_unregister(struct ssb_bus *bus)
 {
+       int err;
+
+       err = ssb_gpio_unregister(bus);
+       if (err == -EBUSY)
+               ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n");
+       else if (err)
+               ssb_dprintk(KERN_ERR PFX
+                           "Can not unregister GPIO driver: %i\n", err);
+
        ssb_buses_lock();
        ssb_devices_unregister(bus);
        list_del(&bus->list);
index 6c10b66c796cf7ee23ae3e9334086034198e911c..da38305a2d22a2c24de7b4563da7ed0daa7354a0 100644 (file)
@@ -252,11 +252,16 @@ static inline void ssb_extif_init(struct ssb_extif *extif)
 
 #ifdef CONFIG_SSB_DRIVER_GPIO
 extern int ssb_gpio_init(struct ssb_bus *bus);
+extern int ssb_gpio_unregister(struct ssb_bus *bus);
 #else /* CONFIG_SSB_DRIVER_GPIO */
 static inline int ssb_gpio_init(struct ssb_bus *bus)
 {
        return -ENOTSUPP;
 }
+static inline int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       return 0;
+}
 #endif /* CONFIG_SSB_DRIVER_GPIO */
 
 #endif /* LINUX_SSB_PRIVATE_H_ */
index 25bfce0666ebff70258019ddb1bba9b6f1eca967..4925a02ae7e4db7df4d4cdfc972e68375743861c 100644 (file)
@@ -249,12 +249,12 @@ static void hci_conn_disconnect(struct hci_conn *conn)
        __u8 reason = hci_proto_disconn_ind(conn);
 
        switch (conn->type) {
-       case ACL_LINK:
-               hci_acl_disconn(conn, reason);
-               break;
        case AMP_LINK:
                hci_amp_disconn(conn, reason);
                break;
+       default:
+               hci_acl_disconn(conn, reason);
+               break;
        }
 }
 
index 68a9587c96945cdd3264cc310b68b7be95cfd953..5abefb12891d5144f97d1feacb0803937b0c9765 100644 (file)
@@ -859,6 +859,19 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
        skb_pull(skb, sizeof(code));
 
+       /*
+        * The SMP context must be initialized for all other PDUs except
+        * pairing and security requests. If we get any other PDU when
+        * not initialized simply disconnect (done if this function
+        * returns an error).
+        */
+       if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
+           !conn->smp_chan) {
+               BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
+               kfree_skb(skb);
+               return -ENOTSUPP;
+       }
+
        switch (code) {
        case SMP_CMD_PAIRING_REQ:
                reason = smp_cmd_pairing_req(conn, skb);