net/ice: redirect switch rule to new VSI
[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_epi64x((int64_t)dst_hdl, (int64_t)src_hdl);
128         rte_prefetch0(&ioat->desc_ring[ioat->next_write & mask]);
129
130         ioat->enqueued++;
131         return 1;
132 }
133
134 /**
135  * Trigger hardware to begin performing enqueued copy operations
136  *
137  * This API is used to write the "doorbell" to the hardware to trigger it
138  * to begin the copy operations previously enqueued by rte_ioat_enqueue_copy()
139  *
140  * @param dev_id
141  *   The rawdev device id of the ioat instance
142  */
143 static inline void
144 rte_ioat_do_copies(int dev_id)
145 {
146         struct rte_ioat_rawdev *ioat = rte_rawdevs[dev_id].dev_private;
147         ioat->desc_ring[(ioat->next_write - 1) & (ioat->ring_size - 1)].u
148                         .control.completion_update = 1;
149         rte_compiler_barrier();
150         ioat->regs->dmacount = ioat->next_write;
151         ioat->started = ioat->enqueued;
152 }
153
154 /**
155  * @internal
156  * Returns the index of the last completed operation.
157  */
158 static inline int
159 rte_ioat_get_last_completed(struct rte_ioat_rawdev *ioat, int *error)
160 {
161         uint64_t status = ioat->status;
162
163         /* lower 3 bits indicate "transfer status" : active, idle, halted.
164          * We can ignore bit 0.
165          */
166         *error = status & (RTE_IOAT_CHANSTS_SUSPENDED | RTE_IOAT_CHANSTS_ARMED);
167         return (status - ioat->ring_addr) >> 6;
168 }
169
170 /**
171  * Returns details of copy operations that have been completed
172  *
173  * Returns to the caller the user-provided "handles" for the copy operations
174  * which have been completed by the hardware, and not already returned by
175  * a previous call to this API.
176  *
177  * @param dev_id
178  *   The rawdev device id of the ioat instance
179  * @param max_copies
180  *   The number of entries which can fit in the src_hdls and dst_hdls
181  *   arrays, i.e. max number of completed operations to report
182  * @param src_hdls
183  *   Array to hold the source handle parameters of the completed copies
184  * @param dst_hdls
185  *   Array to hold the destination handle parameters of the completed copies
186  * @return
187  *   -1 on error, with rte_errno set appropriately.
188  *   Otherwise number of completed operations i.e. number of entries written
189  *   to the src_hdls and dst_hdls array parameters.
190  */
191 static inline int
192 rte_ioat_completed_copies(int dev_id, uint8_t max_copies,
193                 uintptr_t *src_hdls, uintptr_t *dst_hdls)
194 {
195         struct rte_ioat_rawdev *ioat = rte_rawdevs[dev_id].dev_private;
196         unsigned short mask = (ioat->ring_size - 1);
197         unsigned short read = ioat->next_read;
198         unsigned short end_read, count;
199         int error;
200         int i = 0;
201
202         end_read = (rte_ioat_get_last_completed(ioat, &error) + 1) & mask;
203         count = (end_read - (read & mask)) & mask;
204
205         if (error) {
206                 rte_errno = EIO;
207                 return -1;
208         }
209
210         if (count > max_copies)
211                 count = max_copies;
212
213         for (; i < count - 1; i += 2, read += 2) {
214                 __m128i hdls0 = _mm_load_si128(&ioat->hdls[read & mask]);
215                 __m128i hdls1 = _mm_load_si128(&ioat->hdls[(read + 1) & mask]);
216
217                 _mm_storeu_si128((void *)&src_hdls[i],
218                                 _mm_unpacklo_epi64(hdls0, hdls1));
219                 _mm_storeu_si128((void *)&dst_hdls[i],
220                                 _mm_unpackhi_epi64(hdls0, hdls1));
221         }
222         for (; i < count; i++, read++) {
223                 uintptr_t *hdls = (void *)&ioat->hdls[read & mask];
224                 src_hdls[i] = hdls[0];
225                 dst_hdls[i] = hdls[1];
226         }
227
228         ioat->next_read = read;
229         ioat->completed += count;
230         return count;
231 }
232
233 #endif /* _RTE_IOAT_RAWDEV_H_ */