]>
Commit | Line | Data |
---|---|---|
80ff0fd3 DD |
1 | /***********************license start*************** |
2 | * Author: Cavium Networks | |
3 | * | |
4 | * Contact: support@caviumnetworks.com | |
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 | * | |
30 | * Interface to the hardware Packet Output unit. | |
31 | * | |
32 | * Starting with SDK 1.7.0, the PKO output functions now support | |
33 | * two types of locking. CVMX_PKO_LOCK_ATOMIC_TAG continues to | |
34 | * function similarly to previous SDKs by using POW atomic tags | |
35 | * to preserve ordering and exclusivity. As a new option, you | |
36 | * can now pass CVMX_PKO_LOCK_CMD_QUEUE which uses a ll/sc | |
37 | * memory based locking instead. This locking has the advantage | |
38 | * of not affecting the tag state but doesn't preserve packet | |
39 | * ordering. CVMX_PKO_LOCK_CMD_QUEUE is appropriate in most | |
40 | * generic code while CVMX_PKO_LOCK_CMD_QUEUE should be used | |
41 | * with hand tuned fast path code. | |
42 | * | |
43 | * Some of other SDK differences visible to the command command | |
44 | * queuing: | |
45 | * - PKO indexes are no longer stored in the FAU. A large | |
46 | * percentage of the FAU register block used to be tied up | |
47 | * maintaining PKO queue pointers. These are now stored in a | |
48 | * global named block. | |
49 | * - The PKO <b>use_locking</b> parameter can now have a global | |
50 | * effect. Since all application use the same named block, | |
51 | * queue locking correctly applies across all operating | |
52 | * systems when using CVMX_PKO_LOCK_CMD_QUEUE. | |
53 | * - PKO 3 word commands are now supported. Use | |
54 | * cvmx_pko_send_packet_finish3(). | |
55 | * | |
56 | */ | |
57 | ||
58 | #ifndef __CVMX_PKO_H__ | |
59 | #define __CVMX_PKO_H__ | |
60 | ||
61 | #include "cvmx-fpa.h" | |
62 | #include "cvmx-pow.h" | |
63 | #include "cvmx-cmd-queue.h" | |
64 | #include "cvmx-pko-defs.h" | |
65 | ||
66 | /* Adjust the command buffer size by 1 word so that in the case of using only | |
67 | * two word PKO commands no command words stradle buffers. The useful values | |
68 | * for this are 0 and 1. */ | |
69 | #define CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST (1) | |
70 | ||
71 | #define CVMX_PKO_MAX_OUTPUT_QUEUES_STATIC 256 | |
72 | #define CVMX_PKO_MAX_OUTPUT_QUEUES ((OCTEON_IS_MODEL(OCTEON_CN31XX) || \ | |
73 | OCTEON_IS_MODEL(OCTEON_CN3010) || OCTEON_IS_MODEL(OCTEON_CN3005) || \ | |
74 | OCTEON_IS_MODEL(OCTEON_CN50XX)) ? 32 : \ | |
75 | (OCTEON_IS_MODEL(OCTEON_CN58XX) || \ | |
76 | OCTEON_IS_MODEL(OCTEON_CN56XX)) ? 256 : 128) | |
77 | #define CVMX_PKO_NUM_OUTPUT_PORTS 40 | |
78 | /* use this for queues that are not used */ | |
79 | #define CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID 63 | |
80 | #define CVMX_PKO_QUEUE_STATIC_PRIORITY 9 | |
81 | #define CVMX_PKO_ILLEGAL_QUEUE 0xFFFF | |
82 | #define CVMX_PKO_MAX_QUEUE_DEPTH 0 | |
83 | ||
84 | typedef enum { | |
85 | CVMX_PKO_SUCCESS, | |
86 | CVMX_PKO_INVALID_PORT, | |
87 | CVMX_PKO_INVALID_QUEUE, | |
88 | CVMX_PKO_INVALID_PRIORITY, | |
89 | CVMX_PKO_NO_MEMORY, | |
90 | CVMX_PKO_PORT_ALREADY_SETUP, | |
91 | CVMX_PKO_CMD_QUEUE_INIT_ERROR | |
92 | } cvmx_pko_status_t; | |
93 | ||
94 | /** | |
95 | * This enumeration represents the differnet locking modes supported by PKO. | |
96 | */ | |
97 | typedef enum { | |
98 | /* | |
99 | * PKO doesn't do any locking. It is the responsibility of the | |
100 | * application to make sure that no other core is accessing | |
101 | * the same queue at the smae time | |
102 | */ | |
103 | CVMX_PKO_LOCK_NONE = 0, | |
104 | /* | |
105 | * PKO performs an atomic tagswitch to insure exclusive access | |
106 | * to the output queue. This will maintain packet ordering on | |
107 | * output. | |
108 | */ | |
109 | CVMX_PKO_LOCK_ATOMIC_TAG = 1, | |
110 | /* | |
111 | * PKO uses the common command queue locks to insure exclusive | |
112 | * access to the output queue. This is a memory based | |
113 | * ll/sc. This is the most portable locking mechanism. | |
114 | */ | |
115 | CVMX_PKO_LOCK_CMD_QUEUE = 2, | |
116 | } cvmx_pko_lock_t; | |
117 | ||
118 | typedef struct { | |
119 | uint32_t packets; | |
120 | uint64_t octets; | |
121 | uint64_t doorbell; | |
122 | } cvmx_pko_port_status_t; | |
123 | ||
124 | /** | |
125 | * This structure defines the address to use on a packet enqueue | |
126 | */ | |
127 | typedef union { | |
128 | uint64_t u64; | |
129 | struct { | |
130 | /* Must CVMX_IO_SEG */ | |
131 | uint64_t mem_space:2; | |
132 | /* Must be zero */ | |
133 | uint64_t reserved:13; | |
134 | /* Must be one */ | |
135 | uint64_t is_io:1; | |
136 | /* The ID of the device on the non-coherent bus */ | |
137 | uint64_t did:8; | |
138 | /* Must be zero */ | |
139 | uint64_t reserved2:4; | |
140 | /* Must be zero */ | |
141 | uint64_t reserved3:18; | |
142 | /* | |
143 | * The hardware likes to have the output port in | |
144 | * addition to the output queue, | |
145 | */ | |
146 | uint64_t port:6; | |
147 | /* | |
148 | * The output queue to send the packet to (0-127 are | |
149 | * legal) | |
150 | */ | |
151 | uint64_t queue:9; | |
152 | /* Must be zero */ | |
153 | uint64_t reserved4:3; | |
154 | } s; | |
155 | } cvmx_pko_doorbell_address_t; | |
156 | ||
157 | /** | |
158 | * Structure of the first packet output command word. | |
159 | */ | |
160 | typedef union { | |
161 | uint64_t u64; | |
162 | struct { | |
163 | /* | |
164 | * The size of the reg1 operation - could be 8, 16, | |
165 | * 32, or 64 bits. | |
166 | */ | |
167 | uint64_t size1:2; | |
168 | /* | |
169 | * The size of the reg0 operation - could be 8, 16, | |
170 | * 32, or 64 bits. | |
171 | */ | |
172 | uint64_t size0:2; | |
173 | /* | |
174 | * If set, subtract 1, if clear, subtract packet | |
175 | * size. | |
176 | */ | |
177 | uint64_t subone1:1; | |
178 | /* | |
179 | * The register, subtract will be done if reg1 is | |
180 | * non-zero. | |
181 | */ | |
182 | uint64_t reg1:11; | |
183 | /* If set, subtract 1, if clear, subtract packet size */ | |
184 | uint64_t subone0:1; | |
185 | /* The register, subtract will be done if reg0 is non-zero */ | |
186 | uint64_t reg0:11; | |
187 | /* | |
188 | * When set, interpret segment pointer and segment | |
189 | * bytes in little endian order. | |
190 | */ | |
191 | uint64_t le:1; | |
192 | /* | |
193 | * When set, packet data not allocated in L2 cache by | |
194 | * PKO. | |
195 | */ | |
196 | uint64_t n2:1; | |
197 | /* | |
198 | * If set and rsp is set, word3 contains a pointer to | |
199 | * a work queue entry. | |
200 | */ | |
201 | uint64_t wqp:1; | |
202 | /* If set, the hardware will send a response when done */ | |
203 | uint64_t rsp:1; | |
204 | /* | |
205 | * If set, the supplied pkt_ptr is really a pointer to | |
206 | * a list of pkt_ptr's. | |
207 | */ | |
208 | uint64_t gather:1; | |
209 | /* | |
210 | * If ipoffp1 is non zero, (ipoffp1-1) is the number | |
211 | * of bytes to IP header, and the hardware will | |
212 | * calculate and insert the UDP/TCP checksum. | |
213 | */ | |
214 | uint64_t ipoffp1:7; | |
215 | /* | |
216 | * If set, ignore the I bit (force to zero) from all | |
217 | * pointer structures. | |
218 | */ | |
219 | uint64_t ignore_i:1; | |
220 | /* | |
221 | * If clear, the hardware will attempt to free the | |
222 | * buffers containing the packet. | |
223 | */ | |
224 | uint64_t dontfree:1; | |
225 | /* | |
226 | * The total number of segs in the packet, if gather | |
227 | * set, also gather list length. | |
228 | */ | |
229 | uint64_t segs:6; | |
230 | /* Including L2, but no trailing CRC */ | |
231 | uint64_t total_bytes:16; | |
232 | } s; | |
233 | } cvmx_pko_command_word0_t; | |
234 | ||
235 | /* CSR typedefs have been moved to cvmx-csr-*.h */ | |
236 | ||
237 | /** | |
238 | * Definition of internal state for Packet output processing | |
239 | */ | |
240 | typedef struct { | |
241 | /* ptr to start of buffer, offset kept in FAU reg */ | |
242 | uint64_t *start_ptr; | |
243 | } cvmx_pko_state_elem_t; | |
244 | ||
245 | /** | |
246 | * Call before any other calls to initialize the packet | |
247 | * output system. | |
248 | */ | |
249 | extern void cvmx_pko_initialize_global(void); | |
250 | extern int cvmx_pko_initialize_local(void); | |
251 | ||
252 | /** | |
253 | * Enables the packet output hardware. It must already be | |
254 | * configured. | |
255 | */ | |
256 | extern void cvmx_pko_enable(void); | |
257 | ||
258 | /** | |
259 | * Disables the packet output. Does not affect any configuration. | |
260 | */ | |
261 | extern void cvmx_pko_disable(void); | |
262 | ||
263 | /** | |
264 | * Shutdown and free resources required by packet output. | |
265 | */ | |
266 | ||
267 | extern void cvmx_pko_shutdown(void); | |
268 | ||
269 | /** | |
270 | * Configure a output port and the associated queues for use. | |
271 | * | |
272 | * @port: Port to configure. | |
273 | * @base_queue: First queue number to associate with this port. | |
274 | * @num_queues: Number of queues t oassociate with this port | |
275 | * @priority: Array of priority levels for each queue. Values are | |
276 | * allowed to be 1-8. A value of 8 get 8 times the traffic | |
277 | * of a value of 1. There must be num_queues elements in the | |
278 | * array. | |
279 | */ | |
280 | extern cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, | |
281 | uint64_t base_queue, | |
282 | uint64_t num_queues, | |
283 | const uint64_t priority[]); | |
284 | ||
285 | /** | |
286 | * Ring the packet output doorbell. This tells the packet | |
287 | * output hardware that "len" command words have been added | |
288 | * to its pending list. This command includes the required | |
289 | * CVMX_SYNCWS before the doorbell ring. | |
290 | * | |
291 | * @port: Port the packet is for | |
292 | * @queue: Queue the packet is for | |
293 | * @len: Length of the command in 64 bit words | |
294 | */ | |
295 | static inline void cvmx_pko_doorbell(uint64_t port, uint64_t queue, | |
296 | uint64_t len) | |
297 | { | |
298 | cvmx_pko_doorbell_address_t ptr; | |
299 | ||
300 | ptr.u64 = 0; | |
301 | ptr.s.mem_space = CVMX_IO_SEG; | |
302 | ptr.s.did = CVMX_OCT_DID_PKT_SEND; | |
303 | ptr.s.is_io = 1; | |
304 | ptr.s.port = port; | |
305 | ptr.s.queue = queue; | |
306 | /* | |
307 | * Need to make sure output queue data is in DRAM before | |
308 | * doorbell write. | |
309 | */ | |
310 | CVMX_SYNCWS; | |
311 | cvmx_write_io(ptr.u64, len); | |
312 | } | |
313 | ||
314 | /** | |
315 | * Prepare to send a packet. This may initiate a tag switch to | |
316 | * get exclusive access to the output queue structure, and | |
317 | * performs other prep work for the packet send operation. | |
318 | * | |
319 | * cvmx_pko_send_packet_finish() MUST be called after this function is called, | |
320 | * and must be called with the same port/queue/use_locking arguments. | |
321 | * | |
322 | * The use_locking parameter allows the caller to use three | |
323 | * possible locking modes. | |
324 | * - CVMX_PKO_LOCK_NONE | |
325 | * - PKO doesn't do any locking. It is the responsibility | |
326 | * of the application to make sure that no other core | |
327 | * is accessing the same queue at the smae time. | |
328 | * - CVMX_PKO_LOCK_ATOMIC_TAG | |
329 | * - PKO performs an atomic tagswitch to insure exclusive | |
330 | * access to the output queue. This will maintain | |
331 | * packet ordering on output. | |
332 | * - CVMX_PKO_LOCK_CMD_QUEUE | |
333 | * - PKO uses the common command queue locks to insure | |
334 | * exclusive access to the output queue. This is a | |
335 | * memory based ll/sc. This is the most portable | |
336 | * locking mechanism. | |
337 | * | |
338 | * NOTE: If atomic locking is used, the POW entry CANNOT be | |
339 | * descheduled, as it does not contain a valid WQE pointer. | |
340 | * | |
341 | * @port: Port to send it on | |
342 | * @queue: Queue to use | |
343 | * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or | |
344 | * CVMX_PKO_LOCK_CMD_QUEUE | |
345 | */ | |
346 | ||
347 | static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, | |
348 | cvmx_pko_lock_t use_locking) | |
349 | { | |
350 | if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) { | |
351 | /* | |
352 | * Must do a full switch here to handle all cases. We | |
353 | * use a fake WQE pointer, as the POW does not access | |
354 | * this memory. The WQE pointer and group are only | |
355 | * used if this work is descheduled, which is not | |
356 | * supported by the | |
357 | * cvmx_pko_send_packet_prepare/cvmx_pko_send_packet_finish | |
358 | * combination. Note that this is a special case in | |
359 | * which these fake values can be used - this is not a | |
360 | * general technique. | |
361 | */ | |
362 | uint32_t tag = | |
363 | CVMX_TAG_SW_BITS_INTERNAL << CVMX_TAG_SW_SHIFT | | |
364 | CVMX_TAG_SUBGROUP_PKO << CVMX_TAG_SUBGROUP_SHIFT | | |
365 | (CVMX_TAG_SUBGROUP_MASK & queue); | |
366 | cvmx_pow_tag_sw_full((cvmx_wqe_t *) cvmx_phys_to_ptr(0x80), tag, | |
367 | CVMX_POW_TAG_TYPE_ATOMIC, 0); | |
368 | } | |
369 | } | |
370 | ||
371 | /** | |
372 | * Complete packet output. cvmx_pko_send_packet_prepare() must be | |
373 | * called exactly once before this, and the same parameters must be | |
374 | * passed to both cvmx_pko_send_packet_prepare() and | |
375 | * cvmx_pko_send_packet_finish(). | |
376 | * | |
377 | * @port: Port to send it on | |
378 | * @queue: Queue to use | |
379 | * @pko_command: | |
380 | * PKO HW command word | |
381 | * @packet: Packet to send | |
382 | * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or | |
383 | * CVMX_PKO_LOCK_CMD_QUEUE | |
384 | * | |
385 | * Returns returns CVMX_PKO_SUCCESS on success, or error code on | |
386 | * failure of output | |
387 | */ | |
388 | static inline cvmx_pko_status_t cvmx_pko_send_packet_finish( | |
389 | uint64_t port, | |
390 | uint64_t queue, | |
391 | cvmx_pko_command_word0_t pko_command, | |
392 | union cvmx_buf_ptr packet, | |
393 | cvmx_pko_lock_t use_locking) | |
394 | { | |
395 | cvmx_cmd_queue_result_t result; | |
396 | if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) | |
397 | cvmx_pow_tag_sw_wait(); | |
398 | result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), | |
399 | (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), | |
400 | pko_command.u64, packet.u64); | |
401 | if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { | |
402 | cvmx_pko_doorbell(port, queue, 2); | |
403 | return CVMX_PKO_SUCCESS; | |
404 | } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) | |
405 | || (result == CVMX_CMD_QUEUE_FULL)) { | |
406 | return CVMX_PKO_NO_MEMORY; | |
407 | } else { | |
408 | return CVMX_PKO_INVALID_QUEUE; | |
409 | } | |
410 | } | |
411 | ||
412 | /** | |
413 | * Complete packet output. cvmx_pko_send_packet_prepare() must be | |
414 | * called exactly once before this, and the same parameters must be | |
415 | * passed to both cvmx_pko_send_packet_prepare() and | |
416 | * cvmx_pko_send_packet_finish(). | |
417 | * | |
418 | * @port: Port to send it on | |
419 | * @queue: Queue to use | |
420 | * @pko_command: | |
421 | * PKO HW command word | |
422 | * @packet: Packet to send | |
423 | * @addr: Plysical address of a work queue entry or physical address | |
424 | * to zero on complete. | |
425 | * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or | |
426 | * CVMX_PKO_LOCK_CMD_QUEUE | |
427 | * | |
428 | * Returns returns CVMX_PKO_SUCCESS on success, or error code on | |
429 | * failure of output | |
430 | */ | |
431 | static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3( | |
432 | uint64_t port, | |
433 | uint64_t queue, | |
434 | cvmx_pko_command_word0_t pko_command, | |
435 | union cvmx_buf_ptr packet, | |
436 | uint64_t addr, | |
437 | cvmx_pko_lock_t use_locking) | |
438 | { | |
439 | cvmx_cmd_queue_result_t result; | |
440 | if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) | |
441 | cvmx_pow_tag_sw_wait(); | |
442 | result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), | |
443 | (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), | |
444 | pko_command.u64, packet.u64, addr); | |
445 | if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { | |
446 | cvmx_pko_doorbell(port, queue, 3); | |
447 | return CVMX_PKO_SUCCESS; | |
448 | } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) | |
449 | || (result == CVMX_CMD_QUEUE_FULL)) { | |
450 | return CVMX_PKO_NO_MEMORY; | |
451 | } else { | |
452 | return CVMX_PKO_INVALID_QUEUE; | |
453 | } | |
454 | } | |
455 | ||
456 | /** | |
457 | * Return the pko output queue associated with a port and a specific core. | |
458 | * In normal mode (PKO lockless operation is disabled), the value returned | |
459 | * is the base queue. | |
460 | * | |
461 | * @port: Port number | |
462 | * @core: Core to get queue for | |
463 | * | |
464 | * Returns Core-specific output queue | |
465 | */ | |
466 | static inline int cvmx_pko_get_base_queue_per_core(int port, int core) | |
467 | { | |
468 | #ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 | |
469 | #define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 16 | |
470 | #endif | |
471 | #ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 | |
472 | #define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 16 | |
473 | #endif | |
474 | ||
475 | if (port < CVMX_PKO_MAX_PORTS_INTERFACE0) | |
476 | return port * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + core; | |
477 | else if (port >= 16 && port < 16 + CVMX_PKO_MAX_PORTS_INTERFACE1) | |
478 | return CVMX_PKO_MAX_PORTS_INTERFACE0 * | |
479 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + (port - | |
480 | 16) * | |
481 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + core; | |
482 | else if ((port >= 32) && (port < 36)) | |
483 | return CVMX_PKO_MAX_PORTS_INTERFACE0 * | |
484 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + | |
485 | CVMX_PKO_MAX_PORTS_INTERFACE1 * | |
486 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + (port - | |
487 | 32) * | |
488 | CVMX_PKO_QUEUES_PER_PORT_PCI; | |
489 | else if ((port >= 36) && (port < 40)) | |
490 | return CVMX_PKO_MAX_PORTS_INTERFACE0 * | |
491 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + | |
492 | CVMX_PKO_MAX_PORTS_INTERFACE1 * | |
493 | CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + | |
494 | 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + (port - | |
495 | 36) * | |
496 | CVMX_PKO_QUEUES_PER_PORT_LOOP; | |
497 | else | |
498 | /* Given the limit on the number of ports we can map to | |
499 | * CVMX_MAX_OUTPUT_QUEUES_STATIC queues (currently 256, | |
500 | * divided among all cores), the remaining unmapped ports | |
501 | * are assigned an illegal queue number */ | |
502 | return CVMX_PKO_ILLEGAL_QUEUE; | |
503 | } | |
504 | ||
505 | /** | |
506 | * For a given port number, return the base pko output queue | |
507 | * for the port. | |
508 | * | |
509 | * @port: Port number | |
510 | * Returns Base output queue | |
511 | */ | |
512 | static inline int cvmx_pko_get_base_queue(int port) | |
513 | { | |
514 | return cvmx_pko_get_base_queue_per_core(port, 0); | |
515 | } | |
516 | ||
517 | /** | |
518 | * For a given port number, return the number of pko output queues. | |
519 | * | |
520 | * @port: Port number | |
521 | * Returns Number of output queues | |
522 | */ | |
523 | static inline int cvmx_pko_get_num_queues(int port) | |
524 | { | |
525 | if (port < 16) | |
526 | return CVMX_PKO_QUEUES_PER_PORT_INTERFACE0; | |
527 | else if (port < 32) | |
528 | return CVMX_PKO_QUEUES_PER_PORT_INTERFACE1; | |
529 | else if (port < 36) | |
530 | return CVMX_PKO_QUEUES_PER_PORT_PCI; | |
531 | else if (port < 40) | |
532 | return CVMX_PKO_QUEUES_PER_PORT_LOOP; | |
533 | else | |
534 | return 0; | |
535 | } | |
536 | ||
537 | /** | |
538 | * Get the status counters for a port. | |
539 | * | |
540 | * @port_num: Port number to get statistics for. | |
541 | * @clear: Set to 1 to clear the counters after they are read | |
542 | * @status: Where to put the results. | |
543 | */ | |
544 | static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, | |
545 | cvmx_pko_port_status_t *status) | |
546 | { | |
547 | union cvmx_pko_reg_read_idx pko_reg_read_idx; | |
548 | union cvmx_pko_mem_count0 pko_mem_count0; | |
549 | union cvmx_pko_mem_count1 pko_mem_count1; | |
550 | ||
551 | pko_reg_read_idx.u64 = 0; | |
552 | pko_reg_read_idx.s.index = port_num; | |
553 | cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); | |
554 | ||
555 | pko_mem_count0.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT0); | |
556 | status->packets = pko_mem_count0.s.count; | |
557 | if (clear) { | |
558 | pko_mem_count0.s.count = port_num; | |
559 | cvmx_write_csr(CVMX_PKO_MEM_COUNT0, pko_mem_count0.u64); | |
560 | } | |
561 | ||
562 | pko_mem_count1.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT1); | |
563 | status->octets = pko_mem_count1.s.count; | |
564 | if (clear) { | |
565 | pko_mem_count1.s.count = port_num; | |
566 | cvmx_write_csr(CVMX_PKO_MEM_COUNT1, pko_mem_count1.u64); | |
567 | } | |
568 | ||
569 | if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { | |
570 | union cvmx_pko_mem_debug9 debug9; | |
571 | pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); | |
572 | cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); | |
573 | debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); | |
574 | status->doorbell = debug9.cn38xx.doorbell; | |
575 | } else { | |
576 | union cvmx_pko_mem_debug8 debug8; | |
577 | pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); | |
578 | cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); | |
579 | debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); | |
580 | status->doorbell = debug8.cn58xx.doorbell; | |
581 | } | |
582 | } | |
583 | ||
584 | /** | |
585 | * Rate limit a PKO port to a max packets/sec. This function is only | |
586 | * supported on CN57XX, CN56XX, CN55XX, and CN54XX. | |
587 | * | |
588 | * @port: Port to rate limit | |
589 | * @packets_s: Maximum packet/sec | |
590 | * @burst: Maximum number of packets to burst in a row before rate | |
591 | * limiting cuts in. | |
592 | * | |
593 | * Returns Zero on success, negative on failure | |
594 | */ | |
595 | extern int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst); | |
596 | ||
597 | /** | |
598 | * Rate limit a PKO port to a max bits/sec. This function is only | |
599 | * supported on CN57XX, CN56XX, CN55XX, and CN54XX. | |
600 | * | |
601 | * @port: Port to rate limit | |
602 | * @bits_s: PKO rate limit in bits/sec | |
603 | * @burst: Maximum number of bits to burst before rate | |
604 | * limiting cuts in. | |
605 | * | |
606 | * Returns Zero on success, negative on failure | |
607 | */ | |
608 | extern int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst); | |
609 | ||
610 | #endif /* __CVMX_PKO_H__ */ |