blob: d53663b418eae56d2b46db53aeb9783cd336fec3 [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 Johnson2b0a7b82016-05-18 15:08:02 -0700163void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700164 hdd_station_ctx_t *sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700165 uint8_t is_on, uint8_t is_connected)
166{
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 Johnson2b0a7b82016-05-18 15:08:02 -0700232void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
233{
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
264/**
265 * hdd_lpass_notify_start() - Notify LPASS of driver start
266 * @hdd_ctx: The global HDD context
267 *
268 * This function is used to notify the LPASS feature that the wlan
269 * driver has (re-)started.
270 *
271 * Return: none
272 */
273void hdd_lpass_notify_start(struct hdd_context_s *hdd_ctx)
274{
275 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
276 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
277 hdd_ctx->target_hw_version,
278 hdd_ctx->target_hw_name);
279}