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