static int p54_beacon_update(struct p54_common *priv, struct ieee80211_vif *vif) { struct ieee80211_tx_control control = { }; struct sk_buff *beacon; int ret; beacon = ieee80211_beacon_get(priv->hw, vif); if (!beacon) return -ENOMEM; ret = p54_beacon_format_ie_tim(beacon); if (ret) return ret; /* * During operation, the firmware takes care of beaconing. * The driver only needs to upload a new beacon template, once * the template was changed by the stack or userspace. * * LMAC API 3.2.2 also specifies that the driver does not need * to cancel the old beacon template by hand, instead the firmware * will release the previous one through the feedback mechanism. */ p54_tx_80211(priv->hw, &control, beacon); priv->tsf_high32 = 0; priv->tsf_low32 = 0; return 0; }
static int iwlagn_update_beacon(struct iwl_priv *priv, struct ieee80211_vif *vif) { lockdep_assert_held(&priv->mutex); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); if (!priv->beacon_skb) return -ENOMEM; return iwlagn_send_beacon_cmd(priv); }
static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { if (changed & BSS_CHANGED_ERP_PREAMBLE) mwl_fwcmd_set_radio_preamble(hw, vif->bss_conf.use_short_preamble); if (changed & BSS_CHANGED_BASIC_RATES) { int idx; int rate; /* Use lowest supported basic rate for multicasts * and management frames (such as probe responses -- * beacons will always go out at 1 Mb/s). */ idx = ffs(vif->bss_conf.basic_rates); if (idx) idx--; if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) rate = mwl_rates_24[idx].hw_value; else rate = mwl_rates_50[idx].hw_value; mwl_fwcmd_use_fixed_rate(hw, rate, rate); } if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { struct sk_buff *skb; if ((info->ssid[0] != '\0') && (info->ssid_len != 0) && (!info->hidden_ssid)) mwl_fwcmd_broadcast_ssid_enable(hw, vif, true); else mwl_fwcmd_broadcast_ssid_enable(hw, vif, false); skb = ieee80211_beacon_get(hw, vif); if (skb) { mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len); dev_kfree_skb_any(skb); } } if (changed & BSS_CHANGED_BEACON_ENABLED) mwl_fwcmd_bss_start(hw, vif, info->enable_beacon); }
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) { struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; struct sk_buff *beacon; u8 *tx_fhdr; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); /* FIXME: Handle BMISS */ if (beacon_pending != 0) { priv->bmiss_cnt++; return; } spin_lock_bh(&priv->beacon_lock); if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); return; } /* Get a new beacon */ beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) beacon->data; priv->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); } tx_ctl.type = ATH9K_HTC_NORMAL; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); spin_unlock_bh(&priv->beacon_lock); }
int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif) { struct sk_buff *beacon; beacon = ieee80211_beacon_get(priv->hw, vif); if (!beacon) return -ENOMEM; if (vnt_beacon_xmit(priv, beacon)) { ieee80211_free_txskb(priv->hw, beacon); return -ENODEV; } return 0; }
static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, struct ieee80211_vif *vif) { struct ieee80211_hw *hw = arg; struct sk_buff *skb; struct ieee80211_tx_info *info; if (vif->type != IEEE80211_IF_TYPE_AP) return; skb = ieee80211_beacon_get(hw, vif); if (skb == NULL) return; info = IEEE80211_SKB_CB(skb); mac80211_hwsim_monitor_rx(hw, skb); mac80211_hwsim_tx_frame(hw, skb); dev_kfree_skb(skb); }
static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; struct ieee80211_hdr *hdr = NULL; struct ieee80211_tx_info *info = NULL; struct sk_buff *pskb = NULL; struct rtl_tx_desc *pdesc = NULL; unsigned int queue_index; u8 temp_one = 1; ring = &rtlpci->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); if (pskb) kfree_skb(pskb); /*NB: the beacon data buffer must be 32-bit aligned. */ pskb = ieee80211_beacon_get(hw, mac->vif); if (pskb == NULL) return; hdr = (struct ieee80211_hdr *)(pskb->data); info = IEEE80211_SKB_CB(pskb); queue_index = BEACON_QUEUE; pdesc = &ring->desc[0]; rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, info, pskb, queue_index); __skb_queue_tail(&ring->queue, pskb); rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, HW_DESC_OWN, (u8 *)&temp_one); return; }
static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_buf *bf; struct ath_vif *avp; struct sk_buff *skb; struct ath_txq *cabq; struct ieee80211_tx_info *info; int cabq_depth; ath9k_reset_beacon_status(sc); avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active) return NULL; /* Release the old beacon first */ bf = avp->av_bcbuf; skb = bf->bf_mpdu; if (skb) { dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; } /* Get a new beacon from mac80211 */ skb = ieee80211_beacon_get(hw, vif); bf->bf_mpdu = skb; if (skb == NULL) return NULL; ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = avp->tsf_adjust; info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { /* * TODO: make sure the seq# gets assigned properly (vs. other * TX frames) */ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; sc->tx.seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); } bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; ath_err(common, "dma_mapping_error on beaconing\n"); return NULL; } skb = ieee80211_get_buffered_bc(hw, vif); /* * if the CABQ traffic from previous DTIM is pending and the current * beacon is also a DTIM. * 1) if there is only one vif let the cab traffic continue. * 2) if there are more than one vif and we are using staggered * beacons, then drain the cabq by dropping all the frames in * the cabq so that the current vifs cab traffic can be scheduled. */ spin_lock_bh(&cabq->axq_lock); cabq_depth = cabq->axq_depth; spin_unlock_bh(&cabq->axq_lock); if (skb && cabq_depth) { if (sc->nvifs > 1) { ath_dbg(common, BEACON, "Flushing previous cabq traffic\n"); ath_draintxq(sc, cabq, false); } } ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx); while (skb) { ath_tx_cabq(hw, skb); skb = ieee80211_get_buffered_bc(hw, vif); } return bf; }
static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, int slot) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ieee80211_vif *vif; struct ath9k_htc_vif *avp; struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl *tx_ctl; struct ieee80211_tx_info *info; struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; u8 *tx_fhdr; int ret; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); spin_lock_bh(&priv->beacon_lock); vif = priv->cur_beacon_conf.bslot[slot]; avp = (struct ath9k_htc_vif *)vif->drv_priv; if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); return; } /* Get a new beacon */ beacon = ieee80211_beacon_get(priv->hw, vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } /* * Update the TSF adjust value here, the HW will * add this value for every beacon. */ mgmt = (struct ieee80211_mgmt *)beacon->data; mgmt->u.beacon.timestamp = avp->tsfadjust; info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) beacon->data; avp->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); } tx_ctl = HTC_SKB_CB(beacon); memset(tx_ctl, 0, sizeof(*tx_ctl)); tx_ctl->type = ATH9K_HTC_BEACON; tx_ctl->epid = priv->beacon_ep; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); ret = htc_send(priv->htc, beacon); if (ret != 0) { if (ret == -ENOMEM) { ath_dbg(common, BSTUCK, "Failed to send beacon, no free TX buffer\n"); } dev_kfree_skb_any(beacon); } spin_unlock_bh(&priv->beacon_lock); }
static int wl1271_op_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) { struct wl1271 *wl = hw->priv; struct sk_buff *beacon; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", conf->bssid); wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, conf->ssid_len); mutex_lock(&wl->mutex); ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; memcpy(wl->bssid, conf->bssid, ETH_ALEN); ret = wl1271_cmd_build_null_data(wl); if (ret < 0) goto out_sleep; wl->ssid_len = conf->ssid_len; if (wl->ssid_len) memcpy(wl->ssid, conf->ssid, wl->ssid_len); if (wl->bss_type != BSS_TYPE_IBSS) { ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1); if (ret < 0) goto out_sleep; } if (conf->changed & IEEE80211_IFCC_BEACON) { beacon = ieee80211_beacon_get(hw, vif); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, beacon->data, beacon->len); if (ret < 0) { dev_kfree_skb(beacon); goto out_sleep; } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, beacon->data, beacon->len); dev_kfree_skb(beacon); if (ret < 0) goto out_sleep; ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); if (ret < 0) goto out_sleep; } out_sleep: wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); return ret; }
/* * Generate beacon frame and queue cab data for a vap. * * Updates the contents of the beacon frame. It is assumed that the buffer for * the beacon frame has been allocated in the ATH object, and simply needs to * be filled for this cycle. Also, any CAB (crap after beacon?) traffic will * be added to the beacon frame at this point. */ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) { struct ath_buf *bf; struct ath_vap *avp; struct sk_buff *skb; struct ath_txq *cabq; struct ieee80211_tx_info *info; int cabq_depth; avp = sc->sc_vaps[if_id]; ASSERT(avp); cabq = sc->sc_cabq; if (avp->av_bcbuf == NULL) { DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", __func__, avp, avp->av_bcbuf); return NULL; } bf = avp->av_bcbuf; skb = (struct sk_buff *)bf->bf_mpdu; if (skb) { pci_unmap_single(sc->pdev, bf->bf_dmacontext, skb_end_pointer(skb) - skb->head, PCI_DMA_TODEVICE); } skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); bf->bf_mpdu = skb; if (skb == NULL) return NULL; info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { /* * TODO: make sure the seq# gets assigned properly (vs. other * TX frames) */ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; sc->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); } bf->bf_buf_addr = bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, skb_end_pointer(skb) - skb->head, PCI_DMA_TODEVICE); skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); /* * if the CABQ traffic from previous DTIM is pending and the current * beacon is also a DTIM. * 1) if there is only one vap let the cab traffic continue. * 2) if there are more than one vap and we are using staggered * beacons, then drain the cabq by dropping all the frames in * the cabq so that the current vaps cab traffic can be scheduled. */ spin_lock_bh(&cabq->axq_lock); cabq_depth = cabq->axq_depth; spin_unlock_bh(&cabq->axq_lock); if (skb && cabq_depth) { /* * Unlock the cabq lock as ath_tx_draintxq acquires * the lock again which is a common function and that * acquires txq lock inside. */ if (sc->sc_nvaps > 1) { ath_tx_draintxq(sc, cabq, false); DPRINTF(sc, ATH_DBG_BEACON, "%s: flush previous cabq traffic\n", __func__); } } /* Construct tx descriptor. */ ath_beacon_setup(sc, avp, bf); /* * Enable the CAB queue before the beacon queue to * insure cab frames are triggered by this beacon. */ while (skb) { ath_tx_cabq(sc, skb); skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); } return bf; }