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;
46 * Structure representing a device instance
48 struct rte_ioat_rawdev {
49 struct rte_rawdev *rawdev;
50 const struct rte_memzone *mz;
51 const struct rte_memzone *desc_mz;
53 volatile struct rte_ioat_registers *regs;
54 phys_addr_t status_addr;
55 phys_addr_t ring_addr;
57 unsigned short ring_size;
58 struct rte_ioat_generic_hw_desc *desc_ring;
59 __m128i *hdls; /* completion handles for returning to user */
62 unsigned short next_read;
63 unsigned short next_write;
65 /* some statistics for tracking, if added/changed update xstats fns*/
66 uint64_t enqueue_failed __rte_cache_aligned;
71 /* to report completions, the device will write status back here */
72 volatile uint64_t status __rte_cache_aligned;
76 * Enqueue a copy operation onto the ioat device
78 * This queues up a copy operation to be performed by hardware, but does not
79 * trigger hardware to begin that operation.
82 * The rawdev device id of the ioat instance
84 * The physical address of the source buffer
86 * The physical address of the destination buffer
88 * The length of the data to be copied
90 * An opaque handle for the source data, to be returned when this operation
91 * has been completed and the user polls for the completion details
93 * An opaque handle for the destination data, to be returned when this
94 * operation has been completed and the user polls for the completion details
96 * A flag parameter indicating that hardware should not begin to perform any
97 * subsequently enqueued copy operations until after this operation has
100 * Number of operations enqueued, either 0 or 1
103 rte_ioat_enqueue_copy(int dev_id, phys_addr_t src, phys_addr_t dst,
104 unsigned int length, uintptr_t src_hdl, uintptr_t dst_hdl,
107 struct rte_ioat_rawdev *ioat =
108 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
109 unsigned short read = ioat->next_read;
110 unsigned short write = ioat->next_write;
111 unsigned short mask = ioat->ring_size - 1;
112 unsigned short space = mask + read - write;
113 struct rte_ioat_generic_hw_desc *desc;
116 ioat->enqueue_failed++;
120 ioat->next_write = write + 1;
123 desc = &ioat->desc_ring[write];
125 /* set descriptor write-back every 16th descriptor */
126 desc->u.control_raw = (uint32_t)((!!fence << 4) | (!(write & 0xF)) << 3);
127 desc->src_addr = src;
128 desc->dest_addr = dst;
130 ioat->hdls[write] = _mm_set_epi64x((int64_t)dst_hdl, (int64_t)src_hdl);
131 rte_prefetch0(&ioat->desc_ring[ioat->next_write & mask]);
138 * Trigger hardware to begin performing enqueued copy operations
140 * This API is used to write the "doorbell" to the hardware to trigger it
141 * to begin the copy operations previously enqueued by rte_ioat_enqueue_copy()
144 * The rawdev device id of the ioat instance
147 rte_ioat_do_copies(int dev_id)
149 struct rte_ioat_rawdev *ioat =
150 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
151 ioat->desc_ring[(ioat->next_write - 1) & (ioat->ring_size - 1)].u
152 .control.completion_update = 1;
153 rte_compiler_barrier();
154 ioat->regs->dmacount = ioat->next_write;
155 ioat->started = ioat->enqueued;
160 * Returns the index of the last completed operation.
163 rte_ioat_get_last_completed(struct rte_ioat_rawdev *ioat, int *error)
165 uint64_t status = ioat->status;
167 /* lower 3 bits indicate "transfer status" : active, idle, halted.
168 * We can ignore bit 0.
170 *error = status & (RTE_IOAT_CHANSTS_SUSPENDED | RTE_IOAT_CHANSTS_ARMED);
171 return (status - ioat->ring_addr) >> 6;
175 * Returns details of copy operations that have been completed
177 * Returns to the caller the user-provided "handles" for the copy operations
178 * which have been completed by the hardware, and not already returned by
179 * a previous call to this API.
182 * The rawdev device id of the ioat instance
184 * The number of entries which can fit in the src_hdls and dst_hdls
185 * arrays, i.e. max number of completed operations to report
187 * Array to hold the source handle parameters of the completed copies
189 * Array to hold the destination handle parameters of the completed copies
191 * -1 on error, with rte_errno set appropriately.
192 * Otherwise number of completed operations i.e. number of entries written
193 * to the src_hdls and dst_hdls array parameters.
196 rte_ioat_completed_copies(int dev_id, uint8_t max_copies,
197 uintptr_t *src_hdls, uintptr_t *dst_hdls)
199 struct rte_ioat_rawdev *ioat =
200 (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private;
201 unsigned short mask = (ioat->ring_size - 1);
202 unsigned short read = ioat->next_read;
203 unsigned short end_read, count;
207 end_read = (rte_ioat_get_last_completed(ioat, &error) + 1) & mask;
208 count = (end_read - (read & mask)) & mask;
215 if (count > max_copies)
218 for (; i < count - 1; i += 2, read += 2) {
219 __m128i hdls0 = _mm_load_si128(&ioat->hdls[read & mask]);
220 __m128i hdls1 = _mm_load_si128(&ioat->hdls[(read + 1) & mask]);
222 _mm_storeu_si128((__m128i *)&src_hdls[i],
223 _mm_unpacklo_epi64(hdls0, hdls1));
224 _mm_storeu_si128((__m128i *)&dst_hdls[i],
225 _mm_unpackhi_epi64(hdls0, hdls1));
227 for (; i < count; i++, read++) {
228 uintptr_t *hdls = (uintptr_t *)&ioat->hdls[read & mask];
229 src_hdls[i] = hdls[0];
230 dst_hdls[i] = hdls[1];
233 ioat->next_read = read;
234 ioat->completed += count;
242 #endif /* _RTE_IOAT_RAWDEV_H_ */