1/* 2 ************************************************************************** 3 * Copyright (c) 2013 - 2015, 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/* 18 * nss_tx_rx_virt_if.c 19 * NSS virtual/redirect handler APIs 20 */ 21 22#include "nss_tx_rx_common.h" 23#include <net/arp.h> 24 25#define NSS_TX_RX_VIRT_IF_TX_TIMEOUT 3000 /* 3 Seconds */ 26#define NSS_TX_RX_VIRT_IF_GET_INDEX(if_num) (if_num-NSS_DYNAMIC_IF_START) 27#define NSS_TX_RX_VIRT_IF_802_3_PKT 0x2 28#define NSS_TX_RX_VIRT_IF_NATIVE_WIFI_PKT 0x3 29 30extern int nss_ctl_redirect; 31 32/* 33 * Data structure that holds the virtual interface context. 34 */ 35static struct nss_tx_rx_virt_if_handle *nss_tx_rx_virt_if_handles[NSS_MAX_DYNAMIC_INTERFACES]; 36 37/* 38 * Spinlock to protect the global data structure virt_handle. 39 */ 40DEFINE_SPINLOCK(nss_tx_rx_virt_if_lock); 41 42/* 43 * nss_tx_rx_virt_if_stats_sync() 44 * Sync stats from the NSS FW 45 */ 46static void nss_tx_rx_virt_if_stats_sync(struct nss_tx_rx_virt_if_handle *handle, 47 struct nss_tx_rx_virt_if_stats *nwis) 48{ 49 struct nss_tx_rx_virt_if_stats *stats = &handle->stats; 50 51 stats->node_stats.rx_packets += nwis->node_stats.rx_packets; 52 stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes; 53 stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped; 54 stats->node_stats.tx_packets += nwis->node_stats.tx_packets; 55 stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes; 56 stats->tx_enqueue_failed += nwis->tx_enqueue_failed; 57 stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed; 58} 59 60/* 61 * nss_tx_rx_virt_if_msg_handler() 62 * Handle msg responses from the FW on virtual interfaces 63 */ 64static void nss_tx_rx_virt_if_msg_handler(struct nss_ctx_instance *nss_ctx, 65 struct nss_cmn_msg *ncm, 66 __attribute__((unused))void *app_data) 67{ 68 struct nss_tx_rx_virt_if_msg *nvim = (struct nss_tx_rx_virt_if_msg *)ncm; 69 int32_t if_num; 70 71 nss_tx_rx_virt_if_msg_callback_t cb; 72 struct nss_tx_rx_virt_if_handle *handle = NULL; 73 74 /* 75 * Sanity check the message type 76 */ 77 if (ncm->type > NSS_VIRT_IF_MAX_MSG_TYPES) { 78 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 79 return; 80 } 81 82 /* 83 * Messages value that are within the base class are handled by the base class. 84 */ 85 if (ncm->type < NSS_IF_MAX_MSG_TYPES) { 86 return nss_if_msg_handler(nss_ctx, ncm, app_data); 87 } 88 89 if (!NSS_IS_IF_TYPE(DYNAMIC, ncm->interface)) { 90 nss_warning("%p: response for another interface: %d", nss_ctx, ncm->interface); 91 return; 92 } 93 94 if_num = NSS_TX_RX_VIRT_IF_GET_INDEX(ncm->interface); 95 96 spin_lock_bh(&nss_tx_rx_virt_if_lock); 97 if (!nss_tx_rx_virt_if_handles[if_num]) { 98 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 99 nss_warning("%p: redir_if handle is NULL\n", nss_ctx); 100 return; 101 } 102 103 handle = nss_tx_rx_virt_if_handles[if_num]; 104 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 105 106 switch (nvim->cm.type) { 107 case NSS_VIRT_IF_STATS_SYNC_MSG: 108 nss_tx_rx_virt_if_stats_sync(handle, &nvim->msg.stats); 109 break; 110 } 111 112 /* 113 * Log failures 114 */ 115 nss_core_log_msg_failures(nss_ctx, ncm); 116 117 /* 118 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages 119 * to the same callback/app_data. 120 */ 121 if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) { 122 ncm->cb = (uint32_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface]; 123 ncm->app_data = (uint32_t)nss_ctx->nss_top->subsys_dp_register[ncm->interface].ndev; 124 } 125 126 /* 127 * Do we have a callback? 128 */ 129 if (!ncm->cb) { 130 return; 131 } 132 133 /* 134 * Callback 135 */ 136 cb = (nss_tx_rx_virt_if_msg_callback_t)ncm->cb; 137 cb((void *)ncm->app_data, ncm); 138} 139 140/* 141 * nss_tx_rx_virt_if_callback 142 * Callback to handle the completion of NSS ->HLOS messages. 143 */ 144static void nss_tx_rx_virt_if_callback(void *app_data, struct nss_cmn_msg *ncm) 145{ 146 struct nss_tx_rx_virt_if_handle *handle = (struct nss_tx_rx_virt_if_handle *)app_data; 147 struct nss_tx_rx_virt_if_pvt *nvip = handle->pvt; 148 149 if (ncm->response != NSS_CMN_RESPONSE_ACK) { 150 nss_warning("%p: redir_if Error response %d\n", handle->nss_ctx, ncm->response); 151 nvip->response = NSS_TX_FAILURE; 152 complete(&nvip->complete); 153 return; 154 } 155 156 nvip->response = NSS_TX_SUCCESS; 157 complete(&nvip->complete); 158} 159 160/* 161 * nss_register_virt_if() 162 */ 163void *nss_register_virt_if(void *ctx, 164 nss_virt_if_rx_callback_t rx_callback, 165 struct net_device *netdev) 166{ 167 struct nss_tx_rx_virt_if_handle *handle = (struct nss_tx_rx_virt_if_handle *)ctx; 168 169 int32_t if_num; 170 171 if (!handle) { 172 nss_warning("handle is NULL\n"); 173 return NULL; 174 } 175 176 if_num = handle->if_num; 177 178 nss_top_main.subsys_dp_register[if_num].ndev = netdev; 179 nss_top_main.subsys_dp_register[if_num].cb = rx_callback; 180 nss_top_main.subsys_dp_register[if_num].app_data = NULL; 181 nss_top_main.subsys_dp_register[if_num].features = (uint32_t)netdev->features; 182 183 nss_top_main.if_rx_msg_callback[if_num] = NULL; 184 185 return ctx; 186} 187 188/* 189 * nss_unregister_virt_if() 190 */ 191void nss_unregister_virt_if(void *ctx) 192{ 193 struct nss_tx_rx_virt_if_handle *handle = (struct nss_tx_rx_virt_if_handle *)ctx; 194 int32_t if_num; 195 196 if (!handle) { 197 nss_warning("handle is NULL\n"); 198 return; 199 } 200 201 if_num = handle->if_num; 202 203 nss_top_main.subsys_dp_register[if_num].ndev = NULL; 204 nss_top_main.subsys_dp_register[if_num].cb = NULL; 205 nss_top_main.subsys_dp_register[if_num].app_data = NULL; 206 nss_top_main.subsys_dp_register[if_num].features = 0; 207 208 nss_top_main.if_rx_msg_callback[if_num] = NULL; 209} 210 211/* 212 * nss_tx_virt_if_recvbuf() 213 * HLOS interface has received a packet which we redirect to the NSS, if appropriate to do so. 214 */ 215nss_tx_status_t nss_tx_virt_if_recvbuf(void *ctx, struct sk_buff *skb, uint32_t nwifi) 216{ 217 struct nss_tx_rx_virt_if_handle *handle = (struct nss_tx_rx_virt_if_handle *)ctx; 218 int32_t if_num = handle->if_num; 219 struct nss_ctx_instance *nss_ctx = handle->nss_ctx; 220 nss_tx_status_t status; 221 int push_mac_header = 0; 222 223 if (unlikely(nss_ctl_redirect == 0)) { 224 return NSS_TX_FAILURE_NOT_ENABLED; 225 } 226 227 if (unlikely(skb->vlan_tci)) { 228 return NSS_TX_FAILURE_NOT_SUPPORTED; 229 } 230 231 nss_assert(NSS_IS_IF_TYPE(DYNAMIC, if_num)); 232 nss_trace("%p: Virtual Rx packet, if_num:%d, skb:%p", nss_ctx, if_num, skb); 233 234 /* 235 * Get the NSS context that will handle this packet and check that it is initialised and ready 236 */ 237 NSS_VERIFY_CTX_MAGIC(nss_ctx); 238 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 239 nss_warning("%p: Virtual Rx packet dropped as core not ready", nss_ctx); 240 return NSS_TX_FAILURE_NOT_READY; 241 } 242 243 /* 244 * Sanity check the SKB to ensure that it's suitable for us 245 */ 246 if (unlikely(skb->len <= ETH_HLEN)) { 247 nss_warning("%p: Virtual Rx packet: %p too short", nss_ctx, skb); 248 return NSS_TX_FAILURE_TOO_SHORT; 249 } 250 251 if (unlikely(skb_shinfo(skb)->nr_frags != 0)) { 252 /* 253 * TODO: If we have a connection matching rule for this skbuff, 254 * do we need to flush it?? 255 */ 256 nss_warning("%p: Delivering the packet to Linux because of fragmented skb: %p\n", nss_ctx, skb); 257 return NSS_TX_FAILURE_NOT_SUPPORTED; 258 } 259 260 /* 261 * We differentiate between skbs with priority to identify native vs non-native wifi pkts 262 */ 263 if (nwifi) { 264 skb->priority = NSS_TX_RX_VIRT_IF_NATIVE_WIFI_PKT; 265 } else { 266 skb->priority = NSS_TX_RX_VIRT_IF_802_3_PKT; 267 268 /* 269 * NSS expects to see buffer from Ethernet header onwards. 270 * If the wireless driver has called eth_type_trans to remove 271 * the ethernet header, we need to push back the header 272 */ 273 if (unlikely((skb->data - skb_mac_header(skb)) == ETH_HLEN)) { 274 skb_push(skb, ETH_HLEN); 275 push_mac_header = 1; 276 } 277 } 278 279 /* 280 * Direct the buffer to the NSS 281 */ 282 status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, 283 H2N_BUFFER_PACKET, H2N_BIT_FLAG_VIRTUAL_BUFFER); 284 if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) { 285 nss_warning("%p: Virtual Rx packet unable to enqueue\n", nss_ctx); 286 287 if (unlikely(push_mac_header)) { 288 skb_pull(skb, ETH_HLEN); 289 } 290 291 return NSS_TX_FAILURE_QUEUE; 292 } 293 294 /* 295 * Kick the NSS awake so it can process our new entry. 296 */ 297 nss_hal_send_interrupt(nss_ctx->nmap, 298 nss_ctx->h2n_desc_rings[NSS_IF_DATA_QUEUE_0].desc_ring.int_bit, 299 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE); 300 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]); 301 return NSS_TX_SUCCESS; 302} 303 304/* 305 * @brief Forward virtual interface packets 306 * This function expects packet with L3 header and eth_type_trans 307 * has been called before calling this api 308 * 309 * @param nss_ctx NSS context (provided during registeration) 310 * @param os_buf OS buffer (e.g. skbuff) 311 * @return nss_tx_status_t Tx status 312 */ 313nss_tx_status_t nss_tx_virt_if_rxbuf(void *ctx, struct sk_buff *os_buf) 314{ 315 316 return nss_tx_virt_if_recvbuf(ctx, os_buf, 0); 317} 318 319/* 320 * @brief Forward Native wifi packet from virtual interface 321 * Expects packet with qca-nwifi format 322 * 323 * @param nss_ctx NSS context (provided during registeration) 324 * @param os_buf OS buffer (e.g. skbuff) 325 * @return nss_tx_status_t Tx status 326 */ 327nss_tx_status_t nss_tx_virt_if_rx_nwifibuf(void *ctx, struct sk_buff *os_buf) 328{ 329 330 return nss_tx_virt_if_recvbuf(ctx, os_buf, 1); 331} 332 333/* 334 * nss_tx_rx_virt_if_msg_init() 335 * Initialize redir specific message structure. 336 */ 337static void nss_tx_rx_virt_if_msg_init(struct nss_tx_rx_virt_if_msg *nrim, 338 uint16_t if_num, 339 uint32_t type, 340 uint32_t len, 341 nss_tx_rx_virt_if_msg_callback_t cb, 342 struct nss_tx_rx_virt_if_handle *app_data) 343{ 344 nss_cmn_msg_init(&nrim->cm, if_num, type, len, (void *)cb, (void *)app_data); 345} 346 347/* 348 * nss_tx_rx_virt_if_handle_create_sync() 349 * Initialize redir handle which holds the if_num and stats per interface. 350 */ 351static struct nss_tx_rx_virt_if_handle *nss_tx_rx_virt_if_handle_create(struct nss_ctx_instance *nss_ctx, int32_t if_num, int32_t *cmd_rsp) 352{ 353 int32_t index; 354 struct nss_tx_rx_virt_if_handle *handle; 355 356 index = NSS_TX_RX_VIRT_IF_GET_INDEX(if_num); 357 358 handle = (struct nss_tx_rx_virt_if_handle *)kzalloc(sizeof(struct nss_tx_rx_virt_if_handle), 359 GFP_KERNEL); 360 if (!handle) { 361 nss_warning("%p: handle memory alloc failed\n", nss_ctx); 362 *cmd_rsp = NSS_TX_RX_VIRT_IF_ALLOC_FAILURE; 363 goto error1; 364 } 365 366 handle->nss_ctx = nss_ctx; 367 handle->if_num = if_num; 368 handle->pvt = (struct nss_tx_rx_virt_if_pvt *)kzalloc(sizeof(struct nss_tx_rx_virt_if_pvt), 369 GFP_KERNEL); 370 if (!handle->pvt) { 371 nss_warning("%p: failure allocating memory for nss_tx_rx_virt_if_pvt\n", nss_ctx); 372 *cmd_rsp = NSS_TX_RX_VIRT_IF_ALLOC_FAILURE; 373 goto error2; 374 } 375 376 handle->cb = NULL; 377 handle->app_data = NULL; 378 379 spin_lock_bh(&nss_tx_rx_virt_if_lock); 380 nss_tx_rx_virt_if_handles[index] = handle; 381 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 382 383 *cmd_rsp = NSS_VIRT_IF_SUCCESS; 384 385 return handle; 386 387error2: 388 kfree(handle); 389error1: 390 return NULL; 391} 392 393/* 394 * nss_tx_rx_virt_if_register_handler_sync() 395 * register msg handler for redir interface and initialize semaphore and completion. 396 */ 397static uint32_t nss_tx_rx_virt_if_register_handler(struct nss_tx_rx_virt_if_handle *handle) 398{ 399 uint32_t ret; 400 struct nss_tx_rx_virt_if_pvt *nrip = NULL; 401 int32_t if_num = handle->if_num; 402 403 ret = nss_core_register_handler(if_num, nss_tx_rx_virt_if_msg_handler, NULL); 404 if (ret != NSS_CORE_STATUS_SUCCESS) { 405 nss_warning("%d: Message handler failed to be registered for interface\n", if_num); 406 return NSS_TX_RX_VIRT_IF_CORE_FAILURE; 407 } 408 409 nrip = handle->pvt; 410 if (!nrip->sem_init_done) { 411 sema_init(&nrip->sem, 1); 412 init_completion(&nrip->complete); 413 nrip->sem_init_done = 1; 414 } 415 416 return NSS_TX_RX_VIRT_IF_SUCCESS; 417} 418 419/* 420 * nss_tx_rx_virt_if_tx_msg() 421 */ 422nss_tx_status_t nss_tx_rx_virt_if_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_tx_rx_virt_if_msg *nrim) 423{ 424 int32_t status; 425 struct sk_buff *nbuf; 426 struct nss_cmn_msg *ncm = &nrim->cm; 427 struct nss_tx_rx_virt_if_msg *nrim2; 428 429 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 430 nss_warning("Interface could not be created as core not ready"); 431 return NSS_TX_FAILURE; 432 } 433 434 /* 435 * Sanity check the message 436 */ 437 if (!NSS_IS_IF_TYPE(DYNAMIC, ncm->interface)) { 438 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 439 return NSS_TX_FAILURE; 440 } 441 442 if (ncm->type > NSS_TX_RX_VIRT_IF_MAX_MSG_TYPES) { 443 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 444 return NSS_TX_FAILURE; 445 } 446 447 if (ncm->len > sizeof(struct nss_tx_rx_virt_if_msg)) { 448 nss_warning("%p: invalid length: %d. Length of redir msg is %d", 449 nss_ctx, ncm->len, sizeof(struct nss_tx_rx_virt_if_msg)); 450 return NSS_TX_FAILURE; 451 } 452 453 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE); 454 if (unlikely(!nbuf)) { 455 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]); 456 nss_warning("%p: redir interface %d: command allocation failed", nss_ctx, ncm->interface); 457 return NSS_TX_FAILURE; 458 } 459 460 nrim2 = (struct nss_tx_rx_virt_if_msg *)skb_put(nbuf, sizeof(struct nss_tx_rx_virt_if_msg)); 461 memcpy(nrim2, nrim, sizeof(struct nss_tx_rx_virt_if_msg)); 462 463 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0); 464 if (status != NSS_CORE_STATUS_SUCCESS) { 465 dev_kfree_skb_any(nbuf); 466 nss_warning("%p: Unable to enqueue 'virtual interface' command\n", nss_ctx); 467 return NSS_TX_FAILURE; 468 } 469 470 nss_hal_send_interrupt(nss_ctx->nmap, 471 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, 472 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE); 473 474 /* 475 * The context returned is the redir interface # which is, essentially, the index into the if_ctx 476 * array that is holding the net_device pointer 477 */ 478 return NSS_TX_SUCCESS; 479} 480 481/* 482 * nss_tx_rx_virt_if_tx_msg_sync 483 * Send a message from HLOS to NSS synchronously. 484 */ 485static nss_tx_status_t nss_tx_rx_virt_if_tx_msg_sync(struct nss_tx_rx_virt_if_handle *handle, 486 struct nss_tx_rx_virt_if_msg *nvim) 487{ 488 nss_tx_status_t status; 489 int ret = 0; 490 struct nss_tx_rx_virt_if_pvt *nrip = handle->pvt; 491 struct nss_ctx_instance *nss_ctx = handle->nss_ctx; 492 493 down(&nrip->sem); 494 495 status = nss_tx_rx_virt_if_tx_msg(nss_ctx, nvim); 496 if (status != NSS_TX_SUCCESS) { 497 nss_warning("%p: nss_tx_rx_virt_if_msg failed\n", nss_ctx); 498 up(&nrip->sem); 499 return status; 500 } 501 502 ret = wait_for_completion_timeout(&nrip->complete, 503 msecs_to_jiffies(NSS_TX_RX_VIRT_IF_TX_TIMEOUT)); 504 if (!ret) { 505 nss_warning("%p: redir_if tx failed due to timeout\n", nss_ctx); 506 nrip->response = NSS_TX_FAILURE; 507 } 508 509 status = nrip->response; 510 up(&nrip->sem); 511 512 return status; 513} 514 515/* 516 * nss_tx_rx_virt_if_handle_destroy() 517 * Destroy the redir handle either due to request from user or due to error, synchronously. 518 */ 519static int nss_tx_rx_virt_if_handle_destroy(struct nss_tx_rx_virt_if_handle *handle) 520{ 521 nss_tx_status_t status; 522 int32_t if_num = handle->if_num; 523 int32_t index = NSS_TX_RX_VIRT_IF_GET_INDEX(if_num); 524 struct nss_ctx_instance *nss_ctx = NULL; 525 526 nss_ctx = handle->nss_ctx; 527 status = nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED); 528 if (status != NSS_TX_SUCCESS) { 529 nss_warning("%p: Dynamic interface destroy failed status %d\n", nss_ctx, status); 530 return status; 531 } 532 533 spin_lock_bh(&nss_tx_rx_virt_if_lock); 534 nss_tx_rx_virt_if_handles[index] = NULL; 535 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 536 537 kfree(handle->pvt); 538 kfree(handle); 539 540 return status; 541} 542 543/* 544 * nss_create_virt_if() 545 * Create a virtual interface synchronously. 546 */ 547void *nss_create_virt_if(struct net_device *netdev) 548{ 549 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.wlan_handler_id]; 550 struct nss_tx_rx_virt_if_msg nrim; 551 struct nss_tx_rx_virt_if_create_msg *nrcm; 552 uint32_t ret; 553 struct nss_tx_rx_virt_if_handle *handle = NULL; 554 int32_t if_num; 555 556 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 557 nss_warning("%p: Interface could not be created as core not ready\n", nss_ctx); 558 return NULL; 559 } 560 561 if_num = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED); 562 if (if_num < 0) { 563 nss_warning("%p: failure allocating redir if\n", nss_ctx); 564 return NULL; 565 } 566 567 handle = nss_tx_rx_virt_if_handle_create(nss_ctx, if_num, &ret); 568 if (!handle) { 569 nss_warning("%p:redir_if handle creation failed ret %d\n", nss_ctx, ret); 570 nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED); 571 return NULL; 572 } 573 574 /* Initializes the semaphore and also sets the msg handler for if_num */ 575 ret = nss_tx_rx_virt_if_register_handler(handle); 576 if (ret != NSS_VIRT_IF_SUCCESS) { 577 nss_warning("%p: Registration handler failed reason: %d\n", nss_ctx, ret); 578 goto error; 579 } 580 581 nss_tx_rx_virt_if_msg_init(&nrim, handle->if_num, NSS_TX_RX_VIRT_IF_TX_CREATE_MSG, 582 sizeof(struct nss_tx_rx_virt_if_create_msg), nss_tx_rx_virt_if_callback, handle); 583 584 nrcm = &nrim.msg.if_create; 585 nrcm->flags = 0; 586 memcpy(nrcm->mac_addr, netdev->dev_addr, ETH_ALEN); 587 588 ret = nss_tx_rx_virt_if_tx_msg_sync(handle, &nrim); 589 if (ret != NSS_TX_SUCCESS) { 590 nss_warning("%p: nss_tx_rx_virt_if_tx_msg_sync failed %u\n", nss_ctx, ret); 591 goto error; 592 } 593 594 spin_lock_bh(&nss_top_main.lock); 595 if (!nss_top_main.subsys_dp_register[handle->if_num].ndev) { 596 nss_top_main.subsys_dp_register[handle->if_num].ndev = netdev; 597 } 598 spin_unlock_bh(&nss_top_main.lock); 599 600 /* 601 * Hold a reference to the net_device 602 */ 603 dev_hold(netdev); 604 605 /* 606 * The context returned is the handle interface # which contains all the info related to 607 * the interface if_num. 608 */ 609 610 return (void*)handle; 611 612error: 613 nss_tx_rx_virt_if_handle_destroy(handle); 614 return NULL; 615} 616 617/* 618 * nss_destroy_virt_if() 619 * Destroy a virtual interface synchronously. 620 */ 621nss_tx_status_t nss_destroy_virt_if(void *ctx) 622{ 623 struct nss_tx_rx_virt_if_handle *handle = (struct nss_tx_rx_virt_if_handle *)ctx; 624 nss_tx_status_t status; 625 struct net_device *dev; 626 int32_t if_num; 627 struct nss_ctx_instance *nss_ctx; 628 uint32_t ret; 629 630 if (!handle) { 631 nss_warning("handle is NULL\n"); 632 return NSS_TX_FAILURE_BAD_PARAM; 633 } 634 635 if_num = handle->if_num; 636 nss_ctx = handle->nss_ctx; 637 638 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 639 nss_warning("%p: Interface could not be destroyed as core not ready\n", nss_ctx); 640 return NSS_TX_FAILURE_NOT_READY; 641 } 642 643 spin_lock_bh(&nss_top_main.lock); 644 if (!nss_top_main.subsys_dp_register[if_num].ndev) { 645 spin_unlock_bh(&nss_top_main.lock); 646 nss_warning("%p: Unregister redir interface %d: no context\n", nss_ctx, if_num); 647 return NSS_TX_FAILURE_BAD_PARAM; 648 } 649 650 dev = nss_top_main.subsys_dp_register[if_num].ndev; 651 nss_top_main.subsys_dp_register[if_num].ndev = NULL; 652 spin_unlock_bh(&nss_top_main.lock); 653 dev_put(dev); 654 655 status = nss_tx_rx_virt_if_handle_destroy(handle); 656 if (status != NSS_TX_SUCCESS) { 657 nss_warning("%p: handle destroy failed for if_num %d\n", nss_ctx, if_num); 658 return NSS_TX_FAILURE; 659 } 660 661 ret = nss_core_unregister_handler(if_num); 662 if (ret != NSS_CORE_STATUS_SUCCESS) { 663 nss_warning("%p: Not able to unregister handler for redir_if interface %d with NSS core\n", nss_ctx, if_num); 664 return NSS_TX_FAILURE_BAD_PARAM; 665 } 666 667 return status; 668} 669 670/* 671 * nss_tx_rx_virt_if_copy_stats() 672 * Copy stats from the redir_if handle to buffer(line) 673 */ 674int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line) 675{ 676 int32_t bytes = 0; 677 struct nss_tx_rx_virt_if_stats *stats; 678 int32_t ifnum; 679 uint32_t len = 80; 680 struct nss_tx_rx_virt_if_handle *handle = NULL; 681 682 if (if_num < 0) { 683 nss_warning("invalid if_num\n"); 684 return 0; 685 } 686 687 ifnum = NSS_TX_RX_VIRT_IF_GET_INDEX(if_num); 688 689 spin_lock_bh(&nss_tx_rx_virt_if_lock); 690 if (!nss_tx_rx_virt_if_handles[ifnum]) { 691 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 692 goto end; 693 } 694 695 handle = nss_tx_rx_virt_if_handles[ifnum]; 696 spin_unlock_bh(&nss_tx_rx_virt_if_lock); 697 698 stats = &handle->stats; 699 700 switch (i) { 701 case 0: 702 bytes = scnprintf(line, len, "rx_packets=%d\n", 703 stats->node_stats.rx_packets); 704 break; 705 706 case 1: 707 bytes = scnprintf(line, len, "rx_bytes=%d\n", 708 stats->node_stats.rx_bytes); 709 break; 710 711 case 2: 712 bytes = scnprintf(line, len, "rx_dropped=%d\n", 713 stats->node_stats.rx_dropped); 714 break; 715 716 case 3: 717 bytes = scnprintf(line, len, "tx_packets=%d\n", 718 stats->node_stats.tx_packets); 719 break; 720 721 case 4: 722 bytes = scnprintf(line, len, "tx_bytes=%d\n", 723 stats->node_stats.tx_bytes); 724 break; 725 726 case 5: 727 bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n", 728 stats->tx_enqueue_failed); 729 break; 730 731 case 6: 732 bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n", 733 stats->shaper_enqueue_failed); 734 break; 735 } 736 737end: 738 return bytes; 739} 740 741EXPORT_SYMBOL(nss_tx_virt_if_rxbuf); 742EXPORT_SYMBOL(nss_tx_virt_if_rx_nwifibuf); 743EXPORT_SYMBOL(nss_create_virt_if); 744EXPORT_SYMBOL(nss_destroy_virt_if); 745EXPORT_SYMBOL(nss_register_virt_if); 746EXPORT_SYMBOL(nss_unregister_virt_if); 747