blob: 28a706768743150ce685541549d1d0cef2ace5f0 [file] [log] [blame]
Sol Kavya55c9a52014-04-08 14:33:16 -07001/*
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/*
18 * nss_if.c
19 * NSS base interfaces
20 */
21
22#include "nss_tx_rx_common.h"
23#include "nss_if.h"
24
25/*
26 * nss_if_msg_handler()
27 * Handle NSS -> HLOS messages for base class interfaces
28 */
29void nss_if_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm,
30 __attribute__((unused))void *app_data)
31{
32 struct nss_if_msg *nim = (struct nss_if_msg *)ncm;
33 nss_if_msg_callback_t cb;
34
35 /*
36 * We only support base class messages with this interface
37 */
38 if (ncm->type > NSS_IF_MAX_MSG_TYPES) {
39 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
40 return;
41 }
42
43 /*
44 * As the base class we allow both virtual and physical interfaces.
45 */
46 if (ncm->interface > NSS_TUNNEL_IF_START) {
47 nss_warning("%p: response for another interface: %d", nss_ctx, ncm->interface);
48 return;
49 }
50
51 if (ncm->len > sizeof(struct nss_if_msg)) {
52 nss_warning("%p: message length too big: %d", nss_ctx, ncm->len);
53 return;
54 }
55
56 /*
57 * Log failures
58 */
59 nss_core_log_msg_failures(nss_ctx, ncm);
60
61 /*
62 * Do we have a callback?
63 */
64 if (!ncm->cb) {
65 return;
66 }
67
68 /*
69 * Callback
70 */
71 cb = (nss_if_msg_callback_t)ncm->cb;
72 cb((void *)ncm->app_data, nim);
73}
74
75/*
76 * nss_if_tx_buf()
77 * Send packet to interface owned by NSS
78 */
79nss_tx_status_t nss_if_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf, uint32_t if_num)
80{
81 int32_t status;
82
83 nss_trace("%p: If Tx packet, id:%d, data=%p", nss_ctx, if_num, os_buf->data);
84
85 NSS_VERIFY_CTX_MAGIC(nss_ctx);
86 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
87 nss_warning("%p: 'Phys If Tx' packet dropped as core not ready", nss_ctx);
88 return NSS_TX_FAILURE_NOT_READY;
89 }
90
91 status = nss_core_send_buffer(nss_ctx, if_num, os_buf, NSS_IF_DATA_QUEUE, H2N_BUFFER_PACKET, 0);
92 if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) {
93 nss_warning("%p: Unable to enqueue 'Phys If Tx' packet\n", nss_ctx);
94 if (status == NSS_CORE_STATUS_FAILURE_QUEUE) {
95 return NSS_TX_FAILURE_QUEUE;
96 }
97 return NSS_TX_FAILURE;
98 }
99
100 /*
101 * Kick the NSS awake so it can process our new entry.
102 */
103 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_DATA_QUEUE].desc_ring.int_bit,
104 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
105 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
106 return NSS_TX_SUCCESS;
107}
108
109/*
110 * nss_if_tx_msg()
111 * Transmit a message to the specific interface on this core.
112 */
113nss_tx_status_t nss_if_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_if_msg *nim)
114{
115 struct nss_cmn_msg *ncm = &nim->cm;
116 struct nss_if_msg *nim2;
117 struct net_device *dev;
118 struct sk_buff *nbuf;
119 uint32_t if_num;
120 int32_t status;
121
122 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
123 nss_warning("Interface could not be created as core not ready");
124 return NSS_TX_FAILURE;
125 }
126
127 /*
128 * Sanity check the message
129 */
130 /*
131 * As the base class we allow both virtual and physical interfaces.
132 */
133 if (ncm->interface > NSS_TUNNEL_IF_START) {
134 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
135 return NSS_TX_FAILURE;
136 }
137
138 if (ncm->type > NSS_IF_MAX_MSG_TYPES) {
139 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
140 return NSS_TX_FAILURE;
141 }
142
143 if (ncm->len > sizeof(struct nss_if_msg)) {
144 nss_warning("%p: invalid length: %d", nss_ctx, ncm->len);
145 return NSS_TX_FAILURE;
146 }
147
148 if_num = ncm->interface;
149 dev = nss_top_main.if_ctx[if_num];
150 if (!dev) {
151 nss_warning("%p: Unregister interface %d: no context", nss_ctx, if_num);
152 return NSS_TX_FAILURE_BAD_PARAM;
153 }
154
155 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
156 if (unlikely(!nbuf)) {
157 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
158 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
159 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
160 nss_warning("%p: interface %p: command allocation failed", nss_ctx, dev);
161 return NSS_TX_FAILURE;
162 }
163
164 nim2 = (struct nss_if_msg *)skb_put(nbuf, sizeof(struct nss_if_msg));
165 memcpy(nim2, nim, sizeof(struct nss_if_msg));
166
167 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
168 if (status != NSS_CORE_STATUS_SUCCESS) {
169 dev_kfree_skb_any(nbuf);
170 nss_warning("%p: Unable to enqueue 'interface' command\n", nss_ctx);
171 return NSS_TX_FAILURE;
172 }
173
174 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
175 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
176 return NSS_TX_SUCCESS;
177}
178
179/*
180 * nss_if_register()
181 * Primary registration for receiving data and msgs from an interface.
182 */
183struct nss_ctx_instance *nss_if_register(uint32_t if_num,
Sakthi Vignesh Radhakrishnanef918492014-04-07 14:24:19 -0700184 nss_if_rx_callback_t rx_callback,
185 nss_if_msg_callback_t msg_callback,
Sol Kavya55c9a52014-04-08 14:33:16 -0700186 struct net_device *if_ctx)
187{
188 return NULL;
189}
190
191/*
192 * nss_if_unregister()
193 * Unregisteer the callback for this interface
194 */
195void nss_if_unregister(uint32_t if_num)
196{
197}
198
199EXPORT_SYMBOL(nss_if_tx_msg);
200EXPORT_SYMBOL(nss_if_register);
201EXPORT_SYMBOL(nss_if_unregister);