blob: 777b719363b1584209720371411c58265fa470c2 [file] [log] [blame]
Suman Ghosh85f353a2019-06-03 14:47:32 +05301/*
2 **************************************************************************
Kyle Swensonab36fae2021-05-21 08:38:22 -06003 * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
Suman Ghosh85f353a2019-06-03 14:47:32 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17 /*
18 * nss_clmap.c
19 * NSS clmap driver interface APIs
20 */
21#include "nss_core.h"
22#include "nss_clmap.h"
23#include "nss_cmn.h"
24#include "nss_tx_rx_common.h"
25#include "nss_clmap_stats.h"
Kyle Swensonab36fae2021-05-21 08:38:22 -060026#include "nss_clmap_strings.h"
Suman Ghosh85f353a2019-06-03 14:47:32 +053027#include "nss_clmap_log.h"
28
29#define NSS_CLMAP_TX_TIMEOUT 3000
30
31/*
32 * Private data structure
33 */
34static struct nss_clmap_pvt {
35 struct semaphore sem; /* Semaphore structure. */
36 struct completion complete; /* Completion structure. */
37 int response; /* Response from FW. */
38 void *cb; /* Original cb for msgs. */
39 void *app_data; /* Original app_data for msgs. */
40} clmap_pvt;
41
42/*
43 * nss_clmap_verify_if_num()
44 * Verify if_num passed to us.
45 */
46static bool nss_clmap_verify_if_num(uint32_t if_num)
47{
48 uint32_t type = nss_dynamic_interface_get_type(nss_clmap_get_ctx(), if_num);
49
50 return ((type == NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_US) ||
51 (type == NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_DS));
52}
53
54/*
55 * nss_clmap_callback()
56 * Callback to handle the completion of NSS->HLOS messages.
57 */
58static void nss_clmap_callback(void *app_data, struct nss_clmap_msg *nclm)
59{
60 clmap_pvt.response = NSS_TX_SUCCESS;
61 clmap_pvt.cb = NULL;
62 clmap_pvt.app_data = NULL;
63
64 if (nclm->cm.response != NSS_CMN_RESPONSE_ACK) {
65 nss_warning("clmap Error response %d\n", nclm->cm.response);
66 clmap_pvt.response = nclm->cm.response;
67 }
68
69 /*
70 * Write memory barrier.
71 */
72 smp_wmb();
73 complete(&clmap_pvt.complete);
74}
75
76/*
77 * nss_clmap_handler()
78 * Handle NSS -> HLOS messages for clmap.
79 */
80static void nss_clmap_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
81{
82 struct nss_clmap_msg *nclm = (struct nss_clmap_msg *)ncm;
83 nss_clmap_msg_callback_t cb;
84
85 BUG_ON(!nss_clmap_verify_if_num(ncm->interface));
86 NSS_VERIFY_CTX_MAGIC(nss_ctx);
87
88 /*
89 * Is this a valid request/response packet?
90 */
91 if (ncm->type >= NSS_CLMAP_MSG_TYPE_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060092 nss_warning("%px: received invalid message %d for clmap interface", nss_ctx, ncm->type);
Suman Ghosh85f353a2019-06-03 14:47:32 +053093 return;
94 }
95
96 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_clmap_msg)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060097 nss_warning("%px: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Suman Ghosh85f353a2019-06-03 14:47:32 +053098 return;
99 }
100
101 /*
102 * Trace messages.
103 */
104 nss_core_log_msg_failures(nss_ctx, ncm);
105 nss_clmap_log_rx_msg(nclm);
106
107 switch (nclm->cm.type) {
108 case NSS_CLMAP_MSG_TYPE_SYNC_STATS:
109 nss_clmap_stats_sync(nss_ctx, &nclm->msg.stats, ncm->interface);
Kyle Swensonab36fae2021-05-21 08:38:22 -0600110 nss_clmap_stats_notify(nss_ctx, ncm->interface);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530111 break;
112 }
113
114 /*
115 * Update the callback and app_data for NOTIFY messages.
116 */
117 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600118 ncm->cb = (nss_ptr_t)nss_core_get_msg_handler(nss_ctx, ncm->interface);
119 ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[ncm->interface].app_data;
Suman Ghosh85f353a2019-06-03 14:47:32 +0530120 }
121
122 /*
123 * Do we have a callback
124 */
125 cb = (nss_clmap_msg_callback_t)ncm->cb;
126 if (!cb) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600127 nss_trace("%px: cb is null for interface %d", nss_ctx, ncm->interface);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530128 return;
129 }
130
131 cb((void *)ncm->app_data, ncm);
132}
133
134/*
135 * nss_clmap_tx_msg()
136 * Transmit a clmap message to NSS FW. Don't call this from softirq/interrupts.
137 */
138nss_tx_status_t nss_clmap_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_clmap_msg *msg)
139{
140 struct nss_cmn_msg *ncm = &msg->cm;
141
142 if (!nss_clmap_verify_if_num(msg->cm.interface)) {
143 return NSS_TX_FAILURE_BAD_PARAM;
144 }
145
146 if (ncm->type >= NSS_CLMAP_MSG_TYPE_MAX) {
147 return NSS_TX_FAILURE_BAD_PARAM;
148 }
149
150 /*
151 * Trace messages.
152 */
153 nss_clmap_log_tx_msg(msg);
154
155 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
156}
157EXPORT_SYMBOL(nss_clmap_tx_msg);
158
159/*
160 * nss_clmap_tx_msg_sync()
161 * Transmit a clmap message to NSS firmware synchronously.
162 */
163nss_tx_status_t nss_clmap_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_clmap_msg *nclm)
164{
165 nss_tx_status_t status;
166 int ret;
167
168 down(&clmap_pvt.sem);
169 nclm->cm.cb = (nss_ptr_t)nss_clmap_callback;
170 nclm->cm.app_data = (nss_ptr_t)NULL;
171
172 status = nss_clmap_tx_msg(nss_ctx, nclm);
173 if (status != NSS_TX_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600174 nss_warning("%px: clmap_tx_msg failed\n", nss_ctx);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530175 up(&clmap_pvt.sem);
176 return status;
177 }
178
179 ret = wait_for_completion_timeout(&clmap_pvt.complete, msecs_to_jiffies(NSS_CLMAP_TX_TIMEOUT));
180 if (!ret) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600181 nss_warning("%px: clmap tx sync failed due to timeout\n", nss_ctx);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530182 clmap_pvt.response = NSS_TX_FAILURE;
183 }
184
185 status = clmap_pvt.response;
186 up(&clmap_pvt.sem);
187 return status;
188}
189EXPORT_SYMBOL(nss_clmap_tx_msg_sync);
190
191/*
192 * nss_clmap_tx_buf()
193 * Transmit data buffer (skb) to a NSS interface number
194 */
195nss_tx_status_t nss_clmap_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *buf, uint32_t if_num)
196{
197 BUG_ON(!nss_clmap_verify_if_num(if_num));
198
199 return nss_core_send_packet(nss_ctx, buf, if_num, H2N_BIT_FLAG_VIRTUAL_BUFFER);
200}
201EXPORT_SYMBOL(nss_clmap_tx_buf);
202
203/*
204 * nss_clmap_unregister()
205 * Un-register a clmap interface from NSS.
206 */
207bool nss_clmap_unregister(uint32_t if_num)
208{
209 struct nss_ctx_instance *nss_ctx;
Kyle Swensondd7b2962021-03-16 13:46:32 -0600210 int status;
Suman Ghosh85f353a2019-06-03 14:47:32 +0530211
212 nss_ctx = nss_clmap_get_ctx();
213 NSS_VERIFY_CTX_MAGIC(nss_ctx);
214
215 if (!nss_clmap_verify_if_num(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600216 nss_warning("%px: clmap unregister request received for invalid interface %d", nss_ctx, if_num);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530217 return false;
218 }
219
Kyle Swensondd7b2962021-03-16 13:46:32 -0600220 status = nss_core_unregister_msg_handler(nss_ctx, if_num);
221 if (status != NSS_CORE_STATUS_SUCCESS) {
222 nss_warning("%px: Failed to unregister handler for clmap NSS I/F:%u\n", nss_ctx, if_num);
223 return false;
224 }
225
Suman Ghosh85f353a2019-06-03 14:47:32 +0530226 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Kyle Swensondd7b2962021-03-16 13:46:32 -0600227 nss_core_unregister_handler(nss_ctx, if_num);
228 nss_clmap_stats_session_unregister(if_num);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530229
230 return true;
231}
232EXPORT_SYMBOL(nss_clmap_unregister);
233
234/*
235 * nss_clmap_register()
236 * Registers a clmap interface with the NSS.
237 */
238struct nss_ctx_instance *nss_clmap_register(uint32_t if_num,
239 uint32_t di_type,
240 nss_clmap_buf_callback_t data_cb,
241 nss_clmap_msg_callback_t notify_cb,
242 struct net_device *netdev,
243 uint32_t features)
244{
245 struct nss_ctx_instance *nss_ctx;
246 int core_status;
247 bool stats_status = false;
248
249 nss_ctx = nss_clmap_get_ctx();
250 NSS_VERIFY_CTX_MAGIC(nss_ctx);
251
252 if (!nss_clmap_verify_if_num(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600253 nss_warning("%px: clmap register request received for invalid interface %d", nss_ctx, if_num);
254 goto fail;
Suman Ghosh85f353a2019-06-03 14:47:32 +0530255 }
256
257 if (di_type == NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_US) {
258 stats_status = nss_clmap_stats_session_register(if_num, NSS_CLMAP_INTERFACE_TYPE_US, netdev);
259 } else {
260 stats_status = nss_clmap_stats_session_register(if_num, NSS_CLMAP_INTERFACE_TYPE_DS, netdev);
261 }
262
263 if (!stats_status) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600264 nss_warning("%px: statistics registration failed for interface: %d\n", nss_ctx, if_num);
265 goto fail;
Suman Ghosh85f353a2019-06-03 14:47:32 +0530266 }
267
268 core_status = nss_core_register_handler(nss_ctx, if_num, nss_clmap_msg_handler, (void *)netdev);
269 if (core_status != NSS_CORE_STATUS_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600270 goto core_reg_fail;
271 }
272
273 core_status = nss_core_register_msg_handler(nss_ctx, if_num, notify_cb);
274 if (core_status != NSS_CORE_STATUS_SUCCESS) {
275 goto msg_reg_fail;
Suman Ghosh85f353a2019-06-03 14:47:32 +0530276 }
277
278 nss_core_register_subsys_dp(nss_ctx, if_num, data_cb, NULL, (void *)netdev, netdev, features);
279 nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num, di_type);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530280
281 return nss_ctx;
Kyle Swensondd7b2962021-03-16 13:46:32 -0600282
283msg_reg_fail:
284 nss_core_unregister_handler(nss_ctx, if_num);
285core_reg_fail:
286 nss_clmap_stats_session_unregister(if_num);
287 nss_warning("%px: NSS core register handler failed for if_num:%d with error :%d", nss_ctx, if_num, core_status);
288fail:
289 return NULL;
290
Suman Ghosh85f353a2019-06-03 14:47:32 +0530291}
292EXPORT_SYMBOL(nss_clmap_register);
293
294/*
295 * nss_clmap_ifnum_with_core_id()
296 * Append core ID to clmap interface num.
297 */
298int nss_clmap_ifnum_with_core_id(int if_num)
299{
300 struct nss_ctx_instance *nss_ctx = nss_clmap_get_ctx();
301
302 NSS_VERIFY_CTX_MAGIC(nss_ctx);
303 if (!nss_is_dynamic_interface(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600304 nss_warning("%px: Invalid if_num: %d, must be a dynamic interface\n", nss_ctx, if_num);
Suman Ghosh85f353a2019-06-03 14:47:32 +0530305 return 0;
306 }
307 return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
308}
309EXPORT_SYMBOL(nss_clmap_ifnum_with_core_id);
310
311/*
312 * nss_clmap_msg_init()
313 * Initialize clmap message.
314 */
315void nss_clmap_msg_init(struct nss_clmap_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len,
316 nss_clmap_msg_callback_t cb, void *app_data)
317{
318 nss_cmn_msg_init(&ncm->cm, if_num, type, len, (void*)cb, app_data);
319}
320EXPORT_SYMBOL(nss_clmap_msg_init);
321
322/*
323 * nss_clmap_get_ctx()
324 * Return a clmap NSS context.
325 */
326struct nss_ctx_instance *nss_clmap_get_ctx()
327{
328 struct nss_ctx_instance *nss_ctx;
329
330 nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.clmap_handler_id];
331 return nss_ctx;
332}
333EXPORT_SYMBOL(nss_clmap_get_ctx);
334
335/*
336 * nss_clmap_init()
337 * Initializes clmap. Gets called from nss_init.c.
338 */
339void nss_clmap_init()
340{
Suman Ghosh85f353a2019-06-03 14:47:32 +0530341 sema_init(&clmap_pvt.sem, 1);
342 init_completion(&clmap_pvt.complete);
Kyle Swensonab36fae2021-05-21 08:38:22 -0600343
344 nss_clmap_stats_dentry_create();
345 nss_clmap_strings_dentry_create();
Suman Ghosh85f353a2019-06-03 14:47:32 +0530346}