root/drivers/net/wireless/ath/ath10k/p2p.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ath10k_p2p_noa_ie_fill
  2. ath10k_p2p_noa_ie_len_compute
  3. ath10k_p2p_noa_ie_assign
  4. __ath10k_p2p_noa_update
  5. ath10k_p2p_noa_update
  6. ath10k_p2p_noa_update_vdev_iter
  7. ath10k_p2p_noa_update_by_vdev_id

   1 // SPDX-License-Identifier: ISC
   2 /*
   3  * Copyright (c) 2015 Qualcomm Atheros, Inc.
   4  */
   5 
   6 #include "core.h"
   7 #include "wmi.h"
   8 #include "mac.h"
   9 #include "p2p.h"
  10 
  11 static void ath10k_p2p_noa_ie_fill(u8 *data, size_t len,
  12                                    const struct wmi_p2p_noa_info *noa)
  13 {
  14         struct ieee80211_p2p_noa_attr *noa_attr;
  15         u8  ctwindow_oppps = noa->ctwindow_oppps;
  16         u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET;
  17         bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT);
  18         __le16 *noa_attr_len;
  19         u16 attr_len;
  20         u8 noa_descriptors = noa->num_descriptors;
  21         int i;
  22 
  23         /* P2P IE */
  24         data[0] = WLAN_EID_VENDOR_SPECIFIC;
  25         data[1] = len - 2;
  26         data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
  27         data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
  28         data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
  29         data[5] = WLAN_OUI_TYPE_WFA_P2P;
  30 
  31         /* NOA ATTR */
  32         data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
  33         noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
  34         noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
  35 
  36         noa_attr->index = noa->index;
  37         noa_attr->oppps_ctwindow = ctwindow;
  38         if (oppps)
  39                 noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
  40 
  41         for (i = 0; i < noa_descriptors; i++) {
  42                 noa_attr->desc[i].count =
  43                         __le32_to_cpu(noa->descriptors[i].type_count);
  44                 noa_attr->desc[i].duration = noa->descriptors[i].duration;
  45                 noa_attr->desc[i].interval = noa->descriptors[i].interval;
  46                 noa_attr->desc[i].start_time = noa->descriptors[i].start_time;
  47         }
  48 
  49         attr_len = 2; /* index + oppps_ctwindow */
  50         attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
  51         *noa_attr_len = __cpu_to_le16(attr_len);
  52 }
  53 
  54 static size_t ath10k_p2p_noa_ie_len_compute(const struct wmi_p2p_noa_info *noa)
  55 {
  56         size_t len = 0;
  57 
  58         if (!noa->num_descriptors &&
  59             !(noa->ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT))
  60                 return 0;
  61 
  62         len += 1 + 1 + 4; /* EID + len + OUI */
  63         len += 1 + 2; /* noa attr + attr len */
  64         len += 1 + 1; /* index + oppps_ctwindow */
  65         len += noa->num_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
  66 
  67         return len;
  68 }
  69 
  70 static void ath10k_p2p_noa_ie_assign(struct ath10k_vif *arvif, void *ie,
  71                                      size_t len)
  72 {
  73         struct ath10k *ar = arvif->ar;
  74 
  75         lockdep_assert_held(&ar->data_lock);
  76 
  77         kfree(arvif->u.ap.noa_data);
  78 
  79         arvif->u.ap.noa_data = ie;
  80         arvif->u.ap.noa_len = len;
  81 }
  82 
  83 static void __ath10k_p2p_noa_update(struct ath10k_vif *arvif,
  84                                     const struct wmi_p2p_noa_info *noa)
  85 {
  86         struct ath10k *ar = arvif->ar;
  87         void *ie;
  88         size_t len;
  89 
  90         lockdep_assert_held(&ar->data_lock);
  91 
  92         ath10k_p2p_noa_ie_assign(arvif, NULL, 0);
  93 
  94         len = ath10k_p2p_noa_ie_len_compute(noa);
  95         if (!len)
  96                 return;
  97 
  98         ie = kmalloc(len, GFP_ATOMIC);
  99         if (!ie)
 100                 return;
 101 
 102         ath10k_p2p_noa_ie_fill(ie, len, noa);
 103         ath10k_p2p_noa_ie_assign(arvif, ie, len);
 104 }
 105 
 106 void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
 107                            const struct wmi_p2p_noa_info *noa)
 108 {
 109         struct ath10k *ar = arvif->ar;
 110 
 111         spin_lock_bh(&ar->data_lock);
 112         __ath10k_p2p_noa_update(arvif, noa);
 113         spin_unlock_bh(&ar->data_lock);
 114 }
 115 
 116 struct ath10k_p2p_noa_arg {
 117         u32 vdev_id;
 118         const struct wmi_p2p_noa_info *noa;
 119 };
 120 
 121 static void ath10k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
 122                                             struct ieee80211_vif *vif)
 123 {
 124         struct ath10k_vif *arvif = (void *)vif->drv_priv;
 125         struct ath10k_p2p_noa_arg *arg = data;
 126 
 127         if (arvif->vdev_id != arg->vdev_id)
 128                 return;
 129 
 130         ath10k_p2p_noa_update(arvif, arg->noa);
 131 }
 132 
 133 void ath10k_p2p_noa_update_by_vdev_id(struct ath10k *ar, u32 vdev_id,
 134                                       const struct wmi_p2p_noa_info *noa)
 135 {
 136         struct ath10k_p2p_noa_arg arg = {
 137                 .vdev_id = vdev_id,
 138                 .noa = noa,
 139         };
 140 
 141         ieee80211_iterate_active_interfaces_atomic(ar->hw,
 142                                                    IEEE80211_IFACE_ITER_NORMAL,
 143                                                    ath10k_p2p_noa_update_vdev_iter,
 144                                                    &arg);
 145 }

/* [<][>][^][v][top][bottom][index][help] */