[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / net / wireless / scsc / hip.c
1 /****************************************************************************
2 *
3 * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 ****************************************************************************/
6
7 #include <scsc/scsc_logring.h>
8
9 #include "hip.h"
10 #include "debug.h"
11 #include "procfs.h"
12 #include "sap.h"
13 #ifdef CONFIG_SCSC_SMAPPER
14 #include "hip4_smapper.h"
15 #endif
16
17 /* SAP implementations container. Local and static to hip */
18 static struct hip_sap {
19 struct sap_api *sap[SAP_TOTAL];
20 } hip_sap_cont;
21
22 /* Register SAP with HIP layer */
23 int slsi_hip_sap_register(struct sap_api *sap_api)
24 {
25 u8 class = sap_api->sap_class;
26
27 if (class >= SAP_TOTAL)
28 return -ENODEV;
29
30 hip_sap_cont.sap[class] = sap_api;
31
32 return 0;
33 }
34
35 /* UNregister SAP with HIP layer */
36 int slsi_hip_sap_unregister(struct sap_api *sap_api)
37 {
38 u8 class = sap_api->sap_class;
39
40 if (class >= SAP_TOTAL)
41 return -ENODEV;
42
43 hip_sap_cont.sap[class] = NULL;
44
45 return 0;
46 }
47
48 int slsi_hip_sap_setup(struct slsi_dev *sdev)
49 {
50 /* Execute callbacks to intorm Supported version */
51 u16 version = 0;
52 u32 conf_hip4_ver = 0;
53
54 conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init);
55
56 /* We enforce that all the SAPs are registered at this point */
57 if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) ||
58 (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST]))
59 return -ENODEV;
60
61 if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported) {
62 if (conf_hip4_ver == 4)
63 version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_mlme_ver);
64 if (conf_hip4_ver == 5)
65 version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_mlme_ver);
66 if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported(version))
67 return -ENODEV;
68 } else {
69 return -ENODEV;
70 }
71
72 if (hip_sap_cont.sap[SAP_MA]->sap_version_supported) {
73 if (conf_hip4_ver == 4)
74 version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_ma_ver);
75 if (conf_hip4_ver == 5)
76 version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_ma_ver);
77 if (hip_sap_cont.sap[SAP_MA]->sap_version_supported(version))
78 return -ENODEV;
79 } else {
80 return -ENODEV;
81 }
82
83 if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported) {
84 if (conf_hip4_ver == 4)
85 version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_debug_ver);
86 if (conf_hip4_ver == 5)
87 version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_debug_ver);
88 if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported(version))
89 return -ENODEV;
90 } else {
91 return -ENODEV;
92 }
93
94 if (hip_sap_cont.sap[SAP_TST]->sap_version_supported) {
95 if (conf_hip4_ver == 4)
96 version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_test_ver);
97 if (conf_hip4_ver == 5)
98 version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_test_ver);
99 if (hip_sap_cont.sap[SAP_TST]->sap_version_supported(version))
100 return -ENODEV;
101 } else {
102 return -ENODEV;
103 }
104
105 /* Success */
106 return 0;
107 }
108
109 static int slsi_hip_service_notifier(struct notifier_block *nb, unsigned long event, void *data)
110 {
111 struct slsi_dev *sdev = (struct slsi_dev *)data;
112 int i;
113
114 if (!sdev)
115 return NOTIFY_BAD;
116
117 /* We enforce that all the SAPs are registered at this point */
118 if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) ||
119 (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST]))
120 return NOTIFY_BAD;
121
122 /* Check whether any sap is interested in the notifications */
123 for (i = 0; i < SAP_TOTAL; i++)
124 if (hip_sap_cont.sap[i]->sap_notifier) {
125 if (hip_sap_cont.sap[i]->sap_notifier(sdev, event))
126 return NOTIFY_BAD;
127 }
128
129 switch (event) {
130 case SCSC_WIFI_STOP:
131 SLSI_INFO(sdev, "Freeze HIP4\n");
132 mutex_lock(&sdev->hip.hip_mutex);
133 hip4_freeze(&sdev->hip4_inst);
134 mutex_unlock(&sdev->hip.hip_mutex);
135 break;
136
137 case SCSC_WIFI_FAILURE_RESET:
138 SLSI_INFO(sdev, "Set HIP4 up again\n");
139 mutex_lock(&sdev->hip.hip_mutex);
140 hip4_setup(&sdev->hip4_inst);
141 mutex_unlock(&sdev->hip.hip_mutex);
142 break;
143
144 case SCSC_WIFI_SUSPEND:
145 SLSI_INFO(sdev, "Suspend HIP4\n");
146 mutex_lock(&sdev->hip.hip_mutex);
147 hip4_suspend(&sdev->hip4_inst);
148 mutex_unlock(&sdev->hip.hip_mutex);
149 break;
150
151 case SCSC_WIFI_RESUME:
152 SLSI_INFO(sdev, "Resume HIP4\n");
153 mutex_lock(&sdev->hip.hip_mutex);
154 hip4_resume(&sdev->hip4_inst);
155 mutex_unlock(&sdev->hip.hip_mutex);
156 break;
157
158 case SCSC_WIFI_SUBSYSTEM_RESET:
159 case SCSC_WIFI_CHIP_READY:
160 break;
161
162 default:
163 SLSI_INFO(sdev, "Unknown event code %lu\n", event);
164 break;
165 }
166
167 return NOTIFY_OK;
168 }
169
170 static struct notifier_block cm_nb = {
171 .notifier_call = slsi_hip_service_notifier,
172 };
173
174 int slsi_hip_init(struct slsi_dev *sdev, struct device *dev)
175 {
176 SLSI_UNUSED_PARAMETER(dev);
177
178 memset(&sdev->hip4_inst, 0, sizeof(sdev->hip4_inst));
179
180 sdev->hip.sdev = sdev;
181 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED);
182 mutex_init(&sdev->hip.hip_mutex);
183
184 /* Register with the service notifier to receiver
185 * asynchronus messages such as SCSC_WIFI_STOP(Freeze), SCSC_WIFI_FAILURE_RESET i
186 */
187 slsi_wlan_service_notifier_register(&cm_nb);
188
189 return 0;
190 }
191
192 void slsi_hip_deinit(struct slsi_dev *sdev)
193 {
194 slsi_wlan_service_notifier_unregister(&cm_nb);
195 mutex_destroy(&sdev->hip.hip_mutex);
196 }
197
198 int slsi_hip_start(struct slsi_dev *sdev)
199 {
200 if (!sdev->maxwell_core) {
201 SLSI_ERR(sdev, "Maxwell core does not exist\n");
202 return -EINVAL;
203 }
204
205 SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[1/3]. Update HIP state (SLSI_HIP_STATE_STARTING)\n");
206 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STARTING);
207
208 SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[2/3]. Initialise HIP\n");
209 if (hip4_init(&sdev->hip4_inst)) {
210 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED);
211 SLSI_ERR(sdev, "hip4_init failed\n");
212 return -EINVAL;
213 }
214
215 SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[3/3]. Update HIP state (SLSI_HIP_STATE_STARTED)\n");
216 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STARTED);
217
218 return 0;
219 }
220
221 /* SAP rx proxy */
222 int slsi_hip_rx(struct slsi_dev *sdev, struct sk_buff *skb)
223 {
224 u16 pid;
225
226 /* We enforce that all the SAPs are registered at this point */
227 if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) ||
228 (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST]))
229 return -ENODEV;
230
231 /* Here we push a copy of the bare RECEIVED skb data also to the
232 * logring as a binary record.
233 * Note that bypassing UDI subsystem as a whole means we are losing:
234 * UDI filtering / UDI Header INFO / UDI QueuesFrames Throttling /
235 * UDI Skb Asynchronous processing
236 * We keep split DATA/CTRL path.
237 */
238 if (fapi_is_ma(skb))
239 SCSC_BIN_TAG_DEBUG(BIN_WIFI_DATA_RX, skb->data, skb->len);
240 else
241 SCSC_BIN_TAG_DEBUG(BIN_WIFI_CTRL_RX, skb->data, skb->len);
242 /* Udi test : If pid in UDI range then pass to UDI and ignore */
243 slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_TO_HOST);
244 pid = fapi_get_u16(skb, receiver_pid);
245 if (pid >= SLSI_TX_PROCESS_ID_UDI_MIN && pid <= SLSI_TX_PROCESS_ID_UDI_MAX) {
246 slsi_kfree_skb(skb);
247 return 0;
248 }
249
250 if (fapi_is_ma(skb))
251 return hip_sap_cont.sap[SAP_MA]->sap_handler(sdev, skb);
252
253 if (fapi_is_mlme(skb))
254 return hip_sap_cont.sap[SAP_MLME]->sap_handler(sdev, skb);
255
256 if (fapi_is_debug(skb))
257 return hip_sap_cont.sap[SAP_DBG]->sap_handler(sdev, skb);
258
259 if (fapi_is_test(skb))
260 return hip_sap_cont.sap[SAP_TST]->sap_handler(sdev, skb);
261
262 return -EIO;
263 }
264
265 /* Only DATA plane will look at the returning FB to account BoT */
266 int slsi_hip_tx_done(struct slsi_dev *sdev, u16 colour)
267 {
268 return hip_sap_cont.sap[SAP_MA]->sap_txdone(sdev, colour);
269 }
270
271 int slsi_hip_setup(struct slsi_dev *sdev)
272 {
273 /* Setup hip4 after initialization */
274 return hip4_setup(&sdev->hip4_inst);
275 }
276
277 #ifdef CONFIG_SCSC_SMAPPER
278 int slsi_hip_consume_smapper_entry(struct slsi_dev *sdev, struct sk_buff *skb)
279 {
280 return hip4_smapper_consume_entry(sdev, &sdev->hip4_inst, skb);
281 }
282
283 struct sk_buff *slsi_hip_get_skb_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb)
284 {
285 return hip4_smapper_get_skb(sdev, &sdev->hip4_inst, skb);
286 }
287
288 void *slsi_hip_get_skb_data_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb)
289 {
290 return hip4_smapper_get_skb_data(sdev, &sdev->hip4_inst, skb);
291 }
292 #endif
293
294 int slsi_hip_stop(struct slsi_dev *sdev)
295 {
296 mutex_lock(&sdev->hip.hip_mutex);
297 SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "Update HIP state (SLSI_HIP_STATE_STOPPING)\n");
298 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPING);
299
300 hip4_deinit(&sdev->hip4_inst);
301
302 SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "Update HIP state (SLSI_HIP_STATE_STOPPED)\n");
303 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED);
304
305 mutex_unlock(&sdev->hip.hip_mutex);
306 return 0;
307 }