blob: 09cac5689c6fc8e147b7813990bd28a05eed3423 [file] [log] [blame]
Jeff Johnson2b0a7b82016-05-18 15:08:02 -07001/*
2 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_lpass.c
30 *
31 * WLAN Host Device Driver LPASS feature implementation
32 *
33 */
34
Jeff Johnson731f3a12016-05-19 07:05:06 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070038/* Include Files */
39#include "wlan_hdd_main.h"
40#include "wlan_hdd_lpass.h"
41#include <cds_utils.h>
42#include "qwlan_version.h"
43
Jeff Johnsonf96ef732016-05-18 16:38:06 -070044/**
45 * wlan_hdd_gen_wlan_status_pack() - Create lpass adapter status package
46 * @data: Status data record to be created
47 * @adapter: Adapter whose status is to being packaged
48 * @sta_ctx: Station-specific context of @adapter
49 * @is_on: Is wlan driver loaded?
50 * @is_connected: Is @adapater connected to an AP?
51 *
52 * Generate a wlan vdev status package. The status info includes wlan
53 * on/off status, vdev ID, vdev mode, supported channels, etc.
54 *
55 * Return: 0 if package was created, otherwise a negative errno
56 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070057static int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
58 hdd_adapter_t *adapter,
Jeff Johnsond9dd4842016-05-18 16:49:29 -070059 hdd_station_ctx_t *sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070060 uint8_t is_on, uint8_t is_connected)
61{
62 hdd_context_t *hdd_ctx = NULL;
63 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
64
65 if (!data) {
Jeff Johnson731f3a12016-05-19 07:05:06 -070066 hdd_err("invalid data pointer");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070067 return -EINVAL;
68 }
69 if (!adapter) {
70 if (is_on) {
71 /* no active interface */
72 data->lpss_support = 0;
73 data->is_on = is_on;
74 return 0;
75 }
Jeff Johnson731f3a12016-05-19 07:05:06 -070076 hdd_err("invalid adapter pointer");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070077 return -EINVAL;
78 }
79
Prashanth Bhattaf59165a2016-08-26 16:40:38 -070080 if (adapter->sessionId == HDD_SESSION_ID_INVALID)
81 return -EINVAL;
82
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070083 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
84 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
85 data->lpss_support = 1;
86 else
87 data->lpss_support = 0;
88 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
89 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
90 &data->numChannels);
91 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
92 data->is_on = is_on;
93 data->vdev_id = adapter->sessionId;
94 data->vdev_mode = adapter->device_mode;
Jeff Johnsond9dd4842016-05-18 16:49:29 -070095 if (sta_ctx) {
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070096 data->is_connected = is_connected;
97 data->rssi = adapter->rssi;
98 data->freq =
Jeff Johnsond9dd4842016-05-18 16:49:29 -070099 cds_chan_to_freq(sta_ctx->conn_info.operationChannel);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100 if (WLAN_SVC_MAX_SSID_LEN >=
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700101 sta_ctx->conn_info.SSID.SSID.length) {
102 data->ssid_len = sta_ctx->conn_info.SSID.SSID.length;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700103 memcpy(data->ssid,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700104 sta_ctx->conn_info.SSID.SSID.ssId,
105 sta_ctx->conn_info.SSID.SSID.length);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700106 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700107 if (QDF_MAC_ADDR_SIZE >= sizeof(sta_ctx->conn_info.bssId))
108 memcpy(data->bssid, sta_ctx->conn_info.bssId.bytes,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700109 QDF_MAC_ADDR_SIZE);
110 }
111 return 0;
112}
113
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700114/**
115 * wlan_hdd_gen_wlan_version_pack() - Create lpass version package
116 * @data: Version data record to be created
117 * @fw_version: Version code from firmware
118 * @chip_id: WLAN chip ID
119 * @chip_name: WLAN chip name
120 *
121 * Generate a wlan software/hw version info package. The version info
122 * includes wlan host driver version, wlan fw driver version, wlan hw
123 * chip id & wlan hw chip name.
124 *
125 * Return: 0 if package was created, otherwise a negative errno
126 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700127static int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
128 uint32_t fw_version,
129 uint32_t chip_id,
130 const char *chip_name)
131{
132 if (!data) {
Jeff Johnson731f3a12016-05-19 07:05:06 -0700133 hdd_err("invalid data pointer");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700134 return -EINVAL;
135 }
136
137 data->chip_id = chip_id;
138 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
139 if (strncmp(chip_name, "Unknown", 7))
140 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
141 else
142 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
143 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
144 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
145 (fw_version & 0xf0000000) >> 28,
146 (fw_version & 0xf000000) >> 24,
147 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
148 return 0;
149}
150
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700151/**
152 * wlan_hdd_send_status_pkg() - Send adapter status to lpass
153 * @adapter: Adapter whose status is to be sent to lpass
154 * @sta_ctx: Station-specific context of @adapter
155 * @is_on: Is @adapter enabled
156 * @is_connected: Is @adapater connected
157 *
158 * Generate wlan vdev status pacakge and send it to a user space
159 * daemon through netlink.
160 *
161 * Return: none
162 */
Jeff Johnson71396692016-09-23 15:41:52 -0700163static void wlan_hdd_send_status_pkg(struct hdd_adapter_s *adapter,
164 struct hdd_station_ctx *sta_ctx,
165 uint8_t is_on, uint8_t is_connected)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700166{
167 int ret = 0;
168 struct wlan_status_data data;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530169 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
170
171 if (!hdd_ctx)
172 return;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700173
174 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
175 return;
176
177 memset(&data, 0, sizeof(struct wlan_status_data));
178 if (is_on)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700179 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700180 is_on, is_connected);
Prashanth Bhattaf59165a2016-08-26 16:40:38 -0700181
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700182 if (!ret)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530183 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
184 WLAN_SVC_WLAN_STATUS_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700185 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700186}
187
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700188/**
189 * wlan_hdd_send_version_pkg() - report version information to lpass
190 * @fw_version: Version code from firmware
191 * @chip_id: WLAN chip ID
192 * @chip_name: WLAN chip name
193 *
194 * Generate a wlan sw/hw version info package and send it to a user
195 * space daemon through netlink.
196 *
197 * Return: none
198 */
Jeff Johnson9afc5012016-09-23 13:56:27 -0700199static void wlan_hdd_send_version_pkg(uint32_t fw_version,
200 uint32_t chip_id,
201 const char *chip_name)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700202{
203 int ret = 0;
204 struct wlan_version_data data;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530205 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
206
207 if (!hdd_ctx)
208 return;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700209
210 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
211 return;
212
213 memset(&data, 0, sizeof(struct wlan_version_data));
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700214 ret = wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
215 chip_name);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700216 if (!ret)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530217 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
218 WLAN_SVC_WLAN_VERSION_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700219 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700220}
221
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700222/**
223 * wlan_hdd_send_all_scan_intf_info() - report scan interfaces to lpass
224 * @hdd_ctx: The global HDD context
225 *
226 * This function iterates through all of the interfaces registered
227 * with HDD and indicates to lpass all that support scanning.
228 * If no interfaces support scanning then that fact is also indicated.
229 *
230 * Return: none
231 */
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700232static void wlan_hdd_send_all_scan_intf_info(struct hdd_context_s *hdd_ctx)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700233{
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700234 hdd_adapter_t *adapter = NULL;
235 hdd_adapter_list_node_t *node = NULL, *next = NULL;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700236 bool scan_intf_found = false;
237 QDF_STATUS status;
238
239 if (!hdd_ctx) {
Jeff Johnson731f3a12016-05-19 07:05:06 -0700240 hdd_err("NULL pointer for hdd_ctx");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700241 return;
242 }
243
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700244 status = hdd_get_front_adapter(hdd_ctx, &node);
245 while (NULL != node && QDF_STATUS_SUCCESS == status) {
246 adapter = node->pAdapter;
247 if (adapter) {
248 if (adapter->device_mode == QDF_STA_MODE
249 || adapter->device_mode == QDF_P2P_CLIENT_MODE
250 || adapter->device_mode ==
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700251 QDF_P2P_DEVICE_MODE) {
252 scan_intf_found = true;
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700253 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700254 }
255 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700256 status = hdd_get_next_adapter(hdd_ctx, node, &next);
257 node = next;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700258 }
259
260 if (!scan_intf_found)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700261 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700262}
Jeff Johnson9afc5012016-09-23 13:56:27 -0700263
Jeff Johnson67904df2016-09-27 15:15:51 -0700264/*
Jeff Johnsonc875e242016-09-23 18:12:34 -0700265 * hdd_lpass_target_config() - Handle LPASS target configuration
Jeff Johnson67904df2016-09-27 15:15:51 -0700266 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonc875e242016-09-23 18:12:34 -0700267 */
268void hdd_lpass_target_config(struct hdd_context_s *hdd_ctx,
269 struct wma_tgt_cfg *target_config)
270{
271 hdd_ctx->lpss_support = target_config->lpss_support;
272}
273
Jeff Johnson67904df2016-09-27 15:15:51 -0700274/*
Jeff Johnson9078bdc2016-09-23 17:18:11 -0700275 * hdd_lpass_populate_cds_config() - Populate LPASS configuration
Jeff Johnson67904df2016-09-27 15:15:51 -0700276 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson9078bdc2016-09-23 17:18:11 -0700277 */
278void hdd_lpass_populate_cds_config(struct cds_config_info *cds_config,
279 struct hdd_context_s *hdd_ctx)
280{
281 cds_config->is_lpass_enabled = hdd_ctx->config->enable_lpass_support;
282}
283
Jeff Johnson67904df2016-09-27 15:15:51 -0700284/*
Jeff Johnson71396692016-09-23 15:41:52 -0700285 * hdd_lpass_notify_connect() - Notify LPASS of interface connect
Jeff Johnson67904df2016-09-27 15:15:51 -0700286 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson71396692016-09-23 15:41:52 -0700287 */
288void hdd_lpass_notify_connect(struct hdd_adapter_s *adapter)
289{
290 struct hdd_station_ctx *sta_ctx;
291
292 /* only send once per connection */
293 if (adapter->rssi_send)
294 return;
295
296 /* don't send if driver is unloading */
297 if (cds_is_driver_unloading())
298 return;
299
300 adapter->rssi_send = true;
301 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
302 wlan_hdd_send_status_pkg(adapter, sta_ctx, 1, 1);
303}
304
Jeff Johnson67904df2016-09-27 15:15:51 -0700305/*
Jeff Johnsoncef59bb2016-09-23 15:28:47 -0700306 * hdd_lpass_notify_disconnect() - Notify LPASS of interface disconnect
Jeff Johnson67904df2016-09-27 15:15:51 -0700307 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsoncef59bb2016-09-23 15:28:47 -0700308 */
309void hdd_lpass_notify_disconnect(struct hdd_adapter_s *adapter)
310{
311 struct hdd_station_ctx *sta_ctx;
312
313 adapter->rssi_send = false;
314 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
315 wlan_hdd_send_status_pkg(adapter, sta_ctx, 1, 0);
316}
317
Jeff Johnson67904df2016-09-27 15:15:51 -0700318/*
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700319 * hdd_lpass_notify_mode_change() - Notify LPASS of interface mode change
Jeff Johnson67904df2016-09-27 15:15:51 -0700320 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700321 *
Jeff Johnson67904df2016-09-27 15:15:51 -0700322 * implementation note: when one interfaces changes we notify the
323 * state of all of the interfaces.
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700324 */
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700325void hdd_lpass_notify_mode_change(struct hdd_adapter_s *adapter)
326{
327 struct hdd_context_s *hdd_ctx;
328
329 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
330 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
331}
332
Jeff Johnson67904df2016-09-27 15:15:51 -0700333/*
Jeff Johnson9afc5012016-09-23 13:56:27 -0700334 * hdd_lpass_notify_start() - Notify LPASS of driver start
Jeff Johnson67904df2016-09-27 15:15:51 -0700335 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson9afc5012016-09-23 13:56:27 -0700336 */
337void hdd_lpass_notify_start(struct hdd_context_s *hdd_ctx)
338{
339 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
340 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
341 hdd_ctx->target_hw_version,
342 hdd_ctx->target_hw_name);
343}
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700344
Jeff Johnson67904df2016-09-27 15:15:51 -0700345/*
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700346 * hdd_lpass_notify_stop() - Notify LPASS of driver stop
Jeff Johnson67904df2016-09-27 15:15:51 -0700347 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700348 */
349void hdd_lpass_notify_stop(struct hdd_context_s *hdd_ctx)
350{
351 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
352}
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700353
Jeff Johnson67904df2016-09-27 15:15:51 -0700354/*
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700355 * hdd_lpass_is_supported() - Is lpass feature supported?
Jeff Johnson67904df2016-09-27 15:15:51 -0700356 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700357 */
358bool hdd_lpass_is_supported(struct hdd_context_s *hdd_ctx)
359{
360 return hdd_ctx->config->enable_lpass_support;
361}