summaryrefslogtreecommitdiff
path: root/arch/mips/mach-octeon/include/mach/cvmx-helper-util.h
blob: ffdd8d03e0d4550ad334b8ed50cfe0bc7ac7a1c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020 Marvell International Ltd.
 */

#ifndef __CVMX_HELPER_UTIL_H__
#define __CVMX_HELPER_UTIL_H__

#include "cvmx-mio-defs.h"
#include "cvmx-helper.h"
#include "cvmx-fpa.h"

typedef char cvmx_pknd_t;
typedef char cvmx_bpid_t;

#define CVMX_INVALID_PKND ((cvmx_pknd_t)-1)
#define CVMX_INVALID_BPID ((cvmx_bpid_t)-1)
#define CVMX_MAX_PKND	  ((cvmx_pknd_t)64)
#define CVMX_MAX_BPID	  ((cvmx_bpid_t)64)

#define CVMX_HELPER_MAX_IFACE 11
#define CVMX_HELPER_MAX_PORTS 16

/* Maximum range for normalized (a.k.a. IPD) port numbers (12-bit field) */
#define CVMX_PKO3_IPD_NUM_MAX 0x1000 //FIXME- take it from someplace else ?
#define CVMX_PKO3_DQ_NUM_MAX  0x400  // 78xx has 1024 queues

#define CVMX_PKO3_IPD_PORT_NULL (CVMX_PKO3_IPD_NUM_MAX - 1)
#define CVMX_PKO3_IPD_PORT_LOOP 0

struct cvmx_xport {
	int node;
	int port;
};

typedef struct cvmx_xport cvmx_xport_t;

static inline struct cvmx_xport cvmx_helper_ipd_port_to_xport(int ipd_port)
{
	struct cvmx_xport r;

	r.port = ipd_port & (CVMX_PKO3_IPD_NUM_MAX - 1);
	r.node = (ipd_port >> 12) & CVMX_NODE_MASK;
	return r;
}

static inline int cvmx_helper_node_to_ipd_port(int node, int index)
{
	return (node << 12) + index;
}

struct cvmx_xdq {
	int node;
	int queue;
};

typedef struct cvmx_xdq cvmx_xdq_t;

static inline struct cvmx_xdq cvmx_helper_queue_to_xdq(int queue)
{
	struct cvmx_xdq r;

	r.queue = queue & (CVMX_PKO3_DQ_NUM_MAX - 1);
	r.node = (queue >> 10) & CVMX_NODE_MASK;
	return r;
}

static inline int cvmx_helper_node_to_dq(int node, int queue)
{
	return (node << 10) + queue;
}

struct cvmx_xiface {
	int node;
	int interface;
};

typedef struct cvmx_xiface cvmx_xiface_t;

/**
 * Return node and interface number from XIFACE.
 *
 * @param xiface interface with node information
 *
 * Return: struct that contains node and interface number.
 */
static inline struct cvmx_xiface cvmx_helper_xiface_to_node_interface(int xiface)
{
	cvmx_xiface_t interface_node;

	/*
	 * If the majic number 0xde0000 is not present in the
	 * interface, then assume it is node 0.
	 */

	if (((xiface >> 0x8) & 0xff) == 0xde) {
		interface_node.node = (xiface >> 16) & CVMX_NODE_MASK;
		interface_node.interface = xiface & 0xff;
	} else {
		interface_node.node = cvmx_get_node_num();
		interface_node.interface = xiface & 0xff;
	}
	return interface_node;
}

/* Used internally only*/
static inline bool __cvmx_helper_xiface_is_null(int xiface)
{
	return (xiface & 0xff) == 0xff;
}

#define __CVMX_XIFACE_NULL 0xff

/**
 * Return interface with majic number and node information (XIFACE)
 *
 * @param node       node of the interface referred to
 * @param interface  interface to use.
 *
 * @return
 */
static inline int cvmx_helper_node_interface_to_xiface(int node, int interface)
{
	return ((node & CVMX_NODE_MASK) << 16) | (0xde << 8) | (interface & 0xff);
}

/**
 * Free the pip packet buffers contained in a work queue entry.
 * The work queue entry is not freed.
 *
 * @param work   Work queue entry with packet to free
 */
static inline void cvmx_helper_free_pip_pkt_data(cvmx_wqe_t *work)
{
	u64 number_buffers;
	cvmx_buf_ptr_t buffer_ptr;
	cvmx_buf_ptr_t next_buffer_ptr;
	u64 start_of_buffer;

	number_buffers = work->word2.s.bufs;
	if (number_buffers == 0)
		return;

	buffer_ptr = work->packet_ptr;

	/* Since the number of buffers is not zero, we know this is not a dynamic
	   short packet. We need to check if it is a packet received with
	   IPD_CTL_STATUS[NO_WPTR]. If this is true, we need to free all buffers
	   except for the first one. The caller doesn't expect their WQE pointer
	   to be freed */
	start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
	if (cvmx_ptr_to_phys(work) == start_of_buffer) {
		next_buffer_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
		buffer_ptr = next_buffer_ptr;
		number_buffers--;
	}

	while (number_buffers--) {
		/* Remember the back pointer is in cache lines, not 64bit words */
		start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
		/* Read pointer to next buffer before we free the current buffer. */
		next_buffer_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
		cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), buffer_ptr.s.pool, 0);
		buffer_ptr = next_buffer_ptr;
	}
}

/**
 * Free the pki packet buffers contained in a work queue entry.
 * If first packet buffer contains wqe, wqe gets freed too so do not access
 * wqe after calling this function.
 * This function asssumes that buffers to be freed are from
 * Naturally aligned pool/aura.
 * It does not use don't write back.
 * @param work   Work queue entry with packet to free
 */
static inline void cvmx_helper_free_pki_pkt_data(cvmx_wqe_t *work)
{
	u64 number_buffers;
	u64 start_of_buffer;
	cvmx_buf_ptr_pki_t next_buffer_ptr;
	cvmx_buf_ptr_pki_t buffer_ptr;
	cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;

	if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
		return;
	}
	/* Make sure errata pki-20776 has been applied*/
	cvmx_wqe_pki_errata_20776(work);
	buffer_ptr = wqe->packet_ptr;
	number_buffers = cvmx_wqe_get_bufs(work);

	while (number_buffers--) {
		/* FIXME: change WQE function prototype */
		unsigned int x = cvmx_wqe_get_aura(work);
		cvmx_fpa3_gaura_t aura = __cvmx_fpa3_gaura(x >> 10, x & 0x3ff);
		/* XXX- assumes the buffer is cache-line aligned and naturally aligned mode*/
		start_of_buffer = (buffer_ptr.addr >> 7) << 7;
		/* Read pointer to next buffer before we free the current buffer. */
		next_buffer_ptr = *(cvmx_buf_ptr_pki_t *)cvmx_phys_to_ptr(buffer_ptr.addr - 8);
		/* FPA AURA comes from WQE, includes node */
		cvmx_fpa3_free(cvmx_phys_to_ptr(start_of_buffer), aura, 0);
		buffer_ptr = next_buffer_ptr;
	}
}

/**
 * Free the pki wqe entry buffer.
 * If wqe buffers contains first packet buffer, wqe does not get freed here.
 * This function asssumes that buffers to be freed are from
 * Naturally aligned pool/aura.
 * It does not use don't write back.
 * @param work   Work queue entry to free
 */
static inline void cvmx_wqe_pki_free(cvmx_wqe_t *work)
{
	cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
	unsigned int x;
	cvmx_fpa3_gaura_t aura;

	if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
		return;
	}
	/* Do nothing if the first packet buffer shares WQE buffer */
	if (!wqe->packet_ptr.packet_outside_wqe)
		return;

	/* FIXME change WQE function prototype */
	x = cvmx_wqe_get_aura(work);
	aura = __cvmx_fpa3_gaura(x >> 10, x & 0x3ff);

	cvmx_fpa3_free(work, aura, 0);
}

/**
 * Convert a interface mode into a human readable string
 *
 * @param mode   Mode to convert
 *
 * Return: String
 */
const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode);

/**
 * Debug routine to dump the packet structure to the console
 *
 * @param work   Work queue entry containing the packet to dump
 * @return
 */
int cvmx_helper_dump_packet(cvmx_wqe_t *work);

/**
 * Get the version of the CVMX libraries.
 *
 * Return: Version string. Note this buffer is allocated statically
 *         and will be shared by all callers.
 */
const char *cvmx_helper_get_version(void);

/**
 * @INTERNAL
 * Setup the common GMX settings that determine the number of
 * ports. These setting apply to almost all configurations of all
 * chips.
 *
 * @param xiface Interface to configure
 * @param num_ports Number of ports on the interface
 *
 * Return: Zero on success, negative on failure
 */
int __cvmx_helper_setup_gmx(int xiface, int num_ports);

/**
 * @INTERNAL
 * Get the number of pko_ports on an interface.
 *
 * @param interface
 *
 * Return: the number of pko_ports on the interface.
 */
int __cvmx_helper_get_num_pko_ports(int interface);

/**
 * Returns the IPD port number for a port on the given
 * interface.
 *
 * @param interface Interface to use
 * @param port      Port on the interface
 *
 * Return: IPD port number
 */
int cvmx_helper_get_ipd_port(int interface, int port);

/**
 * Returns the PKO port number for a port on the given interface,
 * This is the base pko_port for o68 and ipd_port for older models.
 *
 * @param interface Interface to use
 * @param port      Port on the interface
 *
 * Return: PKO port number and -1 on error.
 */
int cvmx_helper_get_pko_port(int interface, int port);

/**
 * Returns the IPD/PKO port number for the first port on the given
 * interface.
 *
 * @param interface Interface to use
 *
 * Return: IPD/PKO port number
 */
static inline int cvmx_helper_get_first_ipd_port(int interface)
{
	return cvmx_helper_get_ipd_port(interface, 0);
}

int cvmx_helper_ports_on_interface(int interface);

/**
 * Returns the IPD/PKO port number for the last port on the given
 * interface.
 *
 * @param interface Interface to use
 *
 * Return: IPD/PKO port number
 *
 * Note: for o68, the last ipd port on an interface does not always equal to
 * the first plus the number of ports as the ipd ports are not contiguous in
 * some cases, e.g., SGMII.
 *
 * Note: code that makes the assumption of contiguous ipd port numbers needs to
 * be aware of this.
 */
static inline int cvmx_helper_get_last_ipd_port(int interface)
{
	return cvmx_helper_get_ipd_port(interface, cvmx_helper_ports_on_interface(interface) - 1);
}

/**
 * Free the packet buffers contained in a work queue entry.
 * The work queue entry is not freed.
 * Note that this function will not free the work queue entry
 * even if it contains a non-redundant data packet, and hence
 * it is not really comparable to how the PKO would free a packet
 * buffers if requested.
 *
 * @param work   Work queue entry with packet to free
 */
void cvmx_helper_free_packet_data(cvmx_wqe_t *work);

/**
 * Returns the interface number for an IPD/PKO port number.
 *
 * @param ipd_port IPD/PKO port number
 *
 * Return: Interface number
 */
int cvmx_helper_get_interface_num(int ipd_port);

/**
 * Returns the interface index number for an IPD/PKO port
 * number.
 *
 * @param ipd_port IPD/PKO port number
 *
 * Return: Interface index number
 */
int cvmx_helper_get_interface_index_num(int ipd_port);

/**
 * Get port kind for a given port in an interface.
 *
 * @param xiface  Interface
 * @param index   index of the port in the interface
 *
 * Return: port kind on sucicess  and -1 on failure
 */
int cvmx_helper_get_pknd(int xiface, int index);

/**
 * Get bpid for a given port in an interface.
 *
 * @param interface  Interface
 * @param port       index of the port in the interface
 *
 * Return: port kind on sucicess  and -1 on failure
 */
int cvmx_helper_get_bpid(int interface, int port);

/**
 * Internal functions.
 */
int __cvmx_helper_post_init_interfaces(void);
int cvmx_helper_setup_red(int pass_thresh, int drop_thresh);
void cvmx_helper_show_stats(int port);

/*
 * Return number of array alements
 */
#define NUM_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))

/**
 * Prints out a buffer with the address, hex bytes, and ASCII
 *
 * @param	addr	Start address to print on the left
 * @param[in]	buffer	array of bytes to print
 * @param	count	Number of bytes to print
 */
void cvmx_print_buffer_u8(unsigned int addr, const u8 *buffer, size_t count);

#endif /* __CVMX_HELPER_H__ */