diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-06-11 12:48:06 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-19 21:49:19 +0200 |
commit | 3ae07d39ea81440768427e7786c5422f3af38a94 (patch) | |
tree | 1a1da597c444c3cc3d8985e634f76bd341b8a6d7 /drivers/net/wireless/ath/ath9k/beacon.c | |
parent | ath9k: Store current offchannel duration (diff) | |
download | linux-3ae07d39ea81440768427e7786c5422f3af38a94.tar.xz linux-3ae07d39ea81440768427e7786c5422f3af38a94.zip |
ath9k: Add p2p go NoA attribute
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 5b1689cf029a..85a40d749e20 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -108,6 +108,40 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); } +static void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp, + struct sk_buff *skb) +{ + static const u8 noa_ie_hdr[] = { + WLAN_EID_VENDOR_SPECIFIC, /* type */ + 0, /* length */ + 0x50, 0x6f, 0x9a, /* WFA OUI */ + 0x09, /* P2P subtype */ + 0x0c, /* Notice of Absence */ + 0x00, /* LSB of little-endian len */ + 0x00, /* MSB of little-endian len */ + }; + + struct ieee80211_p2p_noa_attr *noa; + int noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc); + u8 *hdr; + + if (!avp->offchannel_duration) + return; + + hdr = skb_put(skb, sizeof(noa_ie_hdr)); + memcpy(hdr, noa_ie_hdr, sizeof(noa_ie_hdr)); + hdr[1] = sizeof(noa_ie_hdr) + noa_len - 2; + hdr[7] = noa_len; + + noa = (void *) skb_put(skb, noa_len); + memset(noa, 0, noa_len); + + noa->index = avp->noa_index; + noa->desc[0].count = 1; + noa->desc[0].duration = cpu_to_le32(avp->offchannel_duration); + noa->desc[0].start_time = cpu_to_le32(avp->offchannel_start); +} + static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -155,6 +189,9 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); } + if (vif->p2p) + ath9k_beacon_add_noa(sc, avp, skb); + 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))) { |