zd1211rw: implement beacon fetching and handling ieee80211_get_buffered_bc()
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>
Mon, 31 Jan 2011 18:48:35 +0000 (20:48 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 4 Feb 2011 21:29:49 +0000 (16:29 -0500)
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/zd1211rw/zd_mac.c

index 1bd275bc6084312d4f24909236f255df006b4305..49ab3c35710076647c85b69e9dc33c888ab2d822 100644 (file)
@@ -938,6 +938,34 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
        return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
+static void zd_beacon_done(struct zd_mac *mac)
+{
+       struct sk_buff *skb, *beacon;
+
+       if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
+               return;
+
+       /*
+        * Send out buffered broad- and multicast frames.
+        */
+       while (!ieee80211_queue_stopped(mac->hw, 0)) {
+               skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+               if (!skb)
+                       break;
+               zd_op_tx(mac->hw, skb);
+       }
+
+       /*
+        * Fetch next beacon so that tim_count is updated.
+        */
+       beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+       if (!beacon)
+               return;
+
+       zd_mac_config_beacon(mac->hw, beacon);
+       kfree_skb(beacon);
+}
+
 static void zd_process_intr(struct work_struct *work)
 {
        u16 int_status;
@@ -948,10 +976,12 @@ static void zd_process_intr(struct work_struct *work)
        int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
        spin_unlock_irqrestore(&mac->lock, flags);
 
-       if (int_status & INT_CFG_NEXT_BCN)
-               dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
-       else
+       if (int_status & INT_CFG_NEXT_BCN) {
+               /*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
+               zd_beacon_done(mac);
+       } else {
                dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
+       }
 
        zd_chip_enable_hwint(&mac->chip);
 }
@@ -1135,7 +1165,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
 
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-                   IEEE80211_HW_SIGNAL_UNSPEC;
+                   IEEE80211_HW_SIGNAL_UNSPEC |
+                   IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_MESH_POINT) |