aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-02-26 07:23:17 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2015-03-07 02:57:35 -0500
commit6a94888f173f10d24d69d25fb99ab50bf750e0e3 (patch)
treeeefbd4fb998a2c089106b64d3b47410bffdda8da
parentbc657a36b8999c285a11e1e0abcdca0b18149948 (diff)
ath10k: refactor p2p noa code
Some files are getting bloated and it makes sense to split some of the code into separate files. Do so with the P2P NoA code and prepare it for reuse. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.c124
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.h26
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c91
4 files changed, 156 insertions, 88 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index f4dbb3e93bf8..92a1e097e436 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -10,7 +10,8 @@ ath10k_core-y += mac.o \
10 wmi.o \ 10 wmi.o \
11 wmi-tlv.o \ 11 wmi-tlv.o \
12 bmi.o \ 12 bmi.o \
13 hw.o 13 hw.o \
14 p2p.o
14 15
15ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o 16ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
16ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o 17ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c
new file mode 100644
index 000000000000..79d7485e21cd
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/p2p.c
@@ -0,0 +1,124 @@
1/*
2 * Copyright (c) 2015 Qualcomm Atheros, Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "wmi.h"
19#include "p2p.h"
20
21static void ath10k_p2p_noa_ie_fill(u8 *data, size_t len,
22 const struct wmi_p2p_noa_info *noa)
23{
24 struct ieee80211_p2p_noa_attr *noa_attr;
25 u8 ctwindow_oppps = noa->ctwindow_oppps;
26 u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET;
27 bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT);
28 __le16 *noa_attr_len;
29 u16 attr_len;
30 u8 noa_descriptors = noa->num_descriptors;
31 int i;
32
33 /* P2P IE */
34 data[0] = WLAN_EID_VENDOR_SPECIFIC;
35 data[1] = len - 2;
36 data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
37 data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
38 data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
39 data[5] = WLAN_OUI_TYPE_WFA_P2P;
40
41 /* NOA ATTR */
42 data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
43 noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
44 noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
45
46 noa_attr->index = noa->index;
47 noa_attr->oppps_ctwindow = ctwindow;
48 if (oppps)
49 noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
50
51 for (i = 0; i < noa_descriptors; i++) {
52 noa_attr->desc[i].count =
53 __le32_to_cpu(noa->descriptors[i].type_count);
54 noa_attr->desc[i].duration = noa->descriptors[i].duration;
55 noa_attr->desc[i].interval = noa->descriptors[i].interval;
56 noa_attr->desc[i].start_time = noa->descriptors[i].start_time;
57 }
58
59 attr_len = 2; /* index + oppps_ctwindow */
60 attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
61 *noa_attr_len = __cpu_to_le16(attr_len);
62}
63
64static size_t ath10k_p2p_noa_ie_len_compute(const struct wmi_p2p_noa_info *noa)
65{
66 size_t len = 0;
67
68 if (!noa->num_descriptors &&
69 !(noa->ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT))
70 return 0;
71
72 len += 1 + 1 + 4; /* EID + len + OUI */
73 len += 1 + 2; /* noa attr + attr len */
74 len += 1 + 1; /* index + oppps_ctwindow */
75 len += noa->num_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
76
77 return len;
78}
79
80static void ath10k_p2p_noa_ie_assign(struct ath10k_vif *arvif, void *ie,
81 size_t len)
82{
83 struct ath10k *ar = arvif->ar;
84
85 lockdep_assert_held(&ar->data_lock);
86
87 kfree(arvif->u.ap.noa_data);
88
89 arvif->u.ap.noa_data = ie;
90 arvif->u.ap.noa_len = len;
91}
92
93static void __ath10k_p2p_noa_update(struct ath10k_vif *arvif,
94 const struct wmi_p2p_noa_info *noa)
95{
96 struct ath10k *ar = arvif->ar;
97 void *ie;
98 size_t len;
99
100 lockdep_assert_held(&ar->data_lock);
101
102 ath10k_p2p_noa_ie_assign(arvif, NULL, 0);
103
104 len = ath10k_p2p_noa_ie_len_compute(noa);
105 if (!len)
106 return;
107
108 ie = kmalloc(len, GFP_ATOMIC);
109 if (!ie)
110 return;
111
112 ath10k_p2p_noa_ie_fill(ie, len, noa);
113 ath10k_p2p_noa_ie_assign(arvif, ie, len);
114}
115
116void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
117 const struct wmi_p2p_noa_info *noa)
118{
119 struct ath10k *ar = arvif->ar;
120
121 spin_lock_bh(&ar->data_lock);
122 __ath10k_p2p_noa_update(arvif, noa);
123 spin_unlock_bh(&ar->data_lock);
124}
diff --git a/drivers/net/wireless/ath/ath10k/p2p.h b/drivers/net/wireless/ath/ath10k/p2p.h
new file mode 100644
index 000000000000..171d30d699cc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/p2p.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (c) 2015 Qualcomm Atheros, Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef _P2P_H
18#define _P2P_H
19
20struct ath10k_vif;
21struct wmi_p2p_noa_info;
22
23void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
24 const struct wmi_p2p_noa_info *noa);
25
26#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 7fc81f2fef36..29aef7eb4d6c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -26,6 +26,7 @@
26#include "mac.h" 26#include "mac.h"
27#include "testmode.h" 27#include "testmode.h"
28#include "wmi-ops.h" 28#include "wmi-ops.h"
29#include "p2p.h"
29 30
30/* MAIN WMI cmd track */ 31/* MAIN WMI cmd track */
31static struct wmi_cmd_map wmi_cmd_map = { 32static struct wmi_cmd_map wmi_cmd_map = {
@@ -2276,109 +2277,25 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
2276 tim->bitmap_ctrl, pvm_len); 2277 tim->bitmap_ctrl, pvm_len);
2277} 2278}
2278 2279
2279static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len,
2280 const struct wmi_p2p_noa_info *noa)
2281{
2282 struct ieee80211_p2p_noa_attr *noa_attr;
2283 u8 ctwindow_oppps = noa->ctwindow_oppps;
2284 u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET;
2285 bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT);
2286 __le16 *noa_attr_len;
2287 u16 attr_len;
2288 u8 noa_descriptors = noa->num_descriptors;
2289 int i;
2290
2291 /* P2P IE */
2292 data[0] = WLAN_EID_VENDOR_SPECIFIC;
2293 data[1] = len - 2;
2294 data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
2295 data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
2296 data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
2297 data[5] = WLAN_OUI_TYPE_WFA_P2P;
2298
2299 /* NOA ATTR */
2300 data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
2301 noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
2302 noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
2303
2304 noa_attr->index = noa->index;
2305 noa_attr->oppps_ctwindow = ctwindow;
2306 if (oppps)
2307 noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
2308
2309 for (i = 0; i < noa_descriptors; i++) {
2310 noa_attr->desc[i].count =
2311 __le32_to_cpu(noa->descriptors[i].type_count);
2312 noa_attr->desc[i].duration = noa->descriptors[i].duration;
2313 noa_attr->desc[i].interval = noa->descriptors[i].interval;
2314 noa_attr->desc[i].start_time = noa->descriptors[i].start_time;
2315 }
2316
2317 attr_len = 2; /* index + oppps_ctwindow */
2318 attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
2319 *noa_attr_len = __cpu_to_le16(attr_len);
2320}
2321
2322static u32 ath10k_p2p_calc_noa_ie_len(const struct wmi_p2p_noa_info *noa)
2323{
2324 u32 len = 0;
2325 u8 noa_descriptors = noa->num_descriptors;
2326 u8 opp_ps_info = noa->ctwindow_oppps;
2327 bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
2328
2329 if (!noa_descriptors && !opps_enabled)
2330 return len;
2331
2332 len += 1 + 1 + 4; /* EID + len + OUI */
2333 len += 1 + 2; /* noa attr + attr len */
2334 len += 1 + 1; /* index + oppps_ctwindow */
2335 len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
2336
2337 return len;
2338}
2339
2340static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, 2280static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
2341 struct sk_buff *bcn, 2281 struct sk_buff *bcn,
2342 const struct wmi_p2p_noa_info *noa) 2282 const struct wmi_p2p_noa_info *noa)
2343{ 2283{
2344 u8 *new_data, *old_data = arvif->u.ap.noa_data;
2345 u32 new_len;
2346
2347 if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) 2284 if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
2348 return; 2285 return;
2349 2286
2350 ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); 2287 ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed);
2351 if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) {
2352 new_len = ath10k_p2p_calc_noa_ie_len(noa);
2353 if (!new_len)
2354 goto cleanup;
2355 2288
2356 new_data = kmalloc(new_len, GFP_ATOMIC); 2289 if (noa->changed & WMI_P2P_NOA_CHANGED_BIT)
2357 if (!new_data) 2290 ath10k_p2p_noa_update(arvif, noa);
2358 goto cleanup;
2359
2360 ath10k_p2p_fill_noa_ie(new_data, new_len, noa);
2361
2362 spin_lock_bh(&ar->data_lock);
2363 arvif->u.ap.noa_data = new_data;
2364 arvif->u.ap.noa_len = new_len;
2365 spin_unlock_bh(&ar->data_lock);
2366 kfree(old_data);
2367 }
2368 2291
2369 if (arvif->u.ap.noa_data) 2292 if (arvif->u.ap.noa_data)
2370 if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) 2293 if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC))
2371 memcpy(skb_put(bcn, arvif->u.ap.noa_len), 2294 memcpy(skb_put(bcn, arvif->u.ap.noa_len),
2372 arvif->u.ap.noa_data, 2295 arvif->u.ap.noa_data,
2373 arvif->u.ap.noa_len); 2296 arvif->u.ap.noa_len);
2374 return;
2375 2297
2376cleanup: 2298 return;
2377 spin_lock_bh(&ar->data_lock);
2378 arvif->u.ap.noa_data = NULL;
2379 arvif->u.ap.noa_len = 0;
2380 spin_unlock_bh(&ar->data_lock);
2381 kfree(old_data);
2382} 2299}
2383 2300
2384static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, 2301static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,