blob: de80700c7d3e4221404eba101e84382544348c52 [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
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053080 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
81 hdd_err("invalid session id: %d", adapter->sessionId);
Prashanth Bhattaf59165a2016-08-26 16:40:38 -070082 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053083 }
Prashanth Bhattaf59165a2016-08-26 16:40:38 -070084
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070085 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
86 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
87 data->lpss_support = 1;
88 else
89 data->lpss_support = 0;
90 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
91 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
92 &data->numChannels);
93 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
94 data->is_on = is_on;
95 data->vdev_id = adapter->sessionId;
96 data->vdev_mode = adapter->device_mode;
Jeff Johnsond9dd4842016-05-18 16:49:29 -070097 if (sta_ctx) {
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098 data->is_connected = is_connected;
99 data->rssi = adapter->rssi;
100 data->freq =
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700101 cds_chan_to_freq(sta_ctx->conn_info.operationChannel);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700102 if (WLAN_SVC_MAX_SSID_LEN >=
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700103 sta_ctx->conn_info.SSID.SSID.length) {
104 data->ssid_len = sta_ctx->conn_info.SSID.SSID.length;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700105 memcpy(data->ssid,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700106 sta_ctx->conn_info.SSID.SSID.ssId,
107 sta_ctx->conn_info.SSID.SSID.length);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700108 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700109 if (QDF_MAC_ADDR_SIZE >= sizeof(sta_ctx->conn_info.bssId))
110 memcpy(data->bssid, sta_ctx->conn_info.bssId.bytes,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700111 QDF_MAC_ADDR_SIZE);
112 }
113 return 0;
114}
115
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700116/**
117 * wlan_hdd_gen_wlan_version_pack() - Create lpass version package
118 * @data: Version data record to be created
119 * @fw_version: Version code from firmware
120 * @chip_id: WLAN chip ID
121 * @chip_name: WLAN chip name
122 *
123 * Generate a wlan software/hw version info package. The version info
124 * includes wlan host driver version, wlan fw driver version, wlan hw
125 * chip id & wlan hw chip name.
126 *
127 * Return: 0 if package was created, otherwise a negative errno
128 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700129static int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
130 uint32_t fw_version,
131 uint32_t chip_id,
132 const char *chip_name)
133{
134 if (!data) {
Jeff Johnson731f3a12016-05-19 07:05:06 -0700135 hdd_err("invalid data pointer");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700136 return -EINVAL;
137 }
138
139 data->chip_id = chip_id;
140 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
141 if (strncmp(chip_name, "Unknown", 7))
142 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
143 else
144 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
145 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
146 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
147 (fw_version & 0xf0000000) >> 28,
148 (fw_version & 0xf000000) >> 24,
149 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
150 return 0;
151}
152
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700153/**
154 * wlan_hdd_send_status_pkg() - Send adapter status to lpass
155 * @adapter: Adapter whose status is to be sent to lpass
156 * @sta_ctx: Station-specific context of @adapter
157 * @is_on: Is @adapter enabled
158 * @is_connected: Is @adapater connected
159 *
160 * Generate wlan vdev status pacakge and send it to a user space
161 * daemon through netlink.
162 *
163 * Return: none
164 */
Jeff Johnson71396692016-09-23 15:41:52 -0700165static void wlan_hdd_send_status_pkg(struct hdd_adapter_s *adapter,
166 struct hdd_station_ctx *sta_ctx,
167 uint8_t is_on, uint8_t is_connected)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700168{
169 int ret = 0;
170 struct wlan_status_data data;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530171 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
172
173 if (!hdd_ctx)
174 return;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700175
176 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
177 return;
178
179 memset(&data, 0, sizeof(struct wlan_status_data));
180 if (is_on)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700181 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700182 is_on, is_connected);
Prashanth Bhattaf59165a2016-08-26 16:40:38 -0700183
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700184 if (!ret)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530185 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
186 WLAN_SVC_WLAN_STATUS_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700187 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700188}
189
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700190/**
191 * wlan_hdd_send_version_pkg() - report version information to lpass
192 * @fw_version: Version code from firmware
193 * @chip_id: WLAN chip ID
194 * @chip_name: WLAN chip name
195 *
196 * Generate a wlan sw/hw version info package and send it to a user
197 * space daemon through netlink.
198 *
199 * Return: none
200 */
Jeff Johnson9afc5012016-09-23 13:56:27 -0700201static void wlan_hdd_send_version_pkg(uint32_t fw_version,
202 uint32_t chip_id,
203 const char *chip_name)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700204{
205 int ret = 0;
206 struct wlan_version_data data;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530207 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
208
209 if (!hdd_ctx)
210 return;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700211
212 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
213 return;
214
215 memset(&data, 0, sizeof(struct wlan_version_data));
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700216 ret = wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
217 chip_name);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700218 if (!ret)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +0530219 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
220 WLAN_SVC_WLAN_VERSION_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700221 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700222}
223
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700224/**
225 * wlan_hdd_send_all_scan_intf_info() - report scan interfaces to lpass
226 * @hdd_ctx: The global HDD context
227 *
228 * This function iterates through all of the interfaces registered
229 * with HDD and indicates to lpass all that support scanning.
230 * If no interfaces support scanning then that fact is also indicated.
231 *
232 * Return: none
233 */
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700234static void wlan_hdd_send_all_scan_intf_info(struct hdd_context_s *hdd_ctx)
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700235{
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700236 hdd_adapter_t *adapter = NULL;
237 hdd_adapter_list_node_t *node = NULL, *next = NULL;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700238 bool scan_intf_found = false;
239 QDF_STATUS status;
240
241 if (!hdd_ctx) {
Jeff Johnson731f3a12016-05-19 07:05:06 -0700242 hdd_err("NULL pointer for hdd_ctx");
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700243 return;
244 }
245
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700246 status = hdd_get_front_adapter(hdd_ctx, &node);
247 while (NULL != node && QDF_STATUS_SUCCESS == status) {
248 adapter = node->pAdapter;
249 if (adapter) {
250 if (adapter->device_mode == QDF_STA_MODE
251 || adapter->device_mode == QDF_P2P_CLIENT_MODE
252 || adapter->device_mode ==
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700253 QDF_P2P_DEVICE_MODE) {
254 scan_intf_found = true;
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700255 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700256 }
257 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700258 status = hdd_get_next_adapter(hdd_ctx, node, &next);
259 node = next;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700260 }
261
262 if (!scan_intf_found)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700263 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700264}
Jeff Johnson9afc5012016-09-23 13:56:27 -0700265
Jeff Johnson67904df2016-09-27 15:15:51 -0700266/*
Jeff Johnsonc875e242016-09-23 18:12:34 -0700267 * hdd_lpass_target_config() - Handle LPASS target configuration
Jeff Johnson67904df2016-09-27 15:15:51 -0700268 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonc875e242016-09-23 18:12:34 -0700269 */
270void hdd_lpass_target_config(struct hdd_context_s *hdd_ctx,
271 struct wma_tgt_cfg *target_config)
272{
273 hdd_ctx->lpss_support = target_config->lpss_support;
274}
275
Jeff Johnson67904df2016-09-27 15:15:51 -0700276/*
Jeff Johnson9078bdc2016-09-23 17:18:11 -0700277 * hdd_lpass_populate_cds_config() - Populate LPASS configuration
Jeff Johnson67904df2016-09-27 15:15:51 -0700278 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson9078bdc2016-09-23 17:18:11 -0700279 */
280void hdd_lpass_populate_cds_config(struct cds_config_info *cds_config,
281 struct hdd_context_s *hdd_ctx)
282{
283 cds_config->is_lpass_enabled = hdd_ctx->config->enable_lpass_support;
284}
285
Jeff Johnson67904df2016-09-27 15:15:51 -0700286/*
Jeff Johnson71396692016-09-23 15:41:52 -0700287 * hdd_lpass_notify_connect() - Notify LPASS of interface connect
Jeff Johnson67904df2016-09-27 15:15:51 -0700288 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson71396692016-09-23 15:41:52 -0700289 */
290void hdd_lpass_notify_connect(struct hdd_adapter_s *adapter)
291{
292 struct hdd_station_ctx *sta_ctx;
293
294 /* only send once per connection */
295 if (adapter->rssi_send)
296 return;
297
298 /* don't send if driver is unloading */
299 if (cds_is_driver_unloading())
300 return;
301
302 adapter->rssi_send = true;
303 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
304 wlan_hdd_send_status_pkg(adapter, sta_ctx, 1, 1);
305}
306
Jeff Johnson67904df2016-09-27 15:15:51 -0700307/*
Jeff Johnsoncef59bb2016-09-23 15:28:47 -0700308 * hdd_lpass_notify_disconnect() - Notify LPASS of interface disconnect
Jeff Johnson67904df2016-09-27 15:15:51 -0700309 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsoncef59bb2016-09-23 15:28:47 -0700310 */
311void hdd_lpass_notify_disconnect(struct hdd_adapter_s *adapter)
312{
313 struct hdd_station_ctx *sta_ctx;
314
315 adapter->rssi_send = false;
316 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
317 wlan_hdd_send_status_pkg(adapter, sta_ctx, 1, 0);
318}
319
Jeff Johnson67904df2016-09-27 15:15:51 -0700320/*
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700321 * hdd_lpass_notify_mode_change() - Notify LPASS of interface mode change
Jeff Johnson67904df2016-09-27 15:15:51 -0700322 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700323 *
Jeff Johnson67904df2016-09-27 15:15:51 -0700324 * implementation note: when one interfaces changes we notify the
325 * state of all of the interfaces.
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700326 */
Jeff Johnson2ae6f712016-09-23 15:08:48 -0700327void hdd_lpass_notify_mode_change(struct hdd_adapter_s *adapter)
328{
329 struct hdd_context_s *hdd_ctx;
330
331 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
332 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
333}
334
Jeff Johnson67904df2016-09-27 15:15:51 -0700335/*
Jeff Johnson9afc5012016-09-23 13:56:27 -0700336 * hdd_lpass_notify_start() - Notify LPASS of driver start
Jeff Johnson67904df2016-09-27 15:15:51 -0700337 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnson9afc5012016-09-23 13:56:27 -0700338 */
339void hdd_lpass_notify_start(struct hdd_context_s *hdd_ctx)
340{
341 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
342 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
343 hdd_ctx->target_hw_version,
344 hdd_ctx->target_hw_name);
345}
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700346
Jeff Johnson67904df2016-09-27 15:15:51 -0700347/*
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700348 * hdd_lpass_notify_stop() - Notify LPASS of driver stop
Jeff Johnson67904df2016-09-27 15:15:51 -0700349 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonf7f66f02016-09-23 14:50:11 -0700350 */
351void hdd_lpass_notify_stop(struct hdd_context_s *hdd_ctx)
352{
353 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
354}
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700355
Jeff Johnson67904df2016-09-27 15:15:51 -0700356/*
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700357 * hdd_lpass_is_supported() - Is lpass feature supported?
Jeff Johnson67904df2016-09-27 15:15:51 -0700358 * (public function documented in wlan_hdd_lpass.h)
Jeff Johnsonb8bf9072016-09-23 17:39:27 -0700359 */
360bool hdd_lpass_is_supported(struct hdd_context_s *hdd_ctx)
361{
362 return hdd_ctx->config->enable_lpass_support;
363}