blob: 2563a94bddbdb40f0d51fd22fb4ff37986058a03 [file] [log] [blame]
Manikandan Mohandcc21ba2016-03-15 14:31:56 -07001/*
2 * Copyright (c) 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 * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation
30 */
31
32#include "wlan_hdd_main.h"
33#include "wma_api.h"
34
35/**
36 * hdd_capture_tsf() - capture tsf
37 * @adapter: pointer to adapter
38 * @buf: pointer to uplayer buf
39 * @len : the length of buf
40 *
41 * This function returns tsf value to uplayer.
42 *
43 * Return: 0 for success or non-zero negative failure code
44 */
45int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
46{
47 int ret = 0;
48 hdd_station_ctx_t *hdd_sta_ctx;
49
50 if (adapter == NULL || buf == NULL) {
51 hdd_err(FL("invalid pointer"));
52 return -EINVAL;
53 }
54 if (len != 1)
55 return -EINVAL;
56
57 /* Reset TSF value for new capture */
58 adapter->tsf_high = 0;
59 adapter->tsf_low = 0;
60
61 if (adapter->device_mode == QDF_STA_MODE ||
62 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
63 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
64 if (hdd_sta_ctx->conn_info.connState !=
65 eConnectionState_Associated) {
66
67 hdd_err(FL("failed to cap tsf, not connect with ap"));
68 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
69 return ret;
70 }
71 }
72 if ((adapter->device_mode == QDF_SAP_MODE ||
73 adapter->device_mode == QDF_P2P_GO_MODE) &&
74 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
75 hdd_err(FL("Soft AP / P2p GO not beaconing"));
76 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
77 return ret;
78 }
79 if (adapter->tsf_state == TSF_CAP_STATE) {
80 hdd_err(FL("current in capture state, pls reset"));
81 buf[0] = TSF_CURRENT_IN_CAP_STATE;
82 } else {
83 hdd_info(FL("Send TSF capture to FW"));
84 buf[0] = TSF_RETURN;
85 adapter->tsf_state = TSF_CAP_STATE;
86 ret = wma_cli_set_command((int)adapter->sessionId,
87 (int)GEN_PARAM_CAPTURE_TSF,
88 adapter->sessionId,
89 GEN_CMD);
90
91 if (ret != QDF_STATUS_SUCCESS) {
92 hdd_err(FL("capture fail"));
93 buf[0] = TSF_CAPTURE_FAIL;
94 adapter->tsf_state = TSF_IDLE;
95 }
96 }
97 return ret;
98}
99
100/**
101 * hdd_indicate_tsf() - return tsf to uplayer
102 * @adapter: pointer to adapter
103 * @buf: pointer to uplayer buf
104 * @len : the length of buf
105 *
106 * This function returns tsf value to upper layer.
107 *
108 * Return: 0 for success or non-zero negative failure code
109 */
110int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
111{
112 int ret = 0;
113 hdd_station_ctx_t *hdd_sta_ctx;
114
115 if (adapter == NULL || buf == NULL) {
116 hdd_err(FL("invalid pointer"));
117 return -EINVAL;
118 }
119
120 if (len != 3)
121 return -EINVAL;
122
123 buf[1] = 0;
124 buf[2] = 0;
125 if (adapter->device_mode == QDF_STA_MODE ||
126 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
127 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
128 if (hdd_sta_ctx->conn_info.connState !=
129 eConnectionState_Associated) {
130
131 hdd_info(FL("fail to get tsf, sta in disconnected"));
132 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
133 return ret;
134 }
135 }
136 if ((adapter->device_mode == QDF_SAP_MODE ||
137 adapter->device_mode == QDF_P2P_GO_MODE) &&
138 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
139 hdd_err(FL("Soft AP / P2p GO not beaconing"));
140 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
141 return ret;
142 }
143 if (adapter->tsf_high == 0 && adapter->tsf_low == 0) {
144 hdd_info(FL("TSF value not received"));
145 buf[0] = TSF_NOT_RETURNED_BY_FW;
146 } else {
147 buf[0] = TSF_RETURN;
148 buf[1] = adapter->tsf_low;
149 buf[2] = adapter->tsf_high;
150 adapter->tsf_state = TSF_IDLE;
151
152 ret = wma_cli_set_command((int)adapter->sessionId,
153 (int)GEN_PARAM_RESET_TSF_GPIO,
154 adapter->sessionId,
155 GEN_CMD);
156
157 if (0 != ret) {
158 hdd_err(FL("tsf get fail "));
159 buf[0] = TSF_RESET_GPIO_FAIL;
160 }
161 hdd_info(FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
162 buf[0], buf[1], buf[2]);
163 }
164 return ret;
165}
166
167/**
168 * hdd_get_tsf_cb() - handle tsf callback
169 * @pcb_cxt: pointer to the hdd_contex
170 * @ptsf: pointer to struct stsf
171 *
172 * This function handle the event that reported by firmware at first.
173 * The event contains the vdev_id, current tsf value of this vdev,
174 * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high.
175 * These two values each is uint32.
176 *
177 * Return: 0 for success or non-zero negative failure code
178 */
179static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
180{
181 struct hdd_context_s *hddctx;
182 struct hdd_adapter_s *adapter;
183 int status;
184
185 if (pcb_cxt == NULL || ptsf == NULL) {
186 hdd_err(FL("HDD context is not valid"));
187 return -EINVAL;
188 }
189
190 hddctx = (struct hdd_context_s *)pcb_cxt;
191 status = wlan_hdd_validate_context(hddctx);
192 if (0 != status) {
193 hdd_err(FL("hdd context is not valid"));
194 return -EINVAL;
195 }
196
197 adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id);
198
199 if (NULL == adapter) {
200 hdd_err(FL("failed to find adapter"));
201 return -EINVAL;
202 }
203
204 hdd_info(FL("tsf cb handle event, device_mode is %d"),
205 adapter->device_mode);
206
207 adapter->tsf_low = ptsf->tsf_low;
208 adapter->tsf_high = ptsf->tsf_high;
209
210 hdd_info(FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
211 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
212 return 0;
213}
214
215/**
216 * wlan_hdd_tsf_init() - set callback to handle tsf value.
217 * @hdd_ctx: pointer to the struct hdd_context_s
218 *
219 * This function set the callback to sme module, the callback will be
220 * called when a tsf event is reported by firmware
221 *
222 * Return: none
223 */
224void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx)
225{
226 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
227}