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