blob: 70a71ebe5e9e736e9c976d1ff024bf30a28d5103 [file] [log] [blame]
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -07001/*
2 **************************************************************************
Sakthi Vignesh Radhakrishnand6cf94d2017-04-18 16:58:24 -07003 * Copyright (c) 2014, 2016-2017 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
Sakthi Vignesh Radhakrishnand6cf94d2017-04-18 16:58:24 -0700293 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_SHAPER_BOUNCE_INTERFACE, 0);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700294 if (status != NSS_CORE_STATUS_SUCCESS) {
295 return NSS_TX_FAILURE;
296 }
Stephen Wang90c67de2016-04-26 15:15:59 -0700297 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700298
Sakthi Vignesh Radhakrishnand6cf94d2017-04-18 16:58:24 -0700299 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700300 return NSS_TX_SUCCESS;
301}
302
303/*
304 * nss_shaper_bounce_bridge_packet()
305 * Bounce a packet to the NSS for bridge shaping.
306 *
307 * You must have registered for bridge bounce shaping to call this.
308 */
309nss_tx_status_t nss_shaper_bounce_bridge_packet(void *ctx, uint32_t if_num, struct sk_buff *skb)
310{
311 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)ctx;
312 struct nss_top_instance *nss_top = nss_ctx->nss_top;
313 struct nss_shaper_bounce_registrant *reg;
314 int32_t status;
315
316 /*
317 * Must be valid interface number
318 */
319 if (if_num >= NSS_MAX_NET_INTERFACES) {
320 nss_warning("Invalid if_num: %u", if_num);
321 BUG_ON(false);
322 }
323
324 /*
325 * Must have existing registrant
326 */
327 spin_lock_bh(&nss_top->lock);
328 reg = &nss_top->bounce_bridge_registrants[if_num];
329 if (!reg->registered) {
330 spin_unlock_bh(&nss_top->stats_lock);
331 nss_warning("unregistered: %u", if_num);
332 return NSS_TX_FAILURE;
333 }
334 spin_unlock_bh(&nss_top->lock);
335
336 nss_info("%s: Bridge bounce skb: %p, if_num: %u, ctx: %p", __func__, skb, if_num, nss_ctx);
Sakthi Vignesh Radhakrishnand6cf94d2017-04-18 16:58:24 -0700337 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_SHAPER_BOUNCE_BRIDGE, 0);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700338 if (status != NSS_CORE_STATUS_SUCCESS) {
339 nss_info("%s: Bridge bounce core send rejected", __func__);
340 return NSS_TX_FAILURE;
341 }
Stephen Wang90c67de2016-04-26 15:15:59 -0700342 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700343
Sakthi Vignesh Radhakrishnand6cf94d2017-04-18 16:58:24 -0700344 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700345 return NSS_TX_SUCCESS;
346}
347
348EXPORT_SYMBOL(nss_shaper_bounce_bridge_packet);
349EXPORT_SYMBOL(nss_shaper_bounce_interface_packet);
350EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_interface);
351EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_interface);
352EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_bridge);
353EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_bridge);
354EXPORT_SYMBOL(nss_shaper_register_shaping);
355EXPORT_SYMBOL(nss_shaper_unregister_shaping);