blob: cd3e1f6e2f09e301cf0968cf32103a4220fb9325 [file] [log] [blame]
Amit Gupta316729b2016-08-12 12:21:15 +05301/*
2 **************************************************************************
Thomas Wufc4d9fd2017-03-22 10:15:30 -07003 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Amit Gupta316729b2016-08-12 12:21:15 +05304 * 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_ppe.h"
18
19/*
20 * nss_ppe_verify_ifnum()
21 * Verify PPE interface number.
22 */
23static inline bool nss_ppe_verify_ifnum(int if_num)
24{
25 return nss_is_dynamic_interface(if_num) || (if_num == NSS_PPE_INTERFACE);
26}
27
28/*
29 * nss_ppe_stats_sync
30 * PPE connection sync stats from NSS
31 */
32static void nss_ppe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ppe_sync_stats_msg *stats_msg, uint16_t if_num)
33{
34 spin_lock_bh(&nss_ppe_stats_lock);
35 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_L3_FLOWS] += stats_msg->nss_ppe_v4_l3_flows;
36 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_L2_FLOWS] += stats_msg->nss_ppe_v4_l2_flows;
37 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_CREATE_REQ] += stats_msg->nss_ppe_v4_create_req;
38 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_CREATE_FAIL] += stats_msg->nss_ppe_v4_create_fail;
39 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_DESTROY_REQ] += stats_msg->nss_ppe_v4_destroy_req;
40 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_DESTROY_FAIL] += stats_msg->nss_ppe_v4_destroy_fail;
Amit Gupta263df9c2017-05-16 20:43:07 +053041 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_CREATE_REQ] += stats_msg->nss_ppe_v4_mc_create_req;
42 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_CREATE_FAIL] += stats_msg->nss_ppe_v4_mc_create_fail;
43 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_UPDATE_REQ] += stats_msg->nss_ppe_v4_mc_update_req;
44 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_UPDATE_FAIL] += stats_msg->nss_ppe_v4_mc_update_fail;
45 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_DESTROY_REQ] += stats_msg->nss_ppe_v4_mc_destroy_req;
46 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_DESTROY_FAIL] += stats_msg->nss_ppe_v4_mc_destroy_fail;
Amit Gupta316729b2016-08-12 12:21:15 +053047
48 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L3_FLOWS] += stats_msg->nss_ppe_v6_l3_flows;
49 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L2_FLOWS] += stats_msg->nss_ppe_v6_l2_flows;
50 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_REQ] += stats_msg->nss_ppe_v6_create_req;
51 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_FAIL] += stats_msg->nss_ppe_v6_create_fail;
52 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_REQ] += stats_msg->nss_ppe_v6_destroy_req;
53 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_FAIL] += stats_msg->nss_ppe_v6_destroy_fail;
Amit Gupta263df9c2017-05-16 20:43:07 +053054 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_CREATE_REQ] += stats_msg->nss_ppe_v6_mc_create_req;
55 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_CREATE_FAIL] += stats_msg->nss_ppe_v6_mc_create_fail;
56 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_UPDATE_REQ] += stats_msg->nss_ppe_v6_mc_update_req;
57 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_UPDATE_FAIL] += stats_msg->nss_ppe_v6_mc_update_fail;
58 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_DESTROY_REQ] += stats_msg->nss_ppe_v6_mc_destroy_req;
59 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_DESTROY_FAIL] += stats_msg->nss_ppe_v6_mc_destroy_fail;
Amit Gupta316729b2016-08-12 12:21:15 +053060
Amit Gupta263df9c2017-05-16 20:43:07 +053061 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_VP_FULL] += stats_msg->nss_ppe_fail_vp_full;
Amit Gupta316729b2016-08-12 12:21:15 +053062 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_NH_FULL] += stats_msg->nss_ppe_fail_nh_full;
63 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_FULL] += stats_msg->nss_ppe_fail_flow_full;
64 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_HOST_FULL] += stats_msg->nss_ppe_fail_host_full;
65 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PUBIP_FULL] += stats_msg->nss_ppe_fail_pubip_full;
66 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PORT_SETUP] += stats_msg->nss_ppe_fail_port_setup;
67 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_RW_FIFO_FULL] += stats_msg->nss_ppe_fail_rw_fifo_full;
68 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_COMMAND] += stats_msg->nss_ppe_fail_flow_command;
69 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_UNKNOWN_PROTO] += stats_msg->nss_ppe_fail_unknown_proto;
70 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PPE_UNRESPONSIVE] += stats_msg->nss_ppe_fail_ppe_unresponsive;
Amit Gupta263df9c2017-05-16 20:43:07 +053071 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_CE_OPAQUE_INVALID] += stats_msg->nss_ppe_ce_opaque_invalid;
Thomas Wufc4d9fd2017-03-22 10:15:30 -070072 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FQG_FULL] += stats_msg->nss_ppe_fail_fqg_full;
Amit Gupta316729b2016-08-12 12:21:15 +053073 spin_unlock_bh(&nss_ppe_stats_lock);
74}
75
76/*
77 * nss_ppe_stats_conn_get()
78 * Get ppe connection stats.
79 */
80void nss_ppe_stats_conn_get(uint32_t *stats)
81{
82 if (!stats) {
83 nss_warning("No memory to copy ppe connection stats");
84 return;
85 }
86
87 spin_lock_bh(&nss_ppe_stats_lock);
88
89 if (!nss_ppe_debug_stats.valid) {
90 spin_unlock_bh(&nss_ppe_stats_lock);
91 nss_warning("PPE base address not initialized!\n");
92 return;
93 }
94
95 /*
96 * Get flow stats
97 */
98 memcpy(stats, nss_ppe_debug_stats.conn_stats, (sizeof(uint32_t) * NSS_STATS_PPE_CONN_MAX));
99
100 spin_unlock_bh(&nss_ppe_stats_lock);
101}
102
103/*
104 * nss_ppe_stats_l3_get()
105 * Get ppe L3 debug stats.
106 */
107void nss_ppe_stats_l3_get(uint32_t *stats)
108{
109 if (!stats) {
110 nss_warning("No memory to copy ppe l3 dbg stats\n");
111 return;
112 }
113
114 spin_lock_bh(&nss_ppe_stats_lock);
115
116 if (!nss_ppe_debug_stats.valid) {
117 spin_unlock_bh(&nss_ppe_stats_lock);
118 nss_warning("PPE base address not initialized!\n");
119 return;
120 }
121
122 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG0_OFFSET);
123 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_0]);
124
125 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG1_OFFSET);
126 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_1]);
127
128 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG2_OFFSET);
129 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_2]);
130
131 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG3_OFFSET);
132 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_3]);
133
134 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG4_OFFSET);
135 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_4]);
136
137 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG_PORT_OFFSET);
138 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_PORT]);
139
140 spin_unlock_bh(&nss_ppe_stats_lock);
141}
142
143/*
144 * nss_ppe_stats_code_get()
145 * Get ppe CPU and DROP code for last packet processed.
146 */
147void nss_ppe_stats_code_get(uint32_t *stats)
148{
149 uint32_t drop_0, drop_1, cpu_code;
150
151 nss_trace("%s(%d) Start\n", __func__, __LINE__);
152 if (!stats) {
153 nss_warning("No memory to copy ppe code\n");
154 return;
155 }
156
157 if (!nss_ppe_debug_stats.valid) {
158 nss_warning("PPE base address not initialized!\n");
159 return;
160 }
161
162 spin_lock_bh(&nss_ppe_stats_lock);
163 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP0_OFFSET);
164 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_0);
165
166 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP1_OFFSET);
167 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_1);
168
169 stats[NSS_STATS_PPE_CODE_DROP] = PPE_PKT_CODE_DROP_GET(drop_0, drop_1);
170
171 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_CPU_OFFSET);
172 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &cpu_code);
173
174 stats[NSS_STATS_PPE_CODE_CPU] = PPE_PKT_CODE_CPU_GET(cpu_code);
175
176 spin_unlock_bh(&nss_ppe_stats_lock);
177}
178
179/*
180 * nss_ppe_handler()
181 * Handle NSS -> HLOS messages for ppe tunnel
182 */
183static void nss_ppe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
184{
185 struct nss_ppe_msg *msg = (struct nss_ppe_msg *)ncm;
186
187 nss_trace("nss_ctx: %p ppe msg: %p", nss_ctx, msg);
188 BUG_ON(!nss_ppe_verify_ifnum(ncm->interface));
189
190 /*
191 * Is this a valid request/response packet?
192 */
193 if (ncm->type >= NSS_PPE_MSG_MAX) {
194 nss_warning("%p: received invalid message %d for PPE interface", nss_ctx, ncm->type);
195 return;
196 }
197
198 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ppe_msg)) {
199 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
200 return;
201 }
202
203 switch (msg->cm.type) {
204 case NSS_PPE_MSG_SYNC_STATS:
205 /*
206 * session debug stats embeded in session stats msg
207 */
208 nss_ppe_stats_sync(nss_ctx, &msg->msg.stats, ncm->interface);
209 break;
210 }
211}
212
213/*
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700214 * nss_ppe_get_context()
215 * get NSS context instance for ppe
216 */
217struct nss_ctx_instance *nss_ppe_get_context(void)
218{
219 return &nss_top_main.nss[nss_top_main.ppe_handler_id];
220}
221EXPORT_SYMBOL(nss_ppe_get_context);
222
223/*
Amit Gupta316729b2016-08-12 12:21:15 +0530224 * nss_ppe_register_handler()
225 * debugfs stats msg handler received on static ppe interface
226 *
227 * TODO: Export API so that others can also read PPE stats.
228 */
229void nss_ppe_register_handler(void)
230{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700231 struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
232
233 nss_core_register_handler(nss_ctx, NSS_PPE_INTERFACE, nss_ppe_handler, NULL);
Amit Gupta316729b2016-08-12 12:21:15 +0530234}
235
236/*
237 * nss_ppe_free()
238 * Uninitialize PPE base
239 */
240void nss_ppe_free(void)
241{
242 /*
243 * Check if PPE base is already uninitialized.
244 */
245 if (!ppe_pvt.ppe_base) {
246 return;
247 }
248
249 /*
250 * Unmap PPE base address
251 */
252 iounmap(ppe_pvt.ppe_base);
253 ppe_pvt.ppe_base = NULL;
254
255 spin_lock_bh(&nss_ppe_stats_lock);
256 nss_ppe_debug_stats.valid = false;
257 nss_ppe_debug_stats.if_num = 0;
258 nss_ppe_debug_stats.if_index = 0;
259 spin_unlock_bh(&nss_ppe_stats_lock);
260}
261
262/*
263 * nss_ppe_init()
264 * Initialize PPE base
265 */
266void nss_ppe_init(void)
267{
268 /*
269 * Check if PPE base is already initialized.
270 */
271 if (ppe_pvt.ppe_base) {
272 return;
273 }
274
275 /*
276 * Get the PPE base address
277 */
278 ppe_pvt.ppe_base = ioremap_nocache(PPE_BASE_ADDR, PPE_REG_SIZE);
279 if (!ppe_pvt.ppe_base) {
280 nss_warning("DRV can't get PPE base address\n");
281 return;
282 }
283
284 spin_lock_bh(&nss_ppe_stats_lock);
285 nss_ppe_debug_stats.valid = true;
286 nss_ppe_debug_stats.if_num = 0;
287 nss_ppe_debug_stats.if_index = 0;
288 spin_unlock_bh(&nss_ppe_stats_lock);
289}