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_profiler.c 19 * NSS profiler APIs 20 */ 21 22#include "nss_tx_rx_common.h" 23 24/* 25 * nss_profiler_rx_msg_handler() 26 * Handle profiler information. 27 */ 28static void nss_profiler_rx_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app) 29{ 30 struct nss_profiler_msg *pm = (struct nss_profiler_msg*)ncm; 31 void *ctx = nss_ctx->nss_top->profiler_ctx[nss_ctx->id]; 32 nss_profiler_callback_t cb = nss_ctx->nss_top->profiler_callback[nss_ctx->id]; 33 34 if (ncm->type >= NSS_PROFILER_MAX_MSG_TYPES) { 35 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 36 return; 37 } 38 39 if (ncm->type <= NSS_PROFILER_FLOWCTRL_MSG) { 40 if (ncm->len > sizeof(pm->payload.pcmdp)) { 41 nss_warning("%p: reply for cmd %d size is wrong %d : %d\n", nss_ctx, ncm->type, ncm->len, ncm->interface); 42 return; 43 } 44 } else if (ncm->type <= NSS_PROFILER_DEBUG_REPLY_MSG) { 45 if (ncm->len > sizeof(pm->payload.pdm)) { 46 nss_warning("%p: reply for debug %d is too big %d\n", nss_ctx, ncm->type, ncm->len); 47 return; 48 } 49 } else if (ncm->type <= NSS_PROFILER_COUNTERS_MSG) { 50 if (ncm->len < (sizeof(pm->payload.pcmdp) - (PROFILE_MAX_APP_COUNTERS - pm->payload.pcmdp.num_counters) * sizeof(pm->payload.pcmdp.counters[0])) || ncm->len > sizeof(pm->payload.pcmdp)) { 51 nss_warning("%p: %d params data is too big %d : %d\n", nss_ctx, ncm->type, ncm->len, ncm->interface); 52 return; 53 } 54 } 55 56 /* 57 * status per request callback 58 */ 59 if (ncm->response != NSS_CMM_RESPONSE_NOTIFY && ncm->cb) { 60 nss_info("%p: reply CB %x for %d %d\n", nss_ctx, ncm->cb, ncm->type, ncm->response); 61 cb = (nss_profiler_callback_t)ncm->cb; 62 } 63 64 /* 65 * sample related callback 66 */ 67 if (!cb || !ctx) { 68 nss_warning("%p: Event received for profiler interface before registration", nss_ctx); 69 return; 70 } 71 72 cb(ctx, (struct nss_profiler_msg *)ncm); 73} 74 75/* 76 * nss_tx_profiler_if_buf() 77 * NSS profiler Tx API 78 */ 79nss_tx_status_t nss_profiler_if_tx_buf(void *ctx, void *buf, uint32_t len, void *cb) 80{ 81 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)ctx; 82 struct sk_buff *nbuf; 83 int32_t status; 84 struct nss_profiler_msg *npm; 85 struct nss_profiler_data_msg *pdm = (struct nss_profiler_data_msg *)buf; 86 87 nss_trace("%p: Profiler If Tx, buf=%p", nss_ctx, buf); 88 89 NSS_VERIFY_CTX_MAGIC(nss_ctx); 90 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 91 nss_warning("%p: 'Profiler If Tx' rule dropped as core not ready", nss_ctx); 92 return NSS_TX_FAILURE_NOT_READY; 93 } 94 95 if (NSS_NBUF_PAYLOAD_SIZE < (len + sizeof(*npm))) { 96 return NSS_TX_FAILURE_TOO_LARGE; 97 } 98 99 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE); 100 if (unlikely(!nbuf)) { 101 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]); 102 nss_warning("%p: 'Profiler If Tx' rule dropped as command allocation failed", nss_ctx); 103 return NSS_TX_FAILURE; 104 } 105 106 npm = (struct nss_profiler_msg *)skb_put(nbuf, sizeof(npm->cm) + len); 107 nss_profiler_msg_init(npm, NSS_PROFILER_INTERFACE, pdm->hd_magic & 0xFF, len, 108 cb, ctx); 109 memcpy(&npm->payload, pdm, len); 110 111 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0); 112 if (status != NSS_CORE_STATUS_SUCCESS) { 113 dev_kfree_skb_any(nbuf); 114 nss_warning("%p: Unable to enqueue 'Profiler If cmd Tx\n", nss_ctx); 115 return NSS_TX_FAILURE; 116 } 117 118 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, 119 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE); 120 121 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]); 122 return NSS_TX_SUCCESS; 123} 124 125/* 126 * nss_profiler_notify_register() 127 */ 128void *nss_profiler_notify_register(nss_core_id_t core_id, nss_profiler_callback_t profiler_callback, void *ctx) 129{ 130 nss_assert(core_id < NSS_CORE_MAX); 131 132 if ((core_id == NSS_CORE_0) && (NSS_CORE_STATUS_SUCCESS != 133 nss_core_register_handler(NSS_PROFILER_INTERFACE, nss_profiler_rx_msg_handler, NULL))) { 134 nss_warning("Message handler FAILED to be registered for profiler"); 135 return NULL; 136 } 137 138 nss_top_main.profiler_ctx[core_id] = ctx; 139 nss_top_main.profiler_callback[core_id] = profiler_callback; 140 141 return (void *)&nss_top_main.nss[core_id]; 142} 143 144/* 145 * nss_profiler_notify_unregister() 146 */ 147void nss_profiler_notify_unregister(nss_core_id_t core_id) 148{ 149 nss_assert(core_id < NSS_CORE_MAX); 150 151 nss_core_register_handler(NSS_PROFILER_INTERFACE, NULL, NULL); 152 nss_top_main.profiler_callback[core_id] = NULL; 153 nss_top_main.profiler_ctx[core_id] = NULL; 154} 155 156/* 157 * nss_profiler_msg_init() 158 * Initialize profiler message. 159 */ 160void nss_profiler_msg_init(struct nss_profiler_msg *npm, uint16_t if_num, uint32_t type, uint32_t len, 161 nss_profiler_callback_t cb, void *app_data) 162{ 163 nss_cmn_msg_init(&npm->cm, if_num, type, len, (void *)cb, app_data); 164} 165 166EXPORT_SYMBOL(nss_profiler_notify_register); 167EXPORT_SYMBOL(nss_profiler_notify_unregister); 168EXPORT_SYMBOL(nss_profiler_if_tx_buf); 169EXPORT_SYMBOL(nss_profiler_msg_init); 170