@@ -951,15 +951,46 @@ 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_UNSPECIFIED)
+ return;
+
+ /*
+ * Send out buffered broad- and multicast frames.
+ */
+ if (mac->vif->type == NL80211_IFTYPE_AP) {
+ dev_dbg_f_limit(zd_mac_dev(mac), "buffered_bc tx\n");
+ skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+ while (skb) {
+ zd_op_tx(mac->hw, skb);
+ skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+ }
+ }
+
+ /*
+ * 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;
struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
- if (int_status & INT_CFG_NEXT_BCN)
+ if (int_status & INT_CFG_NEXT_BCN) {
dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
- else
+ zd_beacon_done(mac);
+ } else
dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
zd_chip_enable_hwint(&mac->chip);
@@ -1186,7 +1217,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) |