blob: b31458d5a562fe4882ec345b30b7edc2997c0350 [file] [log] [blame]
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -07001/*
2 **************************************************************************
Aniruddha Paul82fe2d02020-04-23 23:39:10 +05303 * Copyright (c) 2014, 2016-2020 The Linux Foundation. All rights reserved.
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -07004 * 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_tx_rx_common.h"
18
19/*
20 * nss_shaper_register_shaping()
21 * Register to obtain an NSS context for basic shaping operations
22 */
23void *nss_shaper_register_shaping(void)
24{
25 if (nss_top_main.shaping_handler_id == (uint8_t)-1) {
26 nss_warning("%p: SHAPING IS NOT ENABLED", __func__);
27 return NULL;
28 }
29 return (void *)&nss_top_main.nss[nss_top_main.shaping_handler_id];
30}
31
32/*
33 * nss_shaper_unregister_shaping()
34 * Unregister an NSS shaping context
35 */
36void nss_shaper_unregister_shaping(void *nss_ctx)
37{
38}
39
40/*
41 * nss_shaper_register_shaper_bounce_interface()
42 * Register for performing shaper bounce operations for interface shaper
43 */
44void *nss_shaper_register_shaper_bounce_interface(uint32_t if_num, nss_shaper_bounced_callback_t cb, void *app_data, struct module *owner)
45{
46 struct nss_top_instance *nss_top = &nss_top_main;
47 struct nss_shaper_bounce_registrant *reg;
48
49 nss_info("Shaper bounce interface register: %u, cb: %p, app_data: %p, owner: %p",
50 if_num, cb, app_data, owner);
51
52 /*
53 * Must be valid interface number
54 */
55 if (if_num >= NSS_MAX_NET_INTERFACES) {
56 nss_warning("Invalid if_num: %u", if_num);
57 BUG_ON(false);
58 }
59
60 /*
61 * Shaping enabled?
62 */
63 if (nss_top_main.shaping_handler_id == (uint8_t)-1) {
64 nss_warning("%p: SHAPING IS NOT ENABLED", __func__);
65 return NULL;
66 }
67
68 /*
69 * Can we hold the module?
70 */
71 if (!try_module_get(owner)) {
72 nss_warning("%p: Unable to hold owner", __func__);
73 return NULL;
74 }
75
76 spin_lock_bh(&nss_top->lock);
77
78 /*
79 * Must not have existing registrant
80 */
81 reg = &nss_top->bounce_interface_registrants[if_num];
82 if (reg->registered) {
83 spin_unlock_bh(&nss_top->stats_lock);
84 module_put(owner);
85 nss_warning("Already registered: %u", if_num);
86 BUG_ON(false);
87 }
88
89 /*
90 * Register
91 */
92 reg->bounced_callback = cb;
93 reg->app_data = app_data;
94 reg->owner = owner;
95 reg->registered = true;
96 spin_unlock_bh(&nss_top->lock);
97
98 return (void *)&nss_top->nss[nss_top->shaping_handler_id];
99}
100
101/*
102 * nss_shaper_unregister_shaper_bounce_interface()
103 * Unregister for shaper bounce operations for interface shaper
104 */
105void nss_shaper_unregister_shaper_bounce_interface(uint32_t if_num)
106{
107 struct nss_top_instance *nss_top = &nss_top_main;
108 struct nss_shaper_bounce_registrant *reg;
109 struct module *owner;
110
111 nss_info("Shaper bounce interface unregister: %u", if_num);
112
113 /*
114 * Must be valid interface number
115 */
116 if (if_num >= NSS_MAX_NET_INTERFACES) {
117 nss_warning("Invalid if_num: %u", if_num);
118 BUG_ON(false);
119 }
120
121 spin_lock_bh(&nss_top->lock);
122
123 /*
124 * Must have existing registrant
125 */
126 reg = &nss_top->bounce_interface_registrants[if_num];
127 if (!reg->registered) {
128 spin_unlock_bh(&nss_top->stats_lock);
129 nss_warning("Already unregistered: %u", if_num);
130 BUG_ON(false);
131 }
132
133 /*
134 * Unegister
135 */
136 owner = reg->owner;
137 reg->owner = NULL;
138 reg->registered = false;
139 spin_unlock_bh(&nss_top->lock);
140
141 module_put(owner);
142}
143
144/*
145 * nss_shaper_register_shaper_bounce_bridge()
146 * Register for performing shaper bounce operations for bridge shaper
147 */
148void *nss_shaper_register_shaper_bounce_bridge(uint32_t if_num, nss_shaper_bounced_callback_t cb, void *app_data, struct module *owner)
149{
150 struct nss_top_instance *nss_top = &nss_top_main;
151 struct nss_ctx_instance *nss_ctx;
152 struct nss_shaper_bounce_registrant *reg;
153
154 nss_info("Shaper bounce bridge register: %u, cb: %p, app_data: %p, owner: %p",
155 if_num, cb, app_data, owner);
156
157 /*
158 * Must be valid interface number
159 */
160 if (if_num >= NSS_MAX_NET_INTERFACES) {
161 nss_warning("Invalid if_num: %u", if_num);
162 BUG_ON(false);
163 }
164
165 /*
166 * Shaping enabled?
167 */
168 if (nss_top_main.shaping_handler_id == (uint8_t)-1) {
169 nss_warning("%p: SHAPING IS NOT ENABLED", __func__);
170 return NULL;
171 }
172
173 /*
174 * Can we hold the module?
175 */
176 if (!try_module_get(owner)) {
177 nss_warning("%p: Unable to hold owner", __func__);
178 return NULL;
179 }
180
181 spin_lock_bh(&nss_top->lock);
182
183 /*
184 * Must not have existing registrant
185 */
186 reg = &nss_top->bounce_bridge_registrants[if_num];
187 if (reg->registered) {
188 spin_unlock_bh(&nss_top->stats_lock);
189 module_put(owner);
190 nss_warning("Already registered: %u", if_num);
191 BUG_ON(false);
192 }
193
194 /*
195 * Register
196 */
197 reg->bounced_callback = cb;
198 reg->app_data = app_data;
199 reg->owner = owner;
200 reg->registered = true;
201 spin_unlock_bh(&nss_top->lock);
202
203 nss_ctx = &nss_top->nss[nss_top->shaping_handler_id];
204 return (void *)nss_ctx;
205}
206
207/*
208 * nss_shaper_unregister_shaper_bounce_bridge()
209 * Unregister for shaper bounce operations for bridge shaper
210 */
211void nss_shaper_unregister_shaper_bounce_bridge(uint32_t if_num)
212{
213 struct nss_top_instance *nss_top = &nss_top_main;
214 struct nss_shaper_bounce_registrant *reg;
215 struct module *owner;
216
217 nss_info("Shaper bounce bridge unregister: %u", if_num);
218
219 /*
220 * Must be valid interface number
221 */
222 if (if_num >= NSS_MAX_NET_INTERFACES) {
223 nss_warning("Invalid if_num: %u", if_num);
224 BUG_ON(false);
225 }
226
227 spin_lock_bh(&nss_top->lock);
228
229 /*
230 * Must have existing registrant
231 */
232 reg = &nss_top->bounce_bridge_registrants[if_num];
233 if (!reg->registered) {
234 spin_unlock_bh(&nss_top->stats_lock);
235 nss_warning("Already unregistered: %u", if_num);
236 BUG_ON(false);
237 }
238
239 /*
240 * Wait until any bounce callback that is active is finished
241 */
242 while (reg->callback_active) {
243 spin_unlock_bh(&nss_top->stats_lock);
244 yield();
245 spin_lock_bh(&nss_top->stats_lock);
246 }
247
248 /*
249 * Unegister
250 */
251 owner = reg->owner;
252 reg->owner = NULL;
253 reg->registered = false;
254 spin_unlock_bh(&nss_top->lock);
255
256 module_put(owner);
257}
258
259/*
260 * nss_shaper_bounce_interface_packet()
261 * Bounce a packet to the NSS for interface shaping.
262 *
263 * You must have registered for interface bounce shaping to call this.
264 */
265nss_tx_status_t nss_shaper_bounce_interface_packet(void *ctx, uint32_t if_num, struct sk_buff *skb)
266{
267 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)ctx;
268 struct nss_top_instance *nss_top = nss_ctx->nss_top;
269 struct nss_shaper_bounce_registrant *reg;
270 int32_t status;
271
272 /*
273 * Must be valid interface number
274 */
275 if (if_num >= NSS_MAX_NET_INTERFACES) {
276 nss_warning("Invalid if_num: %u", if_num);
277 BUG_ON(false);
278 }
279
280
281 /*
282 * Must have existing registrant
283 */
284 spin_lock_bh(&nss_top->lock);
285 reg = &nss_top->bounce_interface_registrants[if_num];
286 if (!reg->registered) {
287 spin_unlock_bh(&nss_top->stats_lock);
288 nss_warning("unregistered: %u", if_num);
289 return NSS_TX_FAILURE;
290 }
291 spin_unlock_bh(&nss_top->lock);
292
Aniruddha Paul82fe2d02020-04-23 23:39:10 +0530293 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_H2N_DATA_QUEUE,
294 H2N_BUFFER_SHAPER_BOUNCE_INTERFACE, 0);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700295 if (status != NSS_CORE_STATUS_SUCCESS) {
296 return NSS_TX_FAILURE;
297 }
Stephen Wang90c67de2016-04-26 15:15:59 -0700298 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700299
Sakthi Vignesh Radhakrishnan150c5592019-07-02 10:17:44 -0700300 NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_DRV_STATS_TX_PACKET]);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700301 return NSS_TX_SUCCESS;
302}
303
304/*
305 * nss_shaper_bounce_bridge_packet()
306 * Bounce a packet to the NSS for bridge shaping.
307 *
308 * You must have registered for bridge bounce shaping to call this.
309 */
310nss_tx_status_t nss_shaper_bounce_bridge_packet(void *ctx, uint32_t if_num, struct sk_buff *skb)
311{
312 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)ctx;
313 struct nss_top_instance *nss_top = nss_ctx->nss_top;
314 struct nss_shaper_bounce_registrant *reg;
315 int32_t status;
316
317 /*
318 * Must be valid interface number
319 */
320 if (if_num >= NSS_MAX_NET_INTERFACES) {
321 nss_warning("Invalid if_num: %u", if_num);
322 BUG_ON(false);
323 }
324
325 /*
326 * Must have existing registrant
327 */
328 spin_lock_bh(&nss_top->lock);
329 reg = &nss_top->bounce_bridge_registrants[if_num];
330 if (!reg->registered) {
331 spin_unlock_bh(&nss_top->stats_lock);
332 nss_warning("unregistered: %u", if_num);
333 return NSS_TX_FAILURE;
334 }
335 spin_unlock_bh(&nss_top->lock);
336
337 nss_info("%s: Bridge bounce skb: %p, if_num: %u, ctx: %p", __func__, skb, if_num, nss_ctx);
Aniruddha Paul82fe2d02020-04-23 23:39:10 +0530338 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_H2N_DATA_QUEUE,
339 H2N_BUFFER_SHAPER_BOUNCE_BRIDGE, 0);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700340 if (status != NSS_CORE_STATUS_SUCCESS) {
341 nss_info("%s: Bridge bounce core send rejected", __func__);
342 return NSS_TX_FAILURE;
343 }
Stephen Wang90c67de2016-04-26 15:15:59 -0700344 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700345
Sakthi Vignesh Radhakrishnan150c5592019-07-02 10:17:44 -0700346 NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_DRV_STATS_TX_PACKET]);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700347 return NSS_TX_SUCCESS;
348}
349
Suruchi Agarwal4e03c522018-11-22 15:10:18 +0530350/*
351 * nss_shaper_get_device()
352 * Gets the original device from probe.
353 */
354struct device *nss_shaper_get_dev(void)
355{
356 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.shaping_handler_id];
357 return nss_ctx->dev;
358}
359
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700360EXPORT_SYMBOL(nss_shaper_bounce_bridge_packet);
361EXPORT_SYMBOL(nss_shaper_bounce_interface_packet);
362EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_interface);
363EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_interface);
364EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_bridge);
365EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_bridge);
366EXPORT_SYMBOL(nss_shaper_register_shaping);
367EXPORT_SYMBOL(nss_shaper_unregister_shaping);
Suruchi Agarwal4e03c522018-11-22 15:10:18 +0530368EXPORT_SYMBOL(nss_shaper_get_dev);