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