blob: 3dc5679aae448ca8f0e286e4dbdb692142e280b5 [file] [log] [blame]
Amit Gupta316729b2016-08-12 12:21:15 +05301/*
2 **************************************************************************
Amit Gupta24a1ccb2018-02-26 18:32:35 +05303 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Amit Gupta316729b2016-08-12 12:21:15 +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#include "nss_ppe.h"
Yu Huang8c107082017-07-24 14:58:26 -070018#include "nss_ppe_stats.h"
Amit Gupta79c1c202017-06-30 15:28:13 +053019
Amit Gupta6c0f6412017-11-20 15:42:43 +053020DEFINE_SPINLOCK(nss_ppe_stats_lock);
21
Amit Guptacb1696b2017-11-13 13:09:06 +053022struct nss_ppe_stats_debug nss_ppe_debug_stats;
Amit Gupta6c0f6412017-11-20 15:42:43 +053023struct nss_ppe_pvt ppe_pvt;
Amit Guptacb1696b2017-11-13 13:09:06 +053024
Amit Gupta316729b2016-08-12 12:21:15 +053025/*
26 * nss_ppe_verify_ifnum()
27 * Verify PPE interface number.
28 */
29static inline bool nss_ppe_verify_ifnum(int if_num)
30{
31 return nss_is_dynamic_interface(if_num) || (if_num == NSS_PPE_INTERFACE);
32}
33
34/*
Amit Gupta1263b082017-07-06 14:22:57 +053035 * nss_ppe_callback()
36 * Callback to handle the completion of NSS->HLOS messages.
37 */
38static void nss_ppe_callback(void *app_data, struct nss_ppe_msg *npm)
39{
40 nss_ppe_msg_callback_t callback = (nss_ppe_msg_callback_t)ppe_pvt.cb;
41 void *data = ppe_pvt.app_data;
42
43 ppe_pvt.response = NSS_TX_SUCCESS;
44 ppe_pvt.cb = NULL;
45 ppe_pvt.app_data = NULL;
46
47 if (npm->cm.response != NSS_CMN_RESPONSE_ACK) {
48 nss_warning("ppe error response %d\n", npm->cm.response);
49 ppe_pvt.response = npm->cm.response;
50 }
51
52 if (callback) {
53 callback(data, npm);
54 }
55 complete(&ppe_pvt.complete);
56}
57
58/*
59 * nss_ppe_tx_msg()
60 * Transmit a ppe message to NSSFW
61 */
62nss_tx_status_t nss_ppe_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_ppe_msg *msg)
63{
Amit Gupta1263b082017-07-06 14:22:57 +053064 struct nss_cmn_msg *ncm = &msg->cm;
Amit Gupta1263b082017-07-06 14:22:57 +053065
66 /*
Sachin Shashidhardd7229c2018-08-07 17:33:42 -070067 * Trace messages.
68 */
69 nss_ppe_log_tx_msg(msg);
70
71 /*
Amit Gupta1263b082017-07-06 14:22:57 +053072 * Sanity check the message
73 */
74 if (ncm->type >= NSS_PPE_MSG_MAX) {
75 nss_warning("%p: message type out of range: %d\n", nss_ctx, ncm->type);
76 return NSS_TX_FAILURE;
77 }
78
Stephen Wang3e2dbd12018-03-14 17:28:17 -070079 if (!nss_ppe_verify_ifnum(ncm->interface)) {
80 nss_warning("%p: invalid interface %d\n", nss_ctx, ncm->interface);
Amit Gupta1263b082017-07-06 14:22:57 +053081 return NSS_TX_FAILURE;
82 }
83
Stephen Wang3e2dbd12018-03-14 17:28:17 -070084 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Amit Gupta1263b082017-07-06 14:22:57 +053085}
Amit Gupta1263b082017-07-06 14:22:57 +053086
87/*
88 * nss_ppe_tx_msg_sync()
89 * Transmit a ppe message to NSS firmware synchronously.
90 */
91nss_tx_status_t nss_ppe_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_ppe_msg *npm)
92{
93 nss_tx_status_t status;
94 int ret = 0;
95
96 down(&ppe_pvt.sem);
97 ppe_pvt.cb = (void *)npm->cm.cb;
98 ppe_pvt.app_data = (void *)npm->cm.app_data;
99
100 npm->cm.cb = (nss_ptr_t)nss_ppe_callback;
101 npm->cm.app_data = (nss_ptr_t)NULL;
102
103 status = nss_ppe_tx_msg(nss_ctx, npm);
104 if (status != NSS_TX_SUCCESS) {
105 nss_warning("%p: ppe_tx_msg failed\n", nss_ctx);
106 up(&ppe_pvt.sem);
107 return status;
108 }
109
110 ret = wait_for_completion_timeout(&ppe_pvt.complete, msecs_to_jiffies(NSS_PPE_TX_TIMEOUT));
111 if (!ret) {
112 nss_warning("%p: ppe msg tx failed due to timeout\n", nss_ctx);
113 ppe_pvt.response = NSS_TX_FAILURE;
114 }
115
116 status = ppe_pvt.response;
117 up(&ppe_pvt.sem);
118 return status;
119}
Amit Gupta1263b082017-07-06 14:22:57 +0530120
121/*
122 * nss_ppe_get_context()
123 * Get NSS context instance for ppe
124 */
125struct nss_ctx_instance *nss_ppe_get_context(void)
126{
127 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.ppe_handler_id];
128}
Amit Gupta1263b082017-07-06 14:22:57 +0530129
130/*
131 * nss_ppe_msg_init()
132 * Initialize nss_ppe_msg.
133 */
134void nss_ppe_msg_init(struct nss_ppe_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
135{
136 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
137}
Amit Gupta1263b082017-07-06 14:22:57 +0530138
139/*
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530140 * nss_ppe_tx_ipsec_config_msg
141 * API to send inline IPsec port configure message to NSS FW
142 */
Vijay Vigneshan2475f412018-05-14 19:49:44 +0530143nss_tx_status_t nss_ppe_tx_ipsec_config_msg(uint32_t nss_ifnum, uint32_t vsi_num, uint16_t mtu,
144 __attribute__((unused))uint16_t mru)
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530145{
146 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
147 struct nss_ppe_msg npm = {0};
148
149 if (!nss_ctx) {
150 nss_warning("Can't get nss context\n");
151 return NSS_TX_FAILURE;
152 }
153
154 if (vsi_num >= NSS_PPE_VSI_NUM_MAX) {
155 nss_warning("Invalid vsi number:%u\n", vsi_num);
156 return NSS_TX_FAILURE;
157 }
158
159 nss_ppe_msg_init(&npm, NSS_PPE_INTERFACE, NSS_PPE_MSG_IPSEC_PORT_CONFIG,
160 sizeof(struct nss_ppe_ipsec_port_config_msg), NULL, NULL);
161
162 npm.msg.ipsec_config.nss_ifnum = nss_ifnum;
163 npm.msg.ipsec_config.vsi_num = vsi_num;
164 npm.msg.ipsec_config.mtu = mtu;
165
166 return nss_ppe_tx_msg_sync(nss_ctx, &npm);
167}
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530168
169/*
170 * nss_ppe_tx_ipsec_mtu_msg
171 * API to send IPsec port MTU change message to NSS FW
172 */
Vijay Vigneshan2475f412018-05-14 19:49:44 +0530173nss_tx_status_t nss_ppe_tx_ipsec_mtu_msg(uint32_t nss_ifnum, uint16_t mtu, __attribute__((unused))uint16_t mru)
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530174{
175 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
176 struct nss_ppe_msg npm = {0};
177
178 if (!nss_ctx) {
179 nss_warning("Can't get nss context\n");
180 return NSS_TX_FAILURE;
181 }
182
183 nss_ppe_msg_init(&npm, NSS_PPE_INTERFACE, NSS_PPE_MSG_IPSEC_PORT_MTU_CHANGE,
184 sizeof(struct nss_ppe_ipsec_port_mtu_msg), NULL, NULL);
185
186 npm.msg.ipsec_mtu.nss_ifnum = nss_ifnum;
187 npm.msg.ipsec_mtu.mtu = mtu;
188
189 return nss_ppe_tx_msg_sync(nss_ctx, &npm);
190}
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530191
192/*
193 * nss_ppe_tx_ipsec_add_intf_msg
194 * API to attach NSS interface to IPsec port
195 */
196nss_tx_status_t nss_ppe_tx_ipsec_add_intf_msg(uint32_t nss_ifnum)
197{
198 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
199 struct nss_ppe_msg npm = {0};
200
201 if (!nss_ctx) {
202 nss_warning("Can't get nss context\n");
203 return NSS_TX_FAILURE;
204 }
205
206 nss_ppe_msg_init(&npm, NSS_PPE_INTERFACE, NSS_PPE_MSG_IPSEC_ADD_INTF,
207 sizeof(struct nss_ppe_ipsec_add_intf_msg), NULL, NULL);
208
209 npm.msg.ipsec_addif.nss_ifnum = nss_ifnum;
210
211 return nss_ppe_tx_msg_sync(nss_ctx, &npm);
212}
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530213
214/*
215 * nss_ppe_tx_ipsec_del_intf_msg
216 * API to detach NSS interface to IPsec port
217 */
218nss_tx_status_t nss_ppe_tx_ipsec_del_intf_msg(uint32_t nss_ifnum)
219{
220 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
221 struct nss_ppe_msg npm = {0};
222
223 if (!nss_ctx) {
224 nss_warning("Can't get nss context\n");
225 return NSS_TX_FAILURE;
226 }
227
228 nss_ppe_msg_init(&npm, NSS_PPE_INTERFACE, NSS_PPE_MSG_IPSEC_DEL_INTF,
229 sizeof(struct nss_ppe_ipsec_del_intf_msg), NULL, NULL);
230
231 npm.msg.ipsec_delif.nss_ifnum = nss_ifnum;
232
233 return nss_ppe_tx_msg_sync(nss_ctx, &npm);
234}
Amit Gupta24a1ccb2018-02-26 18:32:35 +0530235
236/*
Amit Gupta316729b2016-08-12 12:21:15 +0530237 * nss_ppe_handler()
Amit Gupta1263b082017-07-06 14:22:57 +0530238 * Handle NSS -> HLOS messages for ppe
Amit Gupta316729b2016-08-12 12:21:15 +0530239 */
240static void nss_ppe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
241{
242 struct nss_ppe_msg *msg = (struct nss_ppe_msg *)ncm;
Amit Gupta1263b082017-07-06 14:22:57 +0530243 void *ctx;
Amit Gupta316729b2016-08-12 12:21:15 +0530244
Amit Gupta1263b082017-07-06 14:22:57 +0530245 nss_ppe_msg_callback_t cb;
246
247 nss_trace("nss_ctx: %p ppe msg: %p\n", nss_ctx, msg);
Amit Gupta316729b2016-08-12 12:21:15 +0530248 BUG_ON(!nss_ppe_verify_ifnum(ncm->interface));
249
250 /*
Sachin Shashidhardd7229c2018-08-07 17:33:42 -0700251 * Trace messages.
252 */
253 nss_ppe_log_rx_msg(msg);
254
255 /*
Amit Gupta316729b2016-08-12 12:21:15 +0530256 * Is this a valid request/response packet?
257 */
258 if (ncm->type >= NSS_PPE_MSG_MAX) {
Amit Gupta1263b082017-07-06 14:22:57 +0530259 nss_warning("%p: received invalid message %d for PPE interface\n", nss_ctx, ncm->type);
Amit Gupta316729b2016-08-12 12:21:15 +0530260 return;
261 }
262
263 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ppe_msg)) {
Amit Gupta1263b082017-07-06 14:22:57 +0530264 nss_warning("%p: Length of message is greater than required: %d\n", nss_ctx, nss_cmn_get_msg_len(ncm));
Amit Gupta316729b2016-08-12 12:21:15 +0530265 return;
266 }
267
268 switch (msg->cm.type) {
269 case NSS_PPE_MSG_SYNC_STATS:
270 /*
271 * session debug stats embeded in session stats msg
272 */
273 nss_ppe_stats_sync(nss_ctx, &msg->msg.stats, ncm->interface);
Amit Gupta1263b082017-07-06 14:22:57 +0530274 return;
Amit Gupta316729b2016-08-12 12:21:15 +0530275 }
Amit Gupta316729b2016-08-12 12:21:15 +0530276
Amit Gupta1263b082017-07-06 14:22:57 +0530277 /*
278 * Log failures
279 */
280 nss_core_log_msg_failures(nss_ctx, ncm);
281
282 /*
283 * Do we have a call back
284 */
285 if (!ncm->cb) {
286 return;
287 }
288
289 /*
290 * callback
291 */
292 cb = (nss_ppe_msg_callback_t)ncm->cb;
293 ctx = (void *)ncm->app_data;
294
295 cb(ctx, msg);
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700296}
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700297
298/*
Amit Gupta316729b2016-08-12 12:21:15 +0530299 * nss_ppe_register_handler()
300 * debugfs stats msg handler received on static ppe interface
301 *
302 * TODO: Export API so that others can also read PPE stats.
303 */
304void nss_ppe_register_handler(void)
305{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700306 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
307
308 nss_core_register_handler(nss_ctx, NSS_PPE_INTERFACE, nss_ppe_handler, NULL);
Yu Huang8c107082017-07-24 14:58:26 -0700309
Amit Guptac438e212018-04-25 19:18:14 +0530310 if (nss_ppe_debug_stats.valid) {
311 nss_ppe_stats_dentry_create();
312 }
Amit Gupta316729b2016-08-12 12:21:15 +0530313}
314
315/*
316 * nss_ppe_free()
317 * Uninitialize PPE base
318 */
319void nss_ppe_free(void)
320{
321 /*
322 * Check if PPE base is already uninitialized.
323 */
324 if (!ppe_pvt.ppe_base) {
325 return;
326 }
327
328 /*
329 * Unmap PPE base address
330 */
331 iounmap(ppe_pvt.ppe_base);
332 ppe_pvt.ppe_base = NULL;
333
334 spin_lock_bh(&nss_ppe_stats_lock);
335 nss_ppe_debug_stats.valid = false;
336 nss_ppe_debug_stats.if_num = 0;
337 nss_ppe_debug_stats.if_index = 0;
338 spin_unlock_bh(&nss_ppe_stats_lock);
339}
340
341/*
342 * nss_ppe_init()
343 * Initialize PPE base
344 */
345void nss_ppe_init(void)
346{
347 /*
348 * Check if PPE base is already initialized.
349 */
350 if (ppe_pvt.ppe_base) {
351 return;
352 }
353
354 /*
355 * Get the PPE base address
356 */
357 ppe_pvt.ppe_base = ioremap_nocache(PPE_BASE_ADDR, PPE_REG_SIZE);
358 if (!ppe_pvt.ppe_base) {
359 nss_warning("DRV can't get PPE base address\n");
360 return;
361 }
362
363 spin_lock_bh(&nss_ppe_stats_lock);
364 nss_ppe_debug_stats.valid = true;
365 nss_ppe_debug_stats.if_num = 0;
366 nss_ppe_debug_stats.if_index = 0;
367 spin_unlock_bh(&nss_ppe_stats_lock);
Amit Gupta1263b082017-07-06 14:22:57 +0530368
369 sema_init(&ppe_pvt.sem, 1);
370 init_completion(&ppe_pvt.complete);
Amit Gupta316729b2016-08-12 12:21:15 +0530371}