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