raw/ioat: add flag to control copying handle parameters
[dpdk.git] / drivers / raw / ioat / rte_ioat_rawdev.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #ifndef _RTE_IOAT_RAWDEV_H_
6 #define _RTE_IOAT_RAWDEV_H_
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 /**
13  * @file rte_ioat_rawdev.h
14  *
15  * Definitions for using the ioat rawdev device driver
16  *
17  * @warning
18  * @b EXPERIMENTAL: these structures and APIs may change without prior notice
19  */
20
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"
27
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"
32
33 /**
34  * Configuration structure for an ioat rawdev instance
35  *
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.
39  */
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 */
43 };
44
45 /**
46  * @internal
47  * Structure representing a device instance
48  */
49 struct rte_ioat_rawdev {
50         struct rte_rawdev *rawdev;
51         const struct rte_memzone *mz;
52         const struct rte_memzone *desc_mz;
53
54         volatile struct rte_ioat_registers *regs;
55         phys_addr_t status_addr;
56         phys_addr_t ring_addr;
57
58         unsigned short ring_size;
59         struct rte_ioat_generic_hw_desc *desc_ring;
60         bool hdls_disable;
61         __m128i *hdls; /* completion handles for returning to user */
62
63
64         unsigned short next_read;
65         unsigned short next_write;
66
67         /* some statistics for tracking, if added/changed update xstats fns*/
68         uint64_t enqueue_failed __rte_cache_aligned;
69         uint64_t enqueued;
70         uint64_t started;
71         uint64_t completed;
72
73         /* to report completions, the device will write status back here */
74         volatile uint64_t status __rte_cache_aligned;
75 };
76
77 /**
78  * Enqueue a copy operation onto the ioat device
79  *
80  * This queues up a copy operation to be performed by hardware, but does not
81  * trigger hardware to begin that operation.
82  *
83  * @param dev_id
84  *   The rawdev device id of the ioat instance
85  * @param src
86  *   The physical address of the source buffer
87  * @param dst
88  *   The physical address of the destination buffer
89  * @param length
90  *   The length of the data to be copied
91  * @param src_hdl
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.
96  * @param dst_hdl
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.
101  * @param fence
102  *   A flag parameter indicating that hardware should not begin to perform any
103  *   subsequently enqueued copy operations until after this operation has
104  *   completed
105  * @return
106  *   Number of operations enqueued, either 0 or 1
107  */
108 static inline int
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,
111                 int fence)
112 {
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;
120
121         if (space == 0) {
122                 ioat->enqueue_failed++;
123                 return 0;
124         }
125
126         ioat->next_write = write + 1;
127         write &= mask;
128
129         desc = &ioat->desc_ring[write];
130         desc->size = length;
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,
137                                         (int64_t)src_hdl);
138
139         rte_prefetch0(&ioat->desc_ring[ioat->next_write & mask]);
140
141         ioat->enqueued++;
142         return 1;
143 }
144
145 /**
146  * Trigger hardware to begin performing enqueued copy operations
147  *
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()
150  *
151  * @param dev_id
152  *   The rawdev device id of the ioat instance
153  */
154 static inline void
155 rte_ioat_do_copies(int dev_id)
156 {
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;
164 }
165
166 /**
167  * @internal
168  * Returns the index of the last completed operation.
169  */
170 static inline int
171 rte_ioat_get_last_completed(struct rte_ioat_rawdev *ioat, int *error)
172 {
173         uint64_t status = ioat->status;
174
175         /* lower 3 bits indicate "transfer status" : active, idle, halted.
176          * We can ignore bit 0.
177          */
178         *error = status & (RTE_IOAT_CHANSTS_SUSPENDED | RTE_IOAT_CHANSTS_ARMED);
179         return (status - ioat->ring_addr) >> 6;
180 }
181
182 /**
183  * Returns details of copy operations that have been completed
184  *
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.
192  *
193  * @param dev_id
194  *   The rawdev device id of the ioat instance
195  * @param max_copies
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.
200  * @param src_hdls
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.
204  * @param dst_hdls
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.
208  * @return
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.
212  */
213 static inline int
214 rte_ioat_completed_copies(int dev_id, uint8_t max_copies,
215                 uintptr_t *src_hdls, uintptr_t *dst_hdls)
216 {
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;
222         int error;
223         int i = 0;
224
225         end_read = (rte_ioat_get_last_completed(ioat, &error) + 1) & mask;
226         count = (end_read - (read & mask)) & mask;
227
228         if (error) {
229                 rte_errno = EIO;
230                 return -1;
231         }
232
233         if (ioat->hdls_disable) {
234                 read += count;
235                 goto end;
236         }
237
238         if (count > max_copies)
239                 count = max_copies;
240
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]);
244
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));
249         }
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];
254         }
255 end:
256         ioat->next_read = read;
257         ioat->completed += count;
258         return count;
259 }
260
261 #ifdef __cplusplus
262 }
263 #endif
264
265 #endif /* _RTE_IOAT_RAWDEV_H_ */