blob: 961e56cfe407631c77cd9d73e899cc8efd2cdfa5 [file] [log] [blame]
Rakesh Nair888af952017-06-30 18:41:58 +05301/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
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#include "edma.h"
17#include "ess_edma.h"
18
19#define EDMA_SYSCTL_RBUF_MAX_SIZE 300
20#define EDMA_SYSCTL_WBUF_MAX_SIZE 7
21
22extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED];
23
24const char *edma_access_category[] = {
25 "BK",
26 "BE",
27 "VI",
28 "VO",
29};
30
31u8 edma_dscp2ac_tbl[EDMA_PRECEDENCE_MAX];
32u8 edma_per_prec_stats_enable __read_mostly = 0;
33u8 edma_prec_stats_reset __read_mostly = 0;
34
35/* edma_dscp2ac_mapping_update()
36 * Map dscp to user-provided Access category values
37 */
38int edma_dscp2ac_mapping_update(struct ctl_table *table, int write,
39 void __user *buffer, size_t *lenp,
40 loff_t *ppos)
41{
42 char *tokens[EDMA_DSCP2AC_INPUT_PARAMS_MAX];
43 char *readbuf = NULL;
44 size_t add_len = 0;
45 int len, i, ret;
46 u8 precedence, ac;
47 char writebuf[EDMA_SYSCTL_WBUF_MAX_SIZE];
48 loff_t w_offset = 0;
49 char *str;
50 int count;
51
52 if (write) {
53 add_len = simple_write_to_buffer(writebuf, sizeof(writebuf), &w_offset, buffer, EDMA_SYSCTL_WBUF_MAX_SIZE - 1);
54 writebuf[add_len] = '\0';
55
56 count = 0;
57 str = writebuf;
58 tokens[count] = strsep(&str, " ");
59 while (tokens[count] != NULL) {
60 count++;
61 if (count == EDMA_DSCP2AC_INPUT_PARAMS_MAX) {
62 break;
63 }
64
65 tokens[count] = strsep(&str, " ");
66 }
67
68 ret = sscanf(tokens[0], "%hhu", &precedence);
69 if (ret != 1) {
70 pr_err("Failed to read precedence token\n");
71 return -EFAULT;
72 }
73
74 ret = sscanf(tokens[1], "%hhu", &ac);
75 if (ret != 1) {
76 pr_err("Failed to read AC token\n");
77 return -EFAULT;
78 }
79
80 /* Use first 3-bits of the 6-bit input DSCP for precedence */
81 precedence = precedence >> 3;
82
83 if (precedence > 7 || ac > 3 ) {
84 pr_info(" Invalid Input. Valid Range: precedence - 0-7, ac - 0-3\n");
85 return -EINVAL;
86 }
87
88 /* Update access category in the global dscp table */
89 edma_dscp2ac_tbl[precedence] = ac;
90
91 return 0;
92 }
93
94 readbuf = vmalloc(EDMA_SYSCTL_RBUF_MAX_SIZE);
95 if (!readbuf) {
96 pr_err("Failed to allocate Memory\n");
97 return -EINVAL;
98 }
99
100 len = scnprintf(readbuf + add_len, 45 ,"%s \n", "precedence: 0 1 2 3 4 5 6 7\n");
101 add_len += len;
102 len = scnprintf(readbuf + add_len, 15, "%s", "AC: ");
103 add_len += len;
104
105 for (i = 0; i < EDMA_PRECEDENCE_MAX; i++) {
106 len = scnprintf(readbuf + add_len, 6, " %s ", edma_access_category[edma_dscp2ac_tbl[i]]);
107 add_len += len;
108 }
109
110 len = scnprintf(readbuf + add_len, 4, "\n\n");
111 add_len += len;
112
113 /* Add Usage/help details in the read buffer */
114 len = scnprintf(readbuf + add_len, 40, "Usage: echo \"<dscp> <AC>\" > dscp2ac\n");
115 add_len += len;
116 len = scnprintf(readbuf + add_len, 37, "dscp: 6 bits dscp value in Decimal\n");
117 add_len += len;
118 len = scnprintf(readbuf + add_len, 55, "AC: 0 --> BK\n 1 --> BE\n 2 --> VI\n 3 --> VO\n");
119 add_len += len;
120
121 add_len = simple_read_from_buffer(buffer, *lenp, ppos, readbuf, add_len);
122 *lenp = add_len;
123
124 vfree(readbuf);
125
126 return 0;
127}
128
129/* edma_per_prec_stats_enable_handler()
130 * Enable per precedence statistics
131 */
132int edma_per_prec_stats_enable_handler(struct ctl_table *table, int write,
133 void __user *buffer, size_t *lenp,
134 loff_t *ppos)
135{
136 int ret;
137
138 ret = proc_dointvec(table, write, buffer, lenp, ppos);
139
140 if ((!write) || (ret))
141 return ret;
142
143 switch (edma_per_prec_stats_enable) {
144 case 0:
145 case 1:
146 break;
147 default:
148 pr_err("Invalid input. Valid values: <0|1>\n");
149 ret = -1;
150 break;
151 }
152
153 return ret;
154}
155
156/* edma_prec_stats_reset_handler()
157 * Reset per-precedence statistics
158 */
159int edma_prec_stats_reset_handler(struct ctl_table *table, int write,
160 void __user *buffer, size_t *lenp,
161 loff_t *ppos)
162{
163 struct edma_adapter *adapter;
164 struct edma_common_info *edma_cinfo;
165 int ret;
166
167 if (!edma_netdev[0]) {
168 pr_err("Invalid Netdevice\n");
169 return -1;
170 }
171
172 adapter = netdev_priv(edma_netdev[0]);
173 edma_cinfo = adapter->edma_cinfo;
174
175 ret = proc_dointvec(table, write, buffer, lenp, ppos);
176
177 if ((!write) || (ret))
178 return ret;
179
180 switch (edma_prec_stats_reset) {
181 case 0:
182 break;
183 case 1:
184 memset(&edma_cinfo->edma_ethstats.tx_prec, 0, sizeof(u64) * EDMA_PRECEDENCE_MAX);
185 memset(&edma_cinfo->edma_ethstats.rx_prec, 0, sizeof(u64) * EDMA_PRECEDENCE_MAX);
186 memset(&edma_cinfo->edma_ethstats.tx_ac, 0, sizeof(u64) * EDMA_AC_MAX);
187 memset(&edma_cinfo->edma_ethstats.rx_ac, 0, sizeof(u64) * EDMA_AC_MAX);
188 break;
189 default:
190 pr_err("Invalid input\n");
191 ret = -1;
192 break;
193 }
194
195 return ret;
196}
197