1/* 2 ************************************************************************** 3 * Copyright (c) 2014-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#include "nss_tx_rx_common.h" 18 19/* 20 * nss_sjack_node_sync_update() 21 * Update sjack node stats. 22 */ 23static void nss_sjack_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_sjack_stats_sync_msg *nins) 24{ 25 struct nss_top_instance *nss_top = nss_ctx->nss_top; 26 27 /* 28 * Update SJACK node stats. 29 */ 30 spin_lock_bh(&nss_top->stats_lock); 31 nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets; 32 nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes; 33 nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped; 34 nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets; 35 nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes; 36 spin_unlock_bh(&nss_top->stats_lock); 37} 38 39/* 40 * nss_sjack_handler() 41 * Handle NSS -> HLOS messages for sjack 42 */ 43static void nss_sjack_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, 44 __attribute__((unused))void *app_data) 45{ 46 void *ctx; 47 nss_sjack_msg_callback_t cb; 48 struct nss_sjack_msg *nsm = (struct nss_sjack_msg *)ncm; 49 50 BUG_ON(ncm->interface != NSS_SJACK_INTERFACE); 51 52 /* 53 * Is this a valid request/response packet? 54 */ 55 if (ncm->type >= NSS_SJACK_MAX_MSG_TYPE) { 56 nss_warning("%p: received invalid message %d for sjack interface", nss_ctx, ncm->type); 57 return; 58 } 59 60 if (ncm->len > sizeof(struct nss_sjack_msg)) { 61 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 62 return; 63 } 64 65 /* 66 * Update the callback and app_data for NOTIFY messages, sjack sends all notify messages 67 * to the same callback/app_data. 68 */ 69 if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) { 70 ncm->cb = (uint32_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface]; 71 } 72 73 /* 74 * Log failures 75 */ 76 nss_core_log_msg_failures(nss_ctx, ncm); 77 78 switch (ncm->type) { 79 case NSS_SJACK_STATS_SYNC_MSG: 80 /* 81 * Update sjack statistics on node sync. 82 */ 83 nss_sjack_node_sync_update(nss_ctx, &nsm->msg.stats_sync); 84 break; 85 } 86 87 /* 88 * Do we have a call back 89 */ 90 if (!ncm->cb) { 91 return; 92 } 93 94 /* 95 * callback 96 */ 97 cb = (nss_sjack_msg_callback_t)ncm->cb; 98 ctx = nss_ctx->nss_top->subsys_dp_register[ncm->interface].ndev; 99 100 cb(ctx, ncm); 101} 102 103 104/* 105 * nss_sjack_tx_msg() 106 * Transmit a sjack message to NSSFW 107 */ 108nss_tx_status_t nss_sjack_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_sjack_msg *msg) 109{ 110 struct nss_sjack_msg *nm; 111 struct nss_cmn_msg *ncm = &msg->cm; 112 struct sk_buff *nbuf; 113 int32_t status; 114 115 NSS_VERIFY_CTX_MAGIC(nss_ctx); 116 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 117 nss_warning("%p: sjack msg dropped as core not ready", nss_ctx); 118 return NSS_TX_FAILURE_NOT_READY; 119 } 120 121 /* 122 * Sanity check the message 123 */ 124 if (ncm->interface != NSS_SJACK_INTERFACE) { 125 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 126 return NSS_TX_FAILURE; 127 } 128 129 if (ncm->type > NSS_SJACK_MAX_MSG_TYPE) { 130 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 131 return NSS_TX_FAILURE; 132 } 133 134 if (ncm->len > sizeof(struct nss_sjack_msg)) { 135 nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len); 136 return NSS_TX_FAILURE; 137 } 138 139 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE); 140 if (unlikely(!nbuf)) { 141 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]); 142 nss_warning("%p: msg dropped as command allocation failed", nss_ctx); 143 return NSS_TX_FAILURE; 144 } 145 146 /* 147 * Copy the message to our skb 148 */ 149 nm = (struct nss_sjack_msg *)skb_put(nbuf, sizeof(struct nss_sjack_msg)); 150 memcpy(nm, msg, sizeof(struct nss_sjack_msg)); 151 152 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0); 153 if (status != NSS_CORE_STATUS_SUCCESS) { 154 dev_kfree_skb_any(nbuf); 155 nss_warning("%p: Unable to enqueue 'sjack message' \n", nss_ctx); 156 return NSS_TX_FAILURE; 157 } 158 159 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, 160 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE); 161 162 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]); 163 return NSS_TX_SUCCESS; 164} 165 166/* 167 * nss_sjack_register_if() 168 */ 169struct nss_ctx_instance *nss_sjack_register_if(uint32_t if_num, struct net_device *netdev, 170 nss_sjack_msg_callback_t event_callback) 171{ 172 nss_assert(if_num == NSS_SJACK_INTERFACE); 173 174 nss_top_main.subsys_dp_register[if_num].ndev = netdev; 175 176 nss_top_main.if_rx_msg_callback[if_num] = event_callback; 177 178 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.sjack_handler_id]; 179} 180 181/* 182 * nss_sjack_unregister_if() 183 */ 184void nss_sjack_unregister_if(uint32_t if_num) 185{ 186 nss_assert(if_num == NSS_SJACK_INTERFACE); 187 188 nss_top_main.subsys_dp_register[if_num].ndev = NULL; 189 nss_top_main.if_rx_msg_callback[if_num] = NULL; 190 191 return; 192} 193 194/* 195 * nss_sjack_register_handler() 196 * Registering handler for sending msg to sjack node on NSS. 197 */ 198void nss_sjack_register_handler(void) 199{ 200 nss_core_register_handler(NSS_SJACK_INTERFACE, nss_sjack_handler, NULL); 201} 202 203EXPORT_SYMBOL(nss_sjack_register_if); 204EXPORT_SYMBOL(nss_sjack_unregister_if); 205EXPORT_SYMBOL(nss_sjack_tx_msg); 206