drivers/octeontx2: fix icc build for i686
[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 /**
9  * @file rte_ioat_rawdev.h
10  *
11  * Definitions for using the ioat rawdev device driver
12  *
13  * @warning
14  * @b EXPERIMENTAL: these structures and APIs may change without prior notice
15  */
16
17 #include <x86intrin.h>
18 #include <rte_atomic.h>
19 #include <rte_memory.h>
20 #include <rte_memzone.h>
21 #include <rte_prefetch.h>
22 #include <rte_ioat_spec.h>
23
24 /** Name of the device driver */
25 #define IOAT_PMD_RAWDEV_NAME rawdev_ioat
26 /** String reported as the device driver name by rte_rawdev_info_get() */
27 #define IOAT_PMD_RAWDEV_NAME_STR "rawdev_ioat"
28 /** Name used to adjust the log level for this driver */
29 #define IOAT_PMD_LOG_NAME "rawdev.ioat"
30
31 /**
32  * Configuration structure for an ioat rawdev instance
33  *
34  * This structure is to be passed as the ".dev_private" parameter when
35  * calling the rte_rawdev_get_info() and rte_rawdev_configure() APIs on
36  * an ioat rawdev instance.
37  */
38 struct rte_ioat_rawdev_config {
39         unsigned short ring_size;
40 };
41
42 /**
43  * @internal
44  * Structure representing a device instance
45  */
46 struct rte_ioat_rawdev {
47         struct rte_rawdev *rawdev;
48         const struct rte_memzone *mz;
49         const struct rte_memzone *desc_mz;
50
51         volatile struct rte_ioat_registers *regs;
52         phys_addr_t status_addr;
53         phys_addr_t ring_addr;
54
55         unsigned short ring_size;
56         struct rte_ioat_generic_hw_desc *desc_ring;
57         __m128i *hdls; /* completion handles for returning to user */
58
59
60         unsigned short next_read;
61         unsigned short next_write;
62
63         /* some statistics for tracking, if added/changed update xstats fns*/
64         uint64_t enqueue_failed __rte_cache_aligned;
65         uint64_t enqueued;
66         uint64_t started;
67         uint64_t completed;
68
69         /* to report completions, the device will write status back here */
70         volatile uint64_t status __rte_cache_aligned;
71 };
72
73 /**
74  * Enqueue a copy operation onto the ioat device
75  *
76  * This queues up a copy operation to be performed by hardware, but does not
77  * trigger hardware to begin that operation.
78  *
79  * @param dev_id
80  *   The rawdev device id of the ioat instance
81  * @param src
82  *   The physical address of the source buffer
83  * @param dst
84  *   The physical address of the destination buffer
85  * @param length
86  *   The length of the data to be copied
87  * @param src_hdl
88  *   An opaque handle for the source data, to be returned when this operation
89  *   has been completed and the user polls for the completion details
90  * @param dst_hdl
91  *   An opaque handle for the destination data, to be returned when this
92  *   operation has been completed and the user polls for the completion details
93  * @param fence
94  *   A flag parameter indicating that hardware should not begin to perform any
95  *   subsequently enqueued copy operations until after this operation has
96  *   completed
97  * @return
98  *   Number of operations enqueued, either 0 or 1
99  */
100 static inline int
101 rte_ioat_enqueue_copy(int dev_id, phys_addr_t src, phys_addr_t dst,
102                 unsigned int length, uintptr_t src_hdl, uintptr_t dst_hdl,
103                 int fence)
104 {
105         struct rte_ioat_rawdev *ioat = rte_rawdevs[dev_id].dev_private;
106         unsigned short read = ioat->next_read;
107         unsigned short write = ioat->next_write;
108         unsigned short mask = ioat->ring_size - 1;
109         unsigned short space = mask + read - write;
110         struct rte_ioat_generic_hw_desc *desc;
111
112         if (space == 0) {
113                 ioat->enqueue_failed++;
114                 return 0;
115         }
116
117         ioat->next_write = write + 1;
118         write &= mask;
119
120         desc = &ioat->desc_ring[write];
121         desc->size = length;
122         /* set descriptor write-back every 16th descriptor */
123         desc->u.control_raw = (uint32_t)((!!fence << 4) | (!(write & 0xF)) << 3);
124         desc->src_addr = src;
125         desc->dest_addr = dst;
126
127         ioat->hdls[write] = _mm_set_epi64((__m64)((uint64_t)dst_hdl),
128                         (__m64)((uint64_t)src_hdl));
129         rte_prefetch0(&ioat->desc_ring[ioat->next_write & mask]);
130
131         ioat->enqueued++;
132         return 1;
133 }
134
135 /**
136  * Trigger hardware to begin performing enqueued copy operations
137  *
138  * This API is used to write the "doorbell" to the hardware to trigger it
139  * to begin the copy operations previously enqueued by rte_ioat_enqueue_copy()
140  *
141  * @param dev_id
142  *   The rawdev device id of the ioat instance
143  */
144 static inline void
145 rte_ioat_do_copies(int dev_id)
146 {
147         struct rte_ioat_rawdev *ioat = rte_rawdevs[dev_id].dev_private;
148         ioat->desc_ring[(ioat->next_write - 1) & (ioat->ring_size - 1)].u
149                         .control.completion_update = 1;
150         rte_compiler_barrier();
151         ioat->regs->dmacount = ioat->next_write;
152         ioat->started = ioat->enqueued;
153 }
154
155 /**
156  * @internal
157  * Returns the index of the last completed operation.
158  */
159 static inline int
160 rte_ioat_get_last_completed(struct rte_ioat_rawdev *ioat, int *error)
161 {
162         uint64_t status = ioat->status;
163
164         /* lower 3 bits indicate "transfer status" : active, idle, halted.
165          * We can ignore bit 0.
166          */
167         *error = status & (RTE_IOAT_CHANSTS_SUSPENDED | RTE_IOAT_CHANSTS_ARMED);
168         return (status - ioat->ring_addr) >> 6;
169 }
170
171 /**
172  * Returns details of copy operations that have been completed
173  *
174  * Returns to the caller the user-provided "handles" for the copy operations
175  * which have been completed by the hardware, and not already returned by
176  * a previous call to this API.
177  *
178  * @param dev_id
179  *   The rawdev device id of the ioat instance
180  * @param max_copies
181  *   The number of entries which can fit in the src_hdls and dst_hdls
182  *   arrays, i.e. max number of completed operations to report
183  * @param src_hdls
184  *   Array to hold the source handle parameters of the completed copies
185  * @param dst_hdls
186  *   Array to hold the destination handle parameters of the completed copies
187  * @return
188  *   -1 on error, with rte_errno set appropriately.
189  *   Otherwise number of completed operations i.e. number of entries written
190  *   to the src_hdls and dst_hdls array parameters.
191  */
192 static inline int
193 rte_ioat_completed_copies(int dev_id, uint8_t max_copies,
194                 uintptr_t *src_hdls, uintptr_t *dst_hdls)
195 {
196         struct rte_ioat_rawdev *ioat = rte_rawdevs[dev_id].dev_private;
197         unsigned short mask = (ioat->ring_size - 1);
198         unsigned short read = ioat->next_read;
199         unsigned short end_read, count;
200         int error;
201         int i = 0;
202
203         end_read = (rte_ioat_get_last_completed(ioat, &error) + 1) & mask;
204         count = (end_read - (read & mask)) & mask;
205
206         if (error) {
207                 rte_errno = EIO;
208                 return -1;
209         }
210
211         if (count > max_copies)
212                 count = max_copies;
213
214         for (; i < count - 1; i += 2, read += 2) {
215                 __m128i hdls0 = _mm_load_si128(&ioat->hdls[read & mask]);
216                 __m128i hdls1 = _mm_load_si128(&ioat->hdls[(read + 1) & mask]);
217
218                 _mm_storeu_si128((void *)&src_hdls[i],
219                                 _mm_unpacklo_epi64(hdls0, hdls1));
220                 _mm_storeu_si128((void *)&dst_hdls[i],
221                                 _mm_unpackhi_epi64(hdls0, hdls1));
222         }
223         for (; i < count; i++, read++) {
224                 uintptr_t *hdls = (void *)&ioat->hdls[read & mask];
225                 src_hdls[i] = hdls[0];
226                 dst_hdls[i] = hdls[1];
227         }
228
229         ioat->next_read = read;
230         ioat->completed += count;
231         return count;
232 }
233
234 #endif /* _RTE_IOAT_RAWDEV_H_ */