diff options
Diffstat (limited to 'arch/mips/mach-octeon/include/mach/cvmx-pko.h')
-rw-r--r-- | arch/mips/mach-octeon/include/mach/cvmx-pko.h | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/arch/mips/mach-octeon/include/mach/cvmx-pko.h b/arch/mips/mach-octeon/include/mach/cvmx-pko.h new file mode 100644 index 00000000000..26e7a9adf4b --- /dev/null +++ b/arch/mips/mach-octeon/include/mach/cvmx-pko.h @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018-2022 Marvell International Ltd. + * + * Backward compatibility for packet transmission using legacy PKO command. + */ + +#ifndef __CVMX_PKO_H__ +#define __CVMX_PKO_H__ + +extern cvmx_pko_return_value_t +cvmx_pko3_legacy_xmit(unsigned int dq, cvmx_pko_command_word0_t pko_command, + cvmx_buf_ptr_t packet, uint64_t addr, bool tag_sw); + +/** + * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly + * once before this, and the same parameters must be passed to both + * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish(). + * + * WARNING: This function may have to look up the proper PKO port in + * the IPD port to PKO port map, and is thus slower than calling + * cvmx_pko_send_packet_finish_pkoid() directly if the PKO port + * identifier is known. + * + * @param ipd_port The IPD port corresponding the to pko port the packet is for + * @param queue Queue to use + * @param pko_command + * PKO HW command word + * @param packet to send + * @param use_locking + * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, + * or CVMX_PKO_LOCK_CMD_QUEUE + * + * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output + */ +static inline cvmx_pko_return_value_t +cvmx_pko_send_packet_finish(u64 ipd_port, uint64_t queue, + cvmx_pko_command_word0_t pko_command, + cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking) +{ + cvmx_cmd_queue_result_t result; + + if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { + return cvmx_pko3_legacy_xmit(queue, pko_command, packet, 0, + use_locking == + CVMX_PKO_LOCK_ATOMIC_TAG); + } + + if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) + cvmx_pow_tag_sw_wait(); + + result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), + (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), + pko_command.u64, packet.u64); + if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) { + cvmx_pko_doorbell(ipd_port, queue, 2); + return CVMX_PKO_SUCCESS; + } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || + (result == CVMX_CMD_QUEUE_FULL)) { + return CVMX_PKO_NO_MEMORY; + } else { + return CVMX_PKO_INVALID_QUEUE; + } +} + +/** + * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly + * once before this, and the same parameters must be passed to both + * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish(). + * + * WARNING: This function may have to look up the proper PKO port in + * the IPD port to PKO port map, and is thus slower than calling + * cvmx_pko_send_packet_finish3_pkoid() directly if the PKO port + * identifier is known. + * + * @param ipd_port The IPD port corresponding the to pko port the packet is for + * @param queue Queue to use + * @param pko_command + * PKO HW command word + * @param packet to send + * @param addr Physical address of a work queue entry or physical address to zero + * on complete. + * @param use_locking + * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, + * or CVMX_PKO_LOCK_CMD_QUEUE + * + * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output + */ +static inline cvmx_pko_return_value_t +cvmx_pko_send_packet_finish3(u64 ipd_port, uint64_t queue, + cvmx_pko_command_word0_t pko_command, + cvmx_buf_ptr_t packet, uint64_t addr, + cvmx_pko_lock_t use_locking) +{ + cvmx_cmd_queue_result_t result; + + if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { + return cvmx_pko3_legacy_xmit(queue, pko_command, packet, addr, + use_locking == + CVMX_PKO_LOCK_ATOMIC_TAG); + } + + if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) + cvmx_pow_tag_sw_wait(); + + result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), + (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), + pko_command.u64, packet.u64, addr); + if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) { + cvmx_pko_doorbell(ipd_port, queue, 3); + return CVMX_PKO_SUCCESS; + } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || + (result == CVMX_CMD_QUEUE_FULL)) { + return CVMX_PKO_NO_MEMORY; + } else { + return CVMX_PKO_INVALID_QUEUE; + } +} + +/** + * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly + * once before this, and the same parameters must be passed to both + * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish_pkoid(). + * + * @param pko_port Port to send it on + * @param queue Queue to use + * @param pko_command + * PKO HW command word + * @param packet to send + * @param use_locking + * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, + * or CVMX_PKO_LOCK_CMD_QUEUE + * + * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output + */ +static inline cvmx_pko_return_value_t +cvmx_pko_send_packet_finish_pkoid(int pko_port, uint64_t queue, + cvmx_pko_command_word0_t pko_command, + cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking) +{ + cvmx_cmd_queue_result_t result; + + if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { + return cvmx_pko3_legacy_xmit(queue, pko_command, packet, 0, + use_locking == + CVMX_PKO_LOCK_ATOMIC_TAG); + } + + if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) + cvmx_pow_tag_sw_wait(); + result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), + (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), + pko_command.u64, packet.u64); + if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) { + cvmx_pko_doorbell_pkoid(pko_port, queue, 2); + return CVMX_PKO_SUCCESS; + } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || + (result == CVMX_CMD_QUEUE_FULL)) { + return CVMX_PKO_NO_MEMORY; + } else { + return CVMX_PKO_INVALID_QUEUE; + } +} + +/** + * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly + * once before this, and the same parameters must be passed to both + * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish_pkoid(). + * + * @param pko_port The PKO port the packet is for + * @param queue Queue to use + * @param pko_command + * PKO HW command word + * @param packet to send + * @param addr Plysical address of a work queue entry or physical address to zero + * on complete. + * @param use_locking + * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, + * or CVMX_PKO_LOCK_CMD_QUEUE + * + * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output + */ +static inline cvmx_pko_return_value_t +cvmx_pko_send_packet_finish3_pkoid(u64 pko_port, uint64_t queue, + cvmx_pko_command_word0_t pko_command, + cvmx_buf_ptr_t packet, uint64_t addr, + cvmx_pko_lock_t use_locking) +{ + cvmx_cmd_queue_result_t result; + + if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { + return cvmx_pko3_legacy_xmit(queue, pko_command, packet, addr, + use_locking == + CVMX_PKO_LOCK_ATOMIC_TAG); + } + + if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) + cvmx_pow_tag_sw_wait(); + result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), + (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), + pko_command.u64, packet.u64, addr); + if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) { + cvmx_pko_doorbell_pkoid(pko_port, queue, 3); + return CVMX_PKO_SUCCESS; + } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || + (result == CVMX_CMD_QUEUE_FULL)) { + return CVMX_PKO_NO_MEMORY; + } else { + return CVMX_PKO_INVALID_QUEUE; + } +} + +#endif /* __CVMX_PKO_H__ */ |