blob: e24ddca016dd72c662ce71462a0ff45354d36087 [file] [log] [blame]
Suruchi Sumanf7e29822019-09-11 11:53:53 +05301/*
2 ***************************************************************************
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 *
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/*
20 * nss_match.c
21 */
22
23#include "nss_tx_rx_common.h"
24#include "nss_match_log.h"
25#include "nss_match_stats.h"
26
27#define NSS_MATCH_TX_TIMEOUT 1000 /* 1 Seconds */
28
29/*
30 * Private data structure for match interface
31 */
32static struct nss_match_pvt {
33 struct semaphore sem;
34 struct completion complete;
35 int32_t response;
36} match_pvt;
37
38/*
39 * nss_get_match_context()
40 */
41struct nss_ctx_instance *nss_match_get_context(void)
42{
43 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.match_handler_id];
44}
45EXPORT_SYMBOL(nss_match_get_context);
46
47/*
48 * nss_match_verify_if_num()
49 */
50static bool nss_match_verify_if_num(uint32_t if_num)
51{
52 if (nss_is_dynamic_interface(if_num) == false) {
53 return false;
54 }
55
56 if (nss_dynamic_interface_get_type(nss_match_get_context(), if_num)
57 != NSS_DYNAMIC_INTERFACE_TYPE_MATCH) {
58 return false;
59 }
60
61 return true;
62}
63
64/*
65 * nss_match_msg_sync_callback
66 * Callback to handle the completion of NSS to HLOS messages.
67 */
68static void nss_match_msg_sync_callback(void *app_data, struct nss_match_msg *matchm)
69{
70 match_pvt.response = NSS_TX_SUCCESS;
71
72 if (matchm->cm.response != NSS_CMN_RESPONSE_ACK) {
73 nss_warning("Match Error response %d\n", matchm->cm.response);
74 match_pvt.response = NSS_TX_FAILURE;
75 }
76
77 complete(&match_pvt.complete);
78}
79
80/*
81 * nss_match_msg_tx()
82 * Sends message to NSS.
83 */
84static nss_tx_status_t nss_match_msg_tx(struct nss_ctx_instance *nss_ctx, struct nss_match_msg *matchm)
85{
86 struct nss_cmn_msg *ncm = &matchm->cm;
87
88 NSS_VERIFY_CTX_MAGIC(nss_ctx);
89
90 /*
91 * Trace Messages
92 */
93 nss_match_log_tx_msg(matchm);
94
95 /*
96 * Sanity check the message
97 */
98 if (!nss_match_verify_if_num(ncm->interface)) {
99 nss_warning("%p: Tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
100 return NSS_TX_FAILURE;
101 }
102
103 if (ncm->type > NSS_MATCH_MSG_MAX) {
104 nss_warning("%p: Message type out of range: %d", nss_ctx, ncm->type);
105 return NSS_TX_FAILURE;
106 }
107
108 return nss_core_send_cmd(nss_ctx, matchm, sizeof(*matchm), NSS_NBUF_PAYLOAD_SIZE);
109}
110
111/*
112 * nss_match_handler()
113 * Handle NSS to HLOS messages for Match node
114 */
115static void nss_match_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
116{
117 struct nss_match_msg *nem = (struct nss_match_msg *)ncm;
118
119 nss_match_msg_sync_callback_t cb;
120 void *ctx;
121
122 NSS_VERIFY_CTX_MAGIC(nss_ctx);
123 BUG_ON(!nss_match_verify_if_num(ncm->interface));
124
125 /*
126 * Trace Messages
127 */
128 nss_match_log_rx_msg(nem);
129
130 /*
131 * Is this a valid request/response packet?
132 */
133 if (nem->cm.type >= NSS_MATCH_MSG_MAX) {
134 nss_warning("%p: Received invalid message %d for MATCH interface", nss_ctx, nem->cm.type);
135 return;
136 }
137
138 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_match_msg)) {
139 nss_warning("%p: Unexpected message length: %d, on interface: %d",
140 nss_ctx, nss_cmn_get_msg_len(ncm), ncm->interface);
141 return;
142 }
143
144 switch (nem->cm.type) {
145 case NSS_MATCH_STATS_SYNC:
146
147 /*
148 * Update common node statistics
149 */
150 nss_match_stats_sync(nss_ctx, nem);
151 }
152
153 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
154 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
155 }
156
157 /*
158 * Log failures
159 */
160 nss_core_log_msg_failures(nss_ctx, ncm);
161
162 /*
163 * Do we have a call back
164 */
165 if (!ncm->cb) {
166 return;
167 }
168
169 /*
170 * callback
171 */
172 cb = (nss_match_msg_sync_callback_t)ncm->cb;
173 ctx = (void *)ncm->app_data;
174
175 cb(ctx, nem);
176}
177
178/*
179 * nss_match_msg_tx_sync()
180 * Send a message to match node and wait for the response.
181 */
182nss_tx_status_t nss_match_msg_tx_sync(struct nss_ctx_instance *nss_ctx, struct nss_match_msg *matchm)
183{
184 nss_tx_status_t status;
185 int ret = 0;
186 down(&match_pvt.sem);
187
188 matchm->cm.cb = (nss_ptr_t)nss_match_msg_sync_callback;
189 matchm->cm.app_data = (nss_ptr_t)NULL;
190
191 status = nss_match_msg_tx(nss_ctx, matchm);
192 if (status != NSS_TX_SUCCESS) {
193 nss_warning("%p: nss_match_msg_tx failed\n", nss_ctx);
194 up(&match_pvt.sem);
195 return status;
196 }
197
198 ret = wait_for_completion_timeout(&match_pvt.complete, msecs_to_jiffies(NSS_MATCH_TX_TIMEOUT));
199 if (!ret) {
200 nss_warning("%p: MATCH tx failed due to timeout\n", nss_ctx);
201 match_pvt.response = NSS_TX_FAILURE;
202 }
203
204 status = match_pvt.response;
205 up(&match_pvt.sem);
206
207 return status;
208}
209EXPORT_SYMBOL(nss_match_msg_tx_sync);
210
211/*
212 * nss_match_register_instance()
213 * Registers match instance.
214 */
215struct nss_ctx_instance *nss_match_register_instance(int if_num, nss_match_msg_sync_callback_t notify_cb)
216{
217 struct nss_ctx_instance *nss_ctx;
218
219 nss_ctx = nss_match_get_context();
220 NSS_VERIFY_CTX_MAGIC(nss_ctx);
221
222 if (!nss_match_verify_if_num(if_num)) {
223 nss_warning("%p: Incorrect interface number: %d", nss_ctx, if_num);
224 return NULL;
225 }
226
227 nss_core_register_handler(nss_ctx, if_num, nss_match_handler, NULL);
228 nss_top_main.if_rx_msg_callback[if_num] = (nss_if_rx_msg_callback_t)notify_cb;
229
230 if (!nss_match_ifnum_add(if_num)) {
231 nss_warning("Unable to add match inteface : %u\n", if_num);
232 nss_core_unregister_handler(nss_ctx, if_num);
233 nss_top_main.if_rx_msg_callback[if_num] = NULL;
234 return NULL;
235 }
236
237 return nss_ctx;
238}
239EXPORT_SYMBOL(nss_match_register_instance);
240
241/*
242 * nss_match_unregister_instance()
243 * Unregisters match instance.
244 */
245bool nss_match_unregister_instance(int if_num)
246{
247 struct nss_ctx_instance *nss_ctx;
248
249 nss_ctx = nss_match_get_context();
250 NSS_VERIFY_CTX_MAGIC(nss_ctx);
251
252 if (!nss_match_verify_if_num(if_num)) {
253 nss_warning("%p: Incorrect interface number: %d", nss_ctx, if_num);
254 return false;
255 }
256
257 nss_core_unregister_handler(nss_ctx, if_num);
258 nss_top_main.if_rx_msg_callback[if_num] = NULL;
259 nss_match_ifnum_delete(if_num);
260
261 return true;
262}
263EXPORT_SYMBOL(nss_match_unregister_instance);
264
265/*
266 * nss_match_msg_init()
267 * Initialize match message.
268 */
269void nss_match_msg_init(struct nss_match_msg *nmm, uint16_t if_num, uint32_t type, uint32_t len,
270 nss_match_msg_sync_callback_t cb, void *app_data)
271{
272 nss_cmn_msg_init(&nmm->cm, if_num, type, len, (void*)cb, app_data);
273}
274EXPORT_SYMBOL(nss_match_msg_init);
275
276/*
277 * nss_match_init()
278 * Initialize match.
279 */
280void nss_match_init()
281{
282 nss_match_stats_dentry_create();
283 sema_init(&match_pvt.sem, 1);
284 init_completion(&match_pvt.complete);
285}