1/*
2 **************************************************************************
3 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
4 * 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
293	status = nss_core_send_buffer(nss_ctx, if_num, skb, 0, H2N_BUFFER_SHAPER_BOUNCE_INTERFACE, 0);
294	if (status != NSS_CORE_STATUS_SUCCESS) {
295		return NSS_TX_FAILURE;
296	}
297	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
298								NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
299
300	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
301	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);
338	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_CMD_QUEUE, H2N_BUFFER_SHAPER_BOUNCE_BRIDGE, 0);
339	if (status != NSS_CORE_STATUS_SUCCESS) {
340		nss_info("%s: Bridge bounce core send rejected", __func__);
341		return NSS_TX_FAILURE;
342	}
343	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
344								NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
345
346	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
347	return NSS_TX_SUCCESS;
348}
349
350EXPORT_SYMBOL(nss_shaper_bounce_bridge_packet);
351EXPORT_SYMBOL(nss_shaper_bounce_interface_packet);
352EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_interface);
353EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_interface);
354EXPORT_SYMBOL(nss_shaper_unregister_shaper_bounce_bridge);
355EXPORT_SYMBOL(nss_shaper_register_shaper_bounce_bridge);
356EXPORT_SYMBOL(nss_shaper_register_shaping);
357EXPORT_SYMBOL(nss_shaper_unregister_shaping);
358