1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019 Intel Corporation
5 #ifndef _RTE_IOAT_RAWDEV_H_
6 #define _RTE_IOAT_RAWDEV_H_
13 * @file rte_ioat_rawdev.h
15 * Definitions for using the ioat rawdev device driver
18 * @b EXPERIMENTAL: these structures and APIs may change without prior notice
21 #include <x86intrin.h>
22 #include <rte_atomic.h>
23 #include <rte_memory.h>
24 #include <rte_memzone.h>
25 #include <rte_prefetch.h>
26 #include "rte_ioat_spec.h"
28 /** Name of the device driver */
29 #define IOAT_PMD_RAWDEV_NAME rawdev_ioat
30 /** String reported as the device driver name by rte_rawdev_info_get() */
31 #define IOAT_PMD_RAWDEV_NAME_STR "rawdev_ioat"
34 * Configuration structure for an ioat rawdev instance
36 * This structure is to be passed as the ".dev_private" parameter when
37 * calling the rte_rawdev_get_info() and rte_rawdev_configure() APIs on
38 * an ioat rawdev instance.
40 struct rte_ioat_rawdev_config {
41 unsigned short ring_size; /**< size of job submission descriptor ring */
42 bool hdls_disable; /**< if set, ignore user-supplied handle params */
47 * Structure representing a device instance
49 struct rte_ioat_rawdev {
50 struct rte_rawdev *rawdev;
51 const struct rte_memzone *mz;
52 const struct rte_memzone *desc_mz;
54 volatile struct rte_ioat_registers *regs;
55 phys_addr_t status_addr;
56 phys_addr_t ring_addr;
58 unsigned short ring_size;
59 struct rte_ioat_generic_hw_desc *desc_ring;
61 __m128i *hdls; /* completion handles for returning to user */
64 unsigned short next_read;
65 unsigned short next_write;
67 /* some statistics for tracking, if added/changed update xstats fns*/
68 uint64_t enqueue_failed __rte_cache_aligned;
73 /* to report completions, the device will write status back here */
74 volatile uint64_t status __rte_cache_aligned;
78 * Enqueue a copy operation onto the ioat device
80 * This queues up a copy operation to be performed by hardware, but does not
81 * trigger hardware to begin that operation.
84 * The rawdev device id of the ioat instance
86 * The physical address of the source buffer
88 * The physical address of the destination buffer
90 * The length of the data to be copied
92 * An opaque handle for the source data, to be returned when this operation
93 * has been completed and the user polls for the completion details.
94 * NOTE: If hdls_disable configuration option for the device is set, this
95 * parameter is ignored.
97 * An opaque handle for the destination data, to be returned when this
98 * operation has been completed and the user polls for the completion details.
99 * NOTE: If hdls_disable configuration option for the device is set, this
100 * parameter is ignored.
102 * A flag parameter indicating that hardware should not begin to perform any
103 * subsequently enqueued copy operations until after this operation has
106 * Number of operations enqueued, either 0 or 1
109 rte_ioat_enqueue_copy(int dev_id, phys_addr_t src, phys_addr_t dst,
110 unsigned int length, uintptr_t src_hdl, uintptr_t dst_hdl,
113 struct rte_ioat_rawdev *ioat =
114 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
115 unsigned short read = ioat->next_read;
116 unsigned short write = ioat->next_write;
117 unsigned short mask = ioat->ring_size - 1;
118 unsigned short space = mask + read - write;
119 struct rte_ioat_generic_hw_desc *desc;
122 ioat->enqueue_failed++;
126 ioat->next_write = write + 1;
129 desc = &ioat->desc_ring[write];
131 /* set descriptor write-back every 16th descriptor */
132 desc->u.control_raw = (uint32_t)((!!fence << 4) | (!(write & 0xF)) << 3);
133 desc->src_addr = src;
134 desc->dest_addr = dst;
135 if (!ioat->hdls_disable)
136 ioat->hdls[write] = _mm_set_epi64x((int64_t)dst_hdl,
139 rte_prefetch0(&ioat->desc_ring[ioat->next_write & mask]);
146 * Trigger hardware to begin performing enqueued copy operations
148 * This API is used to write the "doorbell" to the hardware to trigger it
149 * to begin the copy operations previously enqueued by rte_ioat_enqueue_copy()
152 * The rawdev device id of the ioat instance
155 rte_ioat_do_copies(int dev_id)
157 struct rte_ioat_rawdev *ioat =
158 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
159 ioat->desc_ring[(ioat->next_write - 1) & (ioat->ring_size - 1)].u
160 .control.completion_update = 1;
161 rte_compiler_barrier();
162 ioat->regs->dmacount = ioat->next_write;
163 ioat->started = ioat->enqueued;
168 * Returns the index of the last completed operation.
171 rte_ioat_get_last_completed(struct rte_ioat_rawdev *ioat, int *error)
173 uint64_t status = ioat->status;
175 /* lower 3 bits indicate "transfer status" : active, idle, halted.
176 * We can ignore bit 0.
178 *error = status & (RTE_IOAT_CHANSTS_SUSPENDED | RTE_IOAT_CHANSTS_ARMED);
179 return (status - ioat->ring_addr) >> 6;
183 * Returns details of copy operations that have been completed
185 * If the hdls_disable option was not set when the device was configured,
186 * the function will return to the caller the user-provided "handles" for
187 * the copy operations which have been completed by the hardware, and not
188 * already returned by a previous call to this API.
189 * If the hdls_disable option for the device was set on configure, the
190 * max_copies, src_hdls and dst_hdls parameters will be ignored, and the
191 * function returns the number of newly-completed operations.
194 * The rawdev device id of the ioat instance
196 * The number of entries which can fit in the src_hdls and dst_hdls
197 * arrays, i.e. max number of completed operations to report.
198 * NOTE: If hdls_disable configuration option for the device is set, this
199 * parameter is ignored.
201 * Array to hold the source handle parameters of the completed copies.
202 * NOTE: If hdls_disable configuration option for the device is set, this
203 * parameter is ignored.
205 * Array to hold the destination handle parameters of the completed copies.
206 * NOTE: If hdls_disable configuration option for the device is set, this
207 * parameter is ignored.
209 * -1 on error, with rte_errno set appropriately.
210 * Otherwise number of completed operations i.e. number of entries written
211 * to the src_hdls and dst_hdls array parameters.
214 rte_ioat_completed_copies(int dev_id, uint8_t max_copies,
215 uintptr_t *src_hdls, uintptr_t *dst_hdls)
217 struct rte_ioat_rawdev *ioat =
218 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
219 unsigned short mask = (ioat->ring_size - 1);
220 unsigned short read = ioat->next_read;
221 unsigned short end_read, count;
225 end_read = (rte_ioat_get_last_completed(ioat, &error) + 1) & mask;
226 count = (end_read - (read & mask)) & mask;
233 if (ioat->hdls_disable) {
238 if (count > max_copies)
241 for (; i < count - 1; i += 2, read += 2) {
242 __m128i hdls0 = _mm_load_si128(&ioat->hdls[read & mask]);
243 __m128i hdls1 = _mm_load_si128(&ioat->hdls[(read + 1) & mask]);
245 _mm_storeu_si128((__m128i *)&src_hdls[i],
246 _mm_unpacklo_epi64(hdls0, hdls1));
247 _mm_storeu_si128((__m128i *)&dst_hdls[i],
248 _mm_unpackhi_epi64(hdls0, hdls1));
250 for (; i < count; i++, read++) {
251 uintptr_t *hdls = (uintptr_t *)&ioat->hdls[read & mask];
252 src_hdls[i] = hdls[0];
253 dst_hdls[i] = hdls[1];
256 ioat->next_read = read;
257 ioat->completed += count;
265 #endif /* _RTE_IOAT_RAWDEV_H_ */