Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
26481 views
1
/***********************license start***************
2
* Author: Cavium Networks
3
*
4
* Contact: [email protected]
5
* This file is part of the OCTEON SDK
6
*
7
* Copyright (c) 2003-2008 Cavium Networks
8
*
9
* This file is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License, Version 2, as
11
* published by the Free Software Foundation.
12
*
13
* This file is distributed in the hope that it will be useful, but
14
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16
* NONINFRINGEMENT. See the GNU General Public License for more
17
* details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this file; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
* or visit http://www.gnu.org/licenses/.
23
*
24
* This file may also be available under a different license from Cavium.
25
* Contact Cavium Networks for more information
26
***********************license end**************************************/
27
28
/*
29
* Small helper utilities.
30
*/
31
#include <linux/kernel.h>
32
33
#include <asm/octeon/octeon.h>
34
35
#include <asm/octeon/cvmx-config.h>
36
37
#include <asm/octeon/cvmx-fpa.h>
38
#include <asm/octeon/cvmx-pip.h>
39
#include <asm/octeon/cvmx-pko.h>
40
#include <asm/octeon/cvmx-ipd.h>
41
#include <asm/octeon/cvmx-spi.h>
42
43
#include <asm/octeon/cvmx-helper.h>
44
#include <asm/octeon/cvmx-helper-util.h>
45
46
#include <asm/octeon/cvmx-ipd-defs.h>
47
48
/**
49
* Convert a interface mode into a human readable string
50
*
51
* @mode: Mode to convert
52
*
53
* Returns String
54
*/
55
const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t
56
mode)
57
{
58
switch (mode) {
59
case CVMX_HELPER_INTERFACE_MODE_DISABLED:
60
return "DISABLED";
61
case CVMX_HELPER_INTERFACE_MODE_RGMII:
62
return "RGMII";
63
case CVMX_HELPER_INTERFACE_MODE_GMII:
64
return "GMII";
65
case CVMX_HELPER_INTERFACE_MODE_SPI:
66
return "SPI";
67
case CVMX_HELPER_INTERFACE_MODE_PCIE:
68
return "PCIE";
69
case CVMX_HELPER_INTERFACE_MODE_XAUI:
70
return "XAUI";
71
case CVMX_HELPER_INTERFACE_MODE_SGMII:
72
return "SGMII";
73
case CVMX_HELPER_INTERFACE_MODE_PICMG:
74
return "PICMG";
75
case CVMX_HELPER_INTERFACE_MODE_NPI:
76
return "NPI";
77
case CVMX_HELPER_INTERFACE_MODE_LOOP:
78
return "LOOP";
79
}
80
return "UNKNOWN";
81
}
82
83
/**
84
* Setup Random Early Drop on a specific input queue
85
*
86
* @queue: Input queue to setup RED on (0-7)
87
* @pass_thresh:
88
* Packets will begin slowly dropping when there are less than
89
* this many packet buffers free in FPA 0.
90
* @drop_thresh:
91
* All incoming packets will be dropped when there are less
92
* than this many free packet buffers in FPA 0.
93
* Returns Zero on success. Negative on failure
94
*/
95
static int cvmx_helper_setup_red_queue(int queue, int pass_thresh,
96
int drop_thresh)
97
{
98
union cvmx_ipd_qosx_red_marks red_marks;
99
union cvmx_ipd_red_quex_param red_param;
100
101
/* Set RED to begin dropping packets when there are pass_thresh buffers
102
left. It will linearly drop more packets until reaching drop_thresh
103
buffers */
104
red_marks.u64 = 0;
105
red_marks.s.drop = drop_thresh;
106
red_marks.s.pass = pass_thresh;
107
cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64);
108
109
/* Use the actual queue 0 counter, not the average */
110
red_param.u64 = 0;
111
red_param.s.prb_con =
112
(255ul << 24) / (red_marks.s.pass - red_marks.s.drop);
113
red_param.s.avg_con = 1;
114
red_param.s.new_con = 255;
115
red_param.s.use_pcnt = 1;
116
cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64);
117
return 0;
118
}
119
120
/**
121
* Setup Random Early Drop to automatically begin dropping packets.
122
*
123
* @pass_thresh:
124
* Packets will begin slowly dropping when there are less than
125
* this many packet buffers free in FPA 0.
126
* @drop_thresh:
127
* All incoming packets will be dropped when there are less
128
* than this many free packet buffers in FPA 0.
129
* Returns Zero on success. Negative on failure
130
*/
131
int cvmx_helper_setup_red(int pass_thresh, int drop_thresh)
132
{
133
union cvmx_ipd_portx_bp_page_cnt page_cnt;
134
union cvmx_ipd_bp_prt_red_end ipd_bp_prt_red_end;
135
union cvmx_ipd_red_port_enable red_port_enable;
136
int queue;
137
int interface;
138
int port;
139
140
/* Disable backpressure based on queued buffers. It needs SW support */
141
page_cnt.u64 = 0;
142
page_cnt.s.bp_enb = 0;
143
page_cnt.s.page_cnt = 100;
144
for (interface = 0; interface < 2; interface++) {
145
for (port = cvmx_helper_get_first_ipd_port(interface);
146
port < cvmx_helper_get_last_ipd_port(interface); port++)
147
cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port),
148
page_cnt.u64);
149
}
150
151
for (queue = 0; queue < 8; queue++)
152
cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh);
153
154
/* Shutoff the dropping based on the per port page count. SW isn't
155
decrementing it right now */
156
ipd_bp_prt_red_end.u64 = 0;
157
ipd_bp_prt_red_end.s.prt_enb = 0;
158
cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64);
159
160
red_port_enable.u64 = 0;
161
red_port_enable.s.prt_enb = 0xfffffffffull;
162
red_port_enable.s.avg_dly = 10000;
163
red_port_enable.s.prb_dly = 10000;
164
cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64);
165
166
return 0;
167
}
168
EXPORT_SYMBOL_GPL(cvmx_helper_setup_red);
169
170
/**
171
* Setup the common GMX settings that determine the number of
172
* ports. These setting apply to almost all configurations of all
173
* chips.
174
*
175
* @interface: Interface to configure
176
* @num_ports: Number of ports on the interface
177
*
178
* Returns Zero on success, negative on failure
179
*/
180
int __cvmx_helper_setup_gmx(int interface, int num_ports)
181
{
182
union cvmx_gmxx_tx_prts gmx_tx_prts;
183
union cvmx_gmxx_rx_prts gmx_rx_prts;
184
union cvmx_pko_reg_gmx_port_mode pko_mode;
185
union cvmx_gmxx_txx_thresh gmx_tx_thresh;
186
int index;
187
188
/* Tell GMX the number of TX ports on this interface */
189
gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface));
190
gmx_tx_prts.s.prts = num_ports;
191
cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64);
192
193
/* Tell GMX the number of RX ports on this interface. This only
194
** applies to *GMII and XAUI ports */
195
if (cvmx_helper_interface_get_mode(interface) ==
196
CVMX_HELPER_INTERFACE_MODE_RGMII
197
|| cvmx_helper_interface_get_mode(interface) ==
198
CVMX_HELPER_INTERFACE_MODE_SGMII
199
|| cvmx_helper_interface_get_mode(interface) ==
200
CVMX_HELPER_INTERFACE_MODE_GMII
201
|| cvmx_helper_interface_get_mode(interface) ==
202
CVMX_HELPER_INTERFACE_MODE_XAUI) {
203
if (num_ports > 4) {
204
cvmx_dprintf("__cvmx_helper_setup_gmx: Illegal "
205
"num_ports\n");
206
return -1;
207
}
208
209
gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface));
210
gmx_rx_prts.s.prts = num_ports;
211
cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64);
212
}
213
214
/* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, and 50XX */
215
if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX)
216
&& !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
217
/* Tell PKO the number of ports on this interface */
218
pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE);
219
if (interface == 0) {
220
if (num_ports == 1)
221
pko_mode.s.mode0 = 4;
222
else if (num_ports == 2)
223
pko_mode.s.mode0 = 3;
224
else if (num_ports <= 4)
225
pko_mode.s.mode0 = 2;
226
else if (num_ports <= 8)
227
pko_mode.s.mode0 = 1;
228
else
229
pko_mode.s.mode0 = 0;
230
} else {
231
if (num_ports == 1)
232
pko_mode.s.mode1 = 4;
233
else if (num_ports == 2)
234
pko_mode.s.mode1 = 3;
235
else if (num_ports <= 4)
236
pko_mode.s.mode1 = 2;
237
else if (num_ports <= 8)
238
pko_mode.s.mode1 = 1;
239
else
240
pko_mode.s.mode1 = 0;
241
}
242
cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64);
243
}
244
245
/*
246
* Set GMX to buffer as much data as possible before starting
247
* transmit. This reduces the chances that we have a TX under
248
* run due to memory contention. Any packet that fits entirely
249
* in the GMX FIFO can never have an under run regardless of
250
* memory load.
251
*/
252
gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface));
253
if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX)
254
|| OCTEON_IS_MODEL(OCTEON_CN50XX)) {
255
/* These chips have a fixed max threshold of 0x40 */
256
gmx_tx_thresh.s.cnt = 0x40;
257
} else {
258
/* Choose the max value for the number of ports */
259
if (num_ports <= 1)
260
gmx_tx_thresh.s.cnt = 0x100 / 1;
261
else if (num_ports == 2)
262
gmx_tx_thresh.s.cnt = 0x100 / 2;
263
else
264
gmx_tx_thresh.s.cnt = 0x100 / 4;
265
}
266
/*
267
* SPI and XAUI can have lots of ports but the GMX hardware
268
* only ever has a max of 4.
269
*/
270
if (num_ports > 4)
271
num_ports = 4;
272
for (index = 0; index < num_ports; index++)
273
cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface),
274
gmx_tx_thresh.u64);
275
276
return 0;
277
}
278
279
/**
280
* Returns the IPD/PKO port number for a port on the given
281
* interface.
282
*
283
* @interface: Interface to use
284
* @port: Port on the interface
285
*
286
* Returns IPD/PKO port number
287
*/
288
int cvmx_helper_get_ipd_port(int interface, int port)
289
{
290
switch (interface) {
291
case 0:
292
return port;
293
case 1:
294
return port + 16;
295
case 2:
296
return port + 32;
297
case 3:
298
return port + 36;
299
case 4:
300
return port + 40;
301
case 5:
302
return port + 44;
303
}
304
return -1;
305
}
306
EXPORT_SYMBOL_GPL(cvmx_helper_get_ipd_port);
307
308
/**
309
* Returns the interface number for an IPD/PKO port number.
310
*
311
* @ipd_port: IPD/PKO port number
312
*
313
* Returns Interface number
314
*/
315
int cvmx_helper_get_interface_num(int ipd_port)
316
{
317
if (ipd_port < 16)
318
return 0;
319
else if (ipd_port < 32)
320
return 1;
321
else if (ipd_port < 36)
322
return 2;
323
else if (ipd_port < 40)
324
return 3;
325
else if (ipd_port < 44)
326
return 4;
327
else if (ipd_port < 48)
328
return 5;
329
else
330
cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD "
331
"port number\n");
332
333
return -1;
334
}
335
EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_num);
336
337
/**
338
* Returns the interface index number for an IPD/PKO port
339
* number.
340
*
341
* @ipd_port: IPD/PKO port number
342
*
343
* Returns Interface index number
344
*/
345
int cvmx_helper_get_interface_index_num(int ipd_port)
346
{
347
if (ipd_port < 32)
348
return ipd_port & 15;
349
else if (ipd_port < 36)
350
return ipd_port & 3;
351
else if (ipd_port < 40)
352
return ipd_port & 3;
353
else if (ipd_port < 44)
354
return ipd_port & 3;
355
else if (ipd_port < 48)
356
return ipd_port & 3;
357
else
358
cvmx_dprintf("cvmx_helper_get_interface_index_num: "
359
"Illegal IPD port number\n");
360
361
return -1;
362
}
363
EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_index_num);
364
365