blob: ff5336333f3dd7d69d3e5c2474640e5502135bf8 [file] [log] [blame]
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +05301/*
2 **************************************************************************
Kyle Swensonab36fae2021-05-21 08:38:22 -06003 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +05304 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
16 **************************************************************************
17 */
18
19#include "nss_tx_rx_common.h"
20#include "nss_tls_log.h"
Kyle Swensonab36fae2021-05-21 08:38:22 -060021#include "nss_tls_stats.h"
22#include "nss_tls_strings.h"
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053023
24#define NSS_TLS_INTERFACE_MAX_LONG BITS_TO_LONGS(NSS_MAX_NET_INTERFACES)
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053025#define NSS_TLS_TX_TIMEOUT 3000 /* 3 Seconds */
26
27/*
28 * Private data structure for handling synchronous messaging.
29 */
30static struct nss_tls_pvt {
31 struct semaphore sem;
32 struct completion complete;
33 struct nss_tls_msg ntcm;
34 unsigned long if_map[NSS_TLS_INTERFACE_MAX_LONG];
35} tls_pvt;
36
37/*
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053038 * nss_tls_verify_ifnum()
39 * Verify if the interface number is a TLS interface.
40 */
41static bool nss_tls_verify_ifnum(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
42{
43 enum nss_dynamic_interface_type type = nss_dynamic_interface_get_type(nss_ctx, if_num);
44
45 if (type == NSS_DYNAMIC_INTERFACE_TYPE_TLS_INNER)
46 return true;
47
48 if (type == NSS_DYNAMIC_INTERFACE_TYPE_TLS_OUTER)
49 return true;
50
51 if (if_num == NSS_TLS_INTERFACE)
52 return true;
53
54 return false;
55}
56
57/*
58 * nss_tls_handler()
59 * Handle NSS -> HLOS messages for tls tunnel
60 */
61static void nss_tls_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *data)
62{
63 nss_tls_msg_callback_t cb;
64 void *app_data;
65
66 NSS_VERIFY_CTX_MAGIC(nss_ctx);
67
Kyle Swensondd7b2962021-03-16 13:46:32 -060068 nss_trace("%px: handle event for interface num :%u", nss_ctx, ncm->interface);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053069
70 /*
71 * Is this a valid request/response packet?
72 */
73 if (ncm->type >= NSS_TLS_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060074 nss_warning("%px:Bad message type(%d) for TLS interface %d", nss_ctx, ncm->type, ncm->interface);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053075 return;
76 }
77
78 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_tls_msg)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060079 nss_warning("%px:Bad message length(%d)", nss_ctx, ncm->len);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053080 return;
81 }
82
Kyle Swensonab36fae2021-05-21 08:38:22 -060083 if (ncm->type == NSS_TLS_MSG_TYPE_CTX_SYNC) {
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053084 nss_tls_stats_sync(nss_ctx, ncm);
Kyle Swensonab36fae2021-05-21 08:38:22 -060085 nss_tls_stats_notify(nss_ctx, ncm->interface);
86 }
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053087
88 /*
89 * Update the callback and app_data for NOTIFY messages
90 */
91 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060092 ncm->cb = (nss_ptr_t)nss_core_get_msg_handler(nss_ctx, ncm->interface);
93 ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[ncm->interface].app_data;
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +053094 }
95
96 /*
97 * Log failures
98 */
99 nss_core_log_msg_failures(nss_ctx, ncm);
100
101 /*
102 * Trace messages.
103 */
104 nss_tls_log_rx_msg((struct nss_tls_msg *)ncm);
105
106 /*
107 * Callback
108 */
109 cb = (nss_tls_msg_callback_t)ncm->cb;
110 app_data = (void *)ncm->app_data;
111
112 /*
113 * Call TLS session callback
114 */
115 if (!cb) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600116 nss_warning("%px: No callback for tls session interface %d", nss_ctx, ncm->interface);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530117 return;
118 }
119
Kyle Swensondd7b2962021-03-16 13:46:32 -0600120 nss_trace("%px: calling tlsmgr event handler(%u)", nss_ctx, ncm->interface);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530121 cb(app_data, ncm);
122}
123
124/*
125 * nss_tls_sync_resp()
126 * Callback to handle the completion of HLOS-->NSS messages.
127 */
128static void nss_tls_sync_resp(void *app_data, struct nss_cmn_msg *ncm)
129{
130 struct nss_tls_msg *pvt_msg = app_data;
131 struct nss_tls_msg *resp_msg = container_of(ncm, struct nss_tls_msg, cm);
132
133 /*
134 * Copy response message to pvt message
135 */
136 memcpy(pvt_msg, resp_msg, sizeof(*resp_msg));
137
138 /*
139 * Write memory barrier
140 */
141 smp_wmb();
142
143 complete(&tls_pvt.complete);
144}
145
146/*
Kyle Swensonab36fae2021-05-21 08:38:22 -0600147 * nss_tls_ifmap_get()
148 * Return TLS active interfaces map.
149 */
150unsigned long *nss_tls_ifmap_get(void)
151{
152 return tls_pvt.if_map;
153}
154
155/*
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530156 * nss_tls_tx_buf()
157 * Transmit buffer over TLS interface
158 */
159nss_tx_status_t nss_tls_tx_buf(struct sk_buff *skb, uint32_t if_num, struct nss_ctx_instance *nss_ctx)
160{
161 int32_t status;
162
163 if (!nss_tls_verify_ifnum(nss_ctx, if_num))
164 return NSS_TX_FAILURE;
165
166 NSS_VERIFY_CTX_MAGIC(nss_ctx);
167
168 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600169 nss_warning("%px: tx_data packet dropped as core not ready", nss_ctx);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530170 return NSS_TX_FAILURE_NOT_READY;
171 }
172
173 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_H2N_DATA_QUEUE, H2N_BUFFER_PACKET, 0);
174 switch (status) {
175 case NSS_CORE_STATUS_SUCCESS:
176 break;
177
178 case NSS_CORE_STATUS_FAILURE_QUEUE: /* queue full condition */
Kyle Swensondd7b2962021-03-16 13:46:32 -0600179 nss_warning("%px: H2N queue full for tx_buf", nss_ctx);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530180 return NSS_TX_FAILURE_QUEUE;
181
182 default:
Kyle Swensondd7b2962021-03-16 13:46:32 -0600183 nss_warning("%px: general failure for tx_buf", nss_ctx);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530184 return NSS_TX_FAILURE;
185 }
186
187 /*
188 * Kick the NSS awake so it can process our new entry.
189 */
190 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
191
192 return NSS_TX_SUCCESS;
193}
194EXPORT_SYMBOL(nss_tls_tx_buf);
195
196/*
197 * nss_tls_tx_msg()
198 * Transmit a TLS message to NSS firmware
199 */
200nss_tx_status_t nss_tls_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_tls_msg *msg)
201{
202 struct nss_cmn_msg *ncm = &msg->cm;
203
204 if (ncm->type >= NSS_TLS_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600205 nss_warning("%px: tls message type out of range: %d", nss_ctx, ncm->type);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530206 return NSS_TX_FAILURE;
207 }
208
209 if (!nss_tls_verify_ifnum(nss_ctx, ncm->interface)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600210 nss_warning("%px: tls message interface is bad: %u", nss_ctx, ncm->interface);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530211 return NSS_TX_FAILURE;
212 }
213
214 /*
215 * Trace messages.
216 */
217 nss_tls_log_tx_msg(msg);
218
219 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
220}
221EXPORT_SYMBOL(nss_tls_tx_msg);
222
223/*
224 * nss_tls_tx_msg_sync()
225 * Transmit a TLS message to NSS firmware synchronously.
226 */
227nss_tx_status_t nss_tls_tx_msg_sync(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
228 enum nss_tls_msg_type type, uint16_t len,
229 struct nss_tls_msg *ntcm)
230{
231 struct nss_tls_msg *local_ntcm = &tls_pvt.ntcm;
232 nss_tx_status_t status;
233 int ret = 0;
234
235 /*
236 * Length of the message should be the based on type
237 */
238 if (len > sizeof(struct nss_tls_msg)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600239 nss_warning("%px: Invalid message length(%u), type (%d), I/F(%u)\n", nss_ctx, len, type, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530240 return NSS_TX_FAILURE;
241 }
242
243 down(&tls_pvt.sem);
244
245 /*
246 * We need to copy the message content into the actual message
247 * to be sent to NSS
248 */
249 memset(local_ntcm, 0, sizeof(*local_ntcm));
250
251 nss_tls_msg_init(local_ntcm, if_num, type, len, nss_tls_sync_resp, local_ntcm);
252 memcpy(&local_ntcm->msg, &ntcm->msg, len);
253
254 status = nss_tls_tx_msg(nss_ctx, local_ntcm);
255 if (status != NSS_TX_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600256 nss_warning("%px: Failed to send message\n", nss_ctx);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530257 goto done;
258 }
259
260 ret = wait_for_completion_timeout(&tls_pvt.complete, msecs_to_jiffies(NSS_TLS_TX_TIMEOUT));
261 if (!ret) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600262 nss_warning("%px: Failed to receive response, timeout(%d)\n", nss_ctx, ret);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530263 status = NSS_TX_FAILURE_NOT_READY;
264 goto done;
265 }
266
267 /*
268 * Read memory barrier
269 */
270 smp_rmb();
271
272 if (local_ntcm->cm.response != NSS_CMN_RESPONSE_ACK) {
273 status = NSS_TX_FAILURE;
274 ntcm->cm.response = local_ntcm->cm.response;
275 ntcm->cm.error = local_ntcm->cm.error;
276 goto done;
277 }
278
279 /*
280 * Copy the message received
281 */
282 memcpy(&ntcm->msg, &local_ntcm->msg, len);
283
284done:
285 up(&tls_pvt.sem);
286 return status;
287}
288EXPORT_SYMBOL(nss_tls_tx_msg_sync);
289
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530290/*
291 * nss_tls_notify_register()
292 * Register a handler for notification from NSS firmware.
293 */
294struct nss_ctx_instance *nss_tls_notify_register(uint32_t if_num, nss_tls_msg_callback_t ev_cb, void *app_data)
295{
296 struct nss_ctx_instance *nss_ctx = nss_tls_get_context();
297 uint32_t ret;
298
299 BUG_ON(!nss_ctx);
300
301 ret = nss_core_register_handler(nss_ctx, if_num, nss_tls_handler, app_data);
302 if (ret != NSS_CORE_STATUS_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600303 nss_warning("%px: unable to register event handler for interface(%u)", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530304 return NULL;
305 }
306
Kyle Swensondd7b2962021-03-16 13:46:32 -0600307 ret = nss_core_register_msg_handler(nss_ctx, if_num, ev_cb);
308 if (ret != NSS_CORE_STATUS_SUCCESS) {
309 nss_core_unregister_handler(nss_ctx, if_num);
310 nss_warning("%px: unable to register event handler for interface(%u)", nss_ctx, if_num);
311 return NULL;
312 }
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530313
314 return nss_ctx;
315}
316EXPORT_SYMBOL(nss_tls_notify_register);
317
318/*
319 * nss_tls_notify_unregister()
320 * Unregister notification callback handler.
321 */
322void nss_tls_notify_unregister(uint32_t if_num)
323{
324 struct nss_ctx_instance *nss_ctx = nss_tls_get_context();
325 uint32_t ret;
326
327 BUG_ON(!nss_ctx);
328
Kyle Swensondd7b2962021-03-16 13:46:32 -0600329 ret = nss_core_unregister_msg_handler(nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530330 if (ret != NSS_CORE_STATUS_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600331 nss_warning("%px: unable to un register event handler for interface(%u)", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530332 return;
333 }
334
Kyle Swensondd7b2962021-03-16 13:46:32 -0600335 ret = nss_core_unregister_handler(nss_ctx, if_num);
336 if (ret != NSS_CORE_STATUS_SUCCESS) {
337 nss_warning("%px: unable to un register event handler for interface(%u)", nss_ctx, if_num);
338 return;
339 }
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530340
341 return;
342}
343EXPORT_SYMBOL(nss_tls_notify_unregister);
344
345/*
346 * nss_tls_register_if()
347 * Register data and event callback handlers for dynamic interface.
348 */
349struct nss_ctx_instance *nss_tls_register_if(uint32_t if_num,
350 nss_tls_data_callback_t data_cb,
351 nss_tls_msg_callback_t ev_cb,
352 struct net_device *netdev,
353 uint32_t features,
354 uint32_t type,
355 void *app_data)
356{
357 struct nss_ctx_instance *nss_ctx = nss_tls_get_context();
358 uint32_t ret;
359
360 if (!nss_tls_verify_ifnum(nss_ctx, if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600361 nss_warning("%px: TLS Interface is not dynamic:%u", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530362 return NULL;
363 }
364
365 if (nss_ctx->subsys_dp_register[if_num].ndev) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600366 nss_warning("%px: Cannot find free slot for TLS NSS I/F:%u", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530367 return NULL;
368 }
369
370 nss_core_register_subsys_dp(nss_ctx, if_num, data_cb, NULL, app_data, netdev, features);
371 nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num, type);
372
373 ret = nss_core_register_handler(nss_ctx, if_num, nss_tls_handler, app_data);
374 if (ret != NSS_CORE_STATUS_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600375 nss_warning("%px: unable to register event handler for interface(%u)", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530376 return NULL;
377 }
378
Kyle Swensondd7b2962021-03-16 13:46:32 -0600379 ret = nss_core_register_msg_handler(nss_ctx, if_num, ev_cb);
380 if (ret != NSS_CORE_STATUS_SUCCESS) {
381 nss_core_unregister_handler(nss_ctx, if_num);
382 nss_warning("%px: unable to register event handler for interface(%u)", nss_ctx, if_num);
383 return NULL;
384 }
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530385
386 /*
387 * Atomically set the bitmap for the interface number
388 */
389 set_bit(if_num, tls_pvt.if_map);
390 return nss_ctx;
391}
392EXPORT_SYMBOL(nss_tls_register_if);
393
394/*
395 * nss_tls_unregister_if()
396 * Unregister data and event callback handlers for the interface.
397 */
398void nss_tls_unregister_if(uint32_t if_num)
399{
400 struct nss_ctx_instance *nss_ctx = nss_tls_get_context();
Kyle Swensondd7b2962021-03-16 13:46:32 -0600401 uint32_t ret;
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530402
403 if (!nss_ctx->subsys_dp_register[if_num].ndev) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600404 nss_warning("%px: Cannot find registered netdev for TLS NSS I/F:%u", nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530405 return;
406 }
407
408 /*
409 * Atomically clear the bitmap for the interface number
410 */
411 clear_bit(if_num, tls_pvt.if_map);
412
Kyle Swensondd7b2962021-03-16 13:46:32 -0600413 ret = nss_core_unregister_msg_handler(nss_ctx, if_num);
414 if (ret != NSS_CORE_STATUS_SUCCESS) {
415 nss_warning("%px: unable to un register event handler for interface(%u)", nss_ctx, if_num);
416 return;
417 }
418
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530419 nss_core_unregister_handler(nss_ctx, if_num);
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530420
421 nss_core_unregister_subsys_dp(nss_ctx, if_num);
422}
423EXPORT_SYMBOL(nss_tls_unregister_if);
424
425/*
426 * nss_tls_get_context()
427 * Return TLS NSS context.
428 */
429struct nss_ctx_instance *nss_tls_get_context(void)
430{
431 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tls_handler_id];
432}
433EXPORT_SYMBOL(nss_tls_get_context);
434
435/*
436 * nss_tls_get_device()
437 * Gets the original device from probe.
438 */
439struct device *nss_tls_get_dev(struct nss_ctx_instance *nss_ctx)
440{
441 return nss_ctx->dev;
442}
443EXPORT_SYMBOL(nss_tls_get_dev);
444
445/*
446 * nss_tls_msg_init()
447 * Initialize nss_tls msg to be sent asynchronously.
448 */
449void nss_tls_msg_init(struct nss_tls_msg *ncm, uint32_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
450{
451 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
452}
453EXPORT_SYMBOL(nss_tls_msg_init);
454
455/*
456 * nss_tls_msg_sync_init()
457 * Initialize nss_tls_msg to be sent synchronously.
458 */
459void nss_tls_msg_sync_init(struct nss_tls_msg *ncm, uint32_t if_num, uint32_t type, uint32_t len)
460{
461 nss_cmn_msg_sync_init(&ncm->cm, if_num, type, len);
462}
463EXPORT_SYMBOL(nss_tls_msg_sync_init);
464
465/*
466 * nss_tls_register_handler()
467 * TLS initialization.
468 */
469void nss_tls_register_handler(void)
470{
471 sema_init(&tls_pvt.sem, 1);
472 init_completion(&tls_pvt.complete);
Kyle Swensonab36fae2021-05-21 08:38:22 -0600473 nss_tls_stats_dentry_create();
474 nss_tls_strings_dentry_create();
Ratheesh Kannoth65edb2d2020-01-23 09:08:46 +0530475}