blob: c553a76be3d05ef3c00cde1e623d5d8a058ce5d3 [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;
41
42 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L3_FLOWS] += stats_msg->nss_ppe_v6_l3_flows;
43 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L2_FLOWS] += stats_msg->nss_ppe_v6_l2_flows;
44 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_REQ] += stats_msg->nss_ppe_v6_create_req;
45 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_FAIL] += stats_msg->nss_ppe_v6_create_fail;
46 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_REQ] += stats_msg->nss_ppe_v6_destroy_req;
47 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_FAIL] += stats_msg->nss_ppe_v6_destroy_fail;
48
49 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_NH_FULL] += stats_msg->nss_ppe_fail_nh_full;
50 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_FULL] += stats_msg->nss_ppe_fail_flow_full;
51 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_HOST_FULL] += stats_msg->nss_ppe_fail_host_full;
52 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PUBIP_FULL] += stats_msg->nss_ppe_fail_pubip_full;
53 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PORT_SETUP] += stats_msg->nss_ppe_fail_port_setup;
54 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_RW_FIFO_FULL] += stats_msg->nss_ppe_fail_rw_fifo_full;
55 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_COMMAND] += stats_msg->nss_ppe_fail_flow_command;
56 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_UNKNOWN_PROTO] += stats_msg->nss_ppe_fail_unknown_proto;
57 nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PPE_UNRESPONSIVE] += stats_msg->nss_ppe_fail_ppe_unresponsive;
Thomas Wufc4d9fd2017-03-22 10:15:30 -070058 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 +053059 spin_unlock_bh(&nss_ppe_stats_lock);
60}
61
62/*
63 * nss_ppe_stats_conn_get()
64 * Get ppe connection stats.
65 */
66void nss_ppe_stats_conn_get(uint32_t *stats)
67{
68 if (!stats) {
69 nss_warning("No memory to copy ppe connection stats");
70 return;
71 }
72
73 spin_lock_bh(&nss_ppe_stats_lock);
74
75 if (!nss_ppe_debug_stats.valid) {
76 spin_unlock_bh(&nss_ppe_stats_lock);
77 nss_warning("PPE base address not initialized!\n");
78 return;
79 }
80
81 /*
82 * Get flow stats
83 */
84 memcpy(stats, nss_ppe_debug_stats.conn_stats, (sizeof(uint32_t) * NSS_STATS_PPE_CONN_MAX));
85
86 spin_unlock_bh(&nss_ppe_stats_lock);
87}
88
89/*
90 * nss_ppe_stats_l3_get()
91 * Get ppe L3 debug stats.
92 */
93void nss_ppe_stats_l3_get(uint32_t *stats)
94{
95 if (!stats) {
96 nss_warning("No memory to copy ppe l3 dbg stats\n");
97 return;
98 }
99
100 spin_lock_bh(&nss_ppe_stats_lock);
101
102 if (!nss_ppe_debug_stats.valid) {
103 spin_unlock_bh(&nss_ppe_stats_lock);
104 nss_warning("PPE base address not initialized!\n");
105 return;
106 }
107
108 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG0_OFFSET);
109 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_0]);
110
111 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG1_OFFSET);
112 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_1]);
113
114 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG2_OFFSET);
115 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_2]);
116
117 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG3_OFFSET);
118 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_3]);
119
120 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG4_OFFSET);
121 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_4]);
122
123 nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG_PORT_OFFSET);
124 nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_PORT]);
125
126 spin_unlock_bh(&nss_ppe_stats_lock);
127}
128
129/*
130 * nss_ppe_stats_code_get()
131 * Get ppe CPU and DROP code for last packet processed.
132 */
133void nss_ppe_stats_code_get(uint32_t *stats)
134{
135 uint32_t drop_0, drop_1, cpu_code;
136
137 nss_trace("%s(%d) Start\n", __func__, __LINE__);
138 if (!stats) {
139 nss_warning("No memory to copy ppe code\n");
140 return;
141 }
142
143 if (!nss_ppe_debug_stats.valid) {
144 nss_warning("PPE base address not initialized!\n");
145 return;
146 }
147
148 spin_lock_bh(&nss_ppe_stats_lock);
149 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP0_OFFSET);
150 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_0);
151
152 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP1_OFFSET);
153 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_1);
154
155 stats[NSS_STATS_PPE_CODE_DROP] = PPE_PKT_CODE_DROP_GET(drop_0, drop_1);
156
157 nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_CPU_OFFSET);
158 nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &cpu_code);
159
160 stats[NSS_STATS_PPE_CODE_CPU] = PPE_PKT_CODE_CPU_GET(cpu_code);
161
162 spin_unlock_bh(&nss_ppe_stats_lock);
163}
164
165/*
166 * nss_ppe_handler()
167 * Handle NSS -> HLOS messages for ppe tunnel
168 */
169static void nss_ppe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
170{
171 struct nss_ppe_msg *msg = (struct nss_ppe_msg *)ncm;
172
173 nss_trace("nss_ctx: %p ppe msg: %p", nss_ctx, msg);
174 BUG_ON(!nss_ppe_verify_ifnum(ncm->interface));
175
176 /*
177 * Is this a valid request/response packet?
178 */
179 if (ncm->type >= NSS_PPE_MSG_MAX) {
180 nss_warning("%p: received invalid message %d for PPE interface", nss_ctx, ncm->type);
181 return;
182 }
183
184 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ppe_msg)) {
185 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
186 return;
187 }
188
189 switch (msg->cm.type) {
190 case NSS_PPE_MSG_SYNC_STATS:
191 /*
192 * session debug stats embeded in session stats msg
193 */
194 nss_ppe_stats_sync(nss_ctx, &msg->msg.stats, ncm->interface);
195 break;
196 }
197}
198
199/*
200 * nss_ppe_register_handler()
201 * debugfs stats msg handler received on static ppe interface
202 *
203 * TODO: Export API so that others can also read PPE stats.
204 */
205void nss_ppe_register_handler(void)
206{
207 nss_core_register_handler(NSS_PPE_INTERFACE, nss_ppe_handler, NULL);
208}
209
210/*
211 * nss_ppe_free()
212 * Uninitialize PPE base
213 */
214void nss_ppe_free(void)
215{
216 /*
217 * Check if PPE base is already uninitialized.
218 */
219 if (!ppe_pvt.ppe_base) {
220 return;
221 }
222
223 /*
224 * Unmap PPE base address
225 */
226 iounmap(ppe_pvt.ppe_base);
227 ppe_pvt.ppe_base = NULL;
228
229 spin_lock_bh(&nss_ppe_stats_lock);
230 nss_ppe_debug_stats.valid = false;
231 nss_ppe_debug_stats.if_num = 0;
232 nss_ppe_debug_stats.if_index = 0;
233 spin_unlock_bh(&nss_ppe_stats_lock);
234}
235
236/*
237 * nss_ppe_init()
238 * Initialize PPE base
239 */
240void nss_ppe_init(void)
241{
242 /*
243 * Check if PPE base is already initialized.
244 */
245 if (ppe_pvt.ppe_base) {
246 return;
247 }
248
249 /*
250 * Get the PPE base address
251 */
252 ppe_pvt.ppe_base = ioremap_nocache(PPE_BASE_ADDR, PPE_REG_SIZE);
253 if (!ppe_pvt.ppe_base) {
254 nss_warning("DRV can't get PPE base address\n");
255 return;
256 }
257
258 spin_lock_bh(&nss_ppe_stats_lock);
259 nss_ppe_debug_stats.valid = true;
260 nss_ppe_debug_stats.if_num = 0;
261 nss_ppe_debug_stats.if_index = 0;
262 spin_unlock_bh(&nss_ppe_stats_lock);
263}