1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2018-2022 Marvell International Ltd.
4 *
5 * Backward compatibility for packet transmission using legacy PKO command.
6 */
7
8#ifndef __CVMX_PKO_H__
9#define __CVMX_PKO_H__
10
11extern cvmx_pko_return_value_t
12cvmx_pko3_legacy_xmit(unsigned int dq, cvmx_pko_command_word0_t pko_command,
13		      cvmx_buf_ptr_t packet, uint64_t addr, bool tag_sw);
14
15/**
16 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly
17 * once before this, and the same parameters must be passed to both
18 * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish().
19 *
20 * WARNING: This function may have to look up the proper PKO port in
21 * the IPD port to PKO port map, and is thus slower than calling
22 * cvmx_pko_send_packet_finish_pkoid() directly if the PKO port
23 * identifier is known.
24 *
25 * @param ipd_port   The IPD port corresponding the to pko port the packet is for
26 * @param queue  Queue to use
27 * @param pko_command
28 *               PKO HW command word
29 * @param packet to send
30 * @param use_locking
31 *               CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG,
32 *               or CVMX_PKO_LOCK_CMD_QUEUE
33 *
34 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output
35 */
36static inline cvmx_pko_return_value_t
37cvmx_pko_send_packet_finish(u64 ipd_port, uint64_t queue,
38			    cvmx_pko_command_word0_t pko_command,
39			    cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking)
40{
41	cvmx_cmd_queue_result_t result;
42
43	if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
44		return cvmx_pko3_legacy_xmit(queue, pko_command, packet, 0,
45					     use_locking ==
46						     CVMX_PKO_LOCK_ATOMIC_TAG);
47	}
48
49	if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
50		cvmx_pow_tag_sw_wait();
51
52	result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue),
53				       (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
54				       pko_command.u64, packet.u64);
55	if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
56		cvmx_pko_doorbell(ipd_port, queue, 2);
57		return CVMX_PKO_SUCCESS;
58	} else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ||
59		   (result == CVMX_CMD_QUEUE_FULL)) {
60		return CVMX_PKO_NO_MEMORY;
61	} else {
62		return CVMX_PKO_INVALID_QUEUE;
63	}
64}
65
66/**
67 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly
68 * once before this, and the same parameters must be passed to both
69 * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish().
70 *
71 * WARNING: This function may have to look up the proper PKO port in
72 * the IPD port to PKO port map, and is thus slower than calling
73 * cvmx_pko_send_packet_finish3_pkoid() directly if the PKO port
74 * identifier is known.
75 *
76 * @param ipd_port   The IPD port corresponding the to pko port the packet is for
77 * @param queue  Queue to use
78 * @param pko_command
79 *               PKO HW command word
80 * @param packet to send
81 * @param addr   Physical address of a work queue entry or physical address to zero
82 *               on complete.
83 * @param use_locking
84 *               CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG,
85 *               or CVMX_PKO_LOCK_CMD_QUEUE
86 *
87 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output
88 */
89static inline cvmx_pko_return_value_t
90cvmx_pko_send_packet_finish3(u64 ipd_port, uint64_t queue,
91			     cvmx_pko_command_word0_t pko_command,
92			     cvmx_buf_ptr_t packet, uint64_t addr,
93			     cvmx_pko_lock_t use_locking)
94{
95	cvmx_cmd_queue_result_t result;
96
97	if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
98		return cvmx_pko3_legacy_xmit(queue, pko_command, packet, addr,
99					     use_locking ==
100						     CVMX_PKO_LOCK_ATOMIC_TAG);
101	}
102
103	if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
104		cvmx_pow_tag_sw_wait();
105
106	result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue),
107				       (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
108				       pko_command.u64, packet.u64, addr);
109	if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
110		cvmx_pko_doorbell(ipd_port, queue, 3);
111		return CVMX_PKO_SUCCESS;
112	} else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ||
113		   (result == CVMX_CMD_QUEUE_FULL)) {
114		return CVMX_PKO_NO_MEMORY;
115	} else {
116		return CVMX_PKO_INVALID_QUEUE;
117	}
118}
119
120/**
121 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly
122 * once before this, and the same parameters must be passed to both
123 * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish_pkoid().
124 *
125 * @param pko_port   Port to send it on
126 * @param queue  Queue to use
127 * @param pko_command
128 *               PKO HW command word
129 * @param packet to send
130 * @param use_locking
131 *               CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG,
132 *               or CVMX_PKO_LOCK_CMD_QUEUE
133 *
134 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output
135 */
136static inline cvmx_pko_return_value_t
137cvmx_pko_send_packet_finish_pkoid(int pko_port, uint64_t queue,
138				  cvmx_pko_command_word0_t pko_command,
139				  cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking)
140{
141	cvmx_cmd_queue_result_t result;
142
143	if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
144		return cvmx_pko3_legacy_xmit(queue, pko_command, packet, 0,
145					     use_locking ==
146						     CVMX_PKO_LOCK_ATOMIC_TAG);
147	}
148
149	if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
150		cvmx_pow_tag_sw_wait();
151	result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue),
152				       (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
153				       pko_command.u64, packet.u64);
154	if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
155		cvmx_pko_doorbell_pkoid(pko_port, queue, 2);
156		return CVMX_PKO_SUCCESS;
157	} else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ||
158		   (result == CVMX_CMD_QUEUE_FULL)) {
159		return CVMX_PKO_NO_MEMORY;
160	} else {
161		return CVMX_PKO_INVALID_QUEUE;
162	}
163}
164
165/**
166 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly
167 * once before this, and the same parameters must be passed to both
168 * cvmx_pko_send_packet_prepare() and cvmx_pko_send_packet_finish_pkoid().
169 *
170 * @param pko_port   The PKO port the packet is for
171 * @param queue  Queue to use
172 * @param pko_command
173 *               PKO HW command word
174 * @param packet to send
175 * @param addr   Plysical address of a work queue entry or physical address to zero
176 *               on complete.
177 * @param use_locking
178 *               CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG,
179 *               or CVMX_PKO_LOCK_CMD_QUEUE
180 *
181 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output
182 */
183static inline cvmx_pko_return_value_t
184cvmx_pko_send_packet_finish3_pkoid(u64 pko_port, uint64_t queue,
185				   cvmx_pko_command_word0_t pko_command,
186				   cvmx_buf_ptr_t packet, uint64_t addr,
187				   cvmx_pko_lock_t use_locking)
188{
189	cvmx_cmd_queue_result_t result;
190
191	if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
192		return cvmx_pko3_legacy_xmit(queue, pko_command, packet, addr,
193					     use_locking ==
194						     CVMX_PKO_LOCK_ATOMIC_TAG);
195	}
196
197	if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
198		cvmx_pow_tag_sw_wait();
199	result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue),
200				       (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
201				       pko_command.u64, packet.u64, addr);
202	if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
203		cvmx_pko_doorbell_pkoid(pko_port, queue, 3);
204		return CVMX_PKO_SUCCESS;
205	} else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ||
206		   (result == CVMX_CMD_QUEUE_FULL)) {
207		return CVMX_PKO_NO_MEMORY;
208	} else {
209		return CVMX_PKO_INVALID_QUEUE;
210	}
211}
212
213#endif /* __CVMX_PKO_H__ */
214