blob: 00fa4387fbdd3c1681e1ee70e6ad1e76d4cc1bfd [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
35/* Include Files */
36#include "wlan_hdd_main.h"
37#include "wlan_hdd_lpass.h"
38#include <cds_utils.h>
39#include "qwlan_version.h"
40
Jeff Johnsonf96ef732016-05-18 16:38:06 -070041/**
42 * wlan_hdd_gen_wlan_status_pack() - Create lpass adapter status package
43 * @data: Status data record to be created
44 * @adapter: Adapter whose status is to being packaged
45 * @sta_ctx: Station-specific context of @adapter
46 * @is_on: Is wlan driver loaded?
47 * @is_connected: Is @adapater connected to an AP?
48 *
49 * Generate a wlan vdev status package. The status info includes wlan
50 * on/off status, vdev ID, vdev mode, supported channels, etc.
51 *
52 * Return: 0 if package was created, otherwise a negative errno
53 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070054static int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
55 hdd_adapter_t *adapter,
Jeff Johnsond9dd4842016-05-18 16:49:29 -070056 hdd_station_ctx_t *sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070057 uint8_t is_on, uint8_t is_connected)
58{
59 hdd_context_t *hdd_ctx = NULL;
60 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
61
62 if (!data) {
63 hddLog(LOGE, FL("invalid data pointer"));
64 return -EINVAL;
65 }
66 if (!adapter) {
67 if (is_on) {
68 /* no active interface */
69 data->lpss_support = 0;
70 data->is_on = is_on;
71 return 0;
72 }
73 hddLog(LOGE, FL("invalid adapter pointer"));
74 return -EINVAL;
75 }
76
77 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
78 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
79 data->lpss_support = 1;
80 else
81 data->lpss_support = 0;
82 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
83 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
84 &data->numChannels);
85 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
86 data->is_on = is_on;
87 data->vdev_id = adapter->sessionId;
88 data->vdev_mode = adapter->device_mode;
Jeff Johnsond9dd4842016-05-18 16:49:29 -070089 if (sta_ctx) {
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070090 data->is_connected = is_connected;
91 data->rssi = adapter->rssi;
92 data->freq =
Jeff Johnsond9dd4842016-05-18 16:49:29 -070093 cds_chan_to_freq(sta_ctx->conn_info.operationChannel);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070094 if (WLAN_SVC_MAX_SSID_LEN >=
Jeff Johnsond9dd4842016-05-18 16:49:29 -070095 sta_ctx->conn_info.SSID.SSID.length) {
96 data->ssid_len = sta_ctx->conn_info.SSID.SSID.length;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070097 memcpy(data->ssid,
Jeff Johnsond9dd4842016-05-18 16:49:29 -070098 sta_ctx->conn_info.SSID.SSID.ssId,
99 sta_ctx->conn_info.SSID.SSID.length);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700101 if (QDF_MAC_ADDR_SIZE >= sizeof(sta_ctx->conn_info.bssId))
102 memcpy(data->bssid, sta_ctx->conn_info.bssId.bytes,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700103 QDF_MAC_ADDR_SIZE);
104 }
105 return 0;
106}
107
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700108/**
109 * wlan_hdd_gen_wlan_version_pack() - Create lpass version package
110 * @data: Version data record to be created
111 * @fw_version: Version code from firmware
112 * @chip_id: WLAN chip ID
113 * @chip_name: WLAN chip name
114 *
115 * Generate a wlan software/hw version info package. The version info
116 * includes wlan host driver version, wlan fw driver version, wlan hw
117 * chip id & wlan hw chip name.
118 *
119 * Return: 0 if package was created, otherwise a negative errno
120 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700121static int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
122 uint32_t fw_version,
123 uint32_t chip_id,
124 const char *chip_name)
125{
126 if (!data) {
127 hddLog(LOGE, FL("invalid data pointer"));
128 return -EINVAL;
129 }
130
131 data->chip_id = chip_id;
132 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
133 if (strncmp(chip_name, "Unknown", 7))
134 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
135 else
136 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
137 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
138 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
139 (fw_version & 0xf0000000) >> 28,
140 (fw_version & 0xf000000) >> 24,
141 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
142 return 0;
143}
144
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700145/**
146 * wlan_hdd_send_status_pkg() - Send adapter status to lpass
147 * @adapter: Adapter whose status is to be sent to lpass
148 * @sta_ctx: Station-specific context of @adapter
149 * @is_on: Is @adapter enabled
150 * @is_connected: Is @adapater connected
151 *
152 * Generate wlan vdev status pacakge and send it to a user space
153 * daemon through netlink.
154 *
155 * Return: none
156 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700157void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700158 hdd_station_ctx_t *sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700159 uint8_t is_on, uint8_t is_connected)
160{
161 int ret = 0;
162 struct wlan_status_data data;
163
164 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
165 return;
166
167 memset(&data, 0, sizeof(struct wlan_status_data));
168 if (is_on)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700169 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, sta_ctx,
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700170 is_on, is_connected);
171 if (!ret)
172 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700173 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700174}
175
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700176/**
177 * wlan_hdd_send_version_pkg() - report version information to lpass
178 * @fw_version: Version code from firmware
179 * @chip_id: WLAN chip ID
180 * @chip_name: WLAN chip name
181 *
182 * Generate a wlan sw/hw version info package and send it to a user
183 * space daemon through netlink.
184 *
185 * Return: none
186 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700187void wlan_hdd_send_version_pkg(uint32_t fw_version,
188 uint32_t chip_id, const char *chip_name)
189{
190 int ret = 0;
191 struct wlan_version_data data;
192
193 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
194 return;
195
196 memset(&data, 0, sizeof(struct wlan_version_data));
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700197 ret = wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
198 chip_name);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700199 if (!ret)
200 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700201 &data, sizeof(data));
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700202}
203
Jeff Johnsonf96ef732016-05-18 16:38:06 -0700204/**
205 * wlan_hdd_send_all_scan_intf_info() - report scan interfaces to lpass
206 * @hdd_ctx: The global HDD context
207 *
208 * This function iterates through all of the interfaces registered
209 * with HDD and indicates to lpass all that support scanning.
210 * If no interfaces support scanning then that fact is also indicated.
211 *
212 * Return: none
213 */
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700214void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
215{
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700216 hdd_adapter_t *adapter = NULL;
217 hdd_adapter_list_node_t *node = NULL, *next = NULL;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700218 bool scan_intf_found = false;
219 QDF_STATUS status;
220
221 if (!hdd_ctx) {
222 hddLog(QDF_TRACE_LEVEL_ERROR,
223 FL("NULL pointer for hdd_ctx"));
224 return;
225 }
226
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700227 status = hdd_get_front_adapter(hdd_ctx, &node);
228 while (NULL != node && QDF_STATUS_SUCCESS == status) {
229 adapter = node->pAdapter;
230 if (adapter) {
231 if (adapter->device_mode == QDF_STA_MODE
232 || adapter->device_mode == QDF_P2P_CLIENT_MODE
233 || adapter->device_mode ==
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700234 QDF_P2P_DEVICE_MODE) {
235 scan_intf_found = true;
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700236 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700237 }
238 }
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700239 status = hdd_get_next_adapter(hdd_ctx, node, &next);
240 node = next;
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700241 }
242
243 if (!scan_intf_found)
Jeff Johnsond9dd4842016-05-18 16:49:29 -0700244 wlan_hdd_send_status_pkg(adapter, NULL, 1, 0);
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700245}