doc: clarify PMD order in release notes
[dpdk.git] / doc / guides / rawdevs / ioat.rst
1 ..  SPDX-License-Identifier: BSD-3-Clause
2     Copyright(c) 2019 Intel Corporation.
3
4 .. include:: <isonum.txt>
5
6 IOAT Rawdev Driver
7 ===================
8
9 The ``ioat`` rawdev driver provides a poll-mode driver (PMD) for Intel\ |reg|
10 Data Streaming Accelerator `(Intel DSA)
11 <https://01.org/blogs/2019/introducing-intel-data-streaming-accelerator>`_ and for Intel\ |reg|
12 QuickData Technology, part of Intel\ |reg| I/O Acceleration Technology
13 `(Intel I/OAT)
14 <https://www.intel.com/content/www/us/en/wireless-network/accel-technology.html>`_.
15 This PMD, when used on supported hardware, allows data copies, for example,
16 cloning packet data, to be accelerated by that hardware rather than having to
17 be done by software, freeing up CPU cycles for other tasks.
18
19 Hardware Requirements
20 ----------------------
21
22 The ``dpdk-devbind.py`` script, included with DPDK,
23 can be used to show the presence of supported hardware.
24 Running ``dpdk-devbind.py --status-dev misc`` will show all the miscellaneous,
25 or rawdev-based devices on the system.
26 For Intel\ |reg| QuickData Technology devices, the hardware will be often listed as "Crystal Beach DMA",
27 or "CBDMA".
28 For Intel\ |reg| DSA devices, they are currently (at time of writing) appearing as devices with type "0b25",
29 due to the absence of pci-id database entries for them at this point.
30
31 Compilation
32 ------------
33
34 For builds using ``meson`` and ``ninja``, the driver will be built when the target platform is x86-based.
35 No additional compilation steps are necessary.
36
37 Device Setup
38 -------------
39
40 Depending on support provided by the PMD, HW devices can either use the kernel configured driver
41 or be bound to a user-space IO driver for use.
42 For example, Intel\ |reg| DSA devices can use the IDXD kernel driver or DPDK-supported drivers,
43 such as ``vfio-pci``.
44
45 Intel\ |reg| DSA devices using idxd kernel driver
46 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47
48 To use a Intel\ |reg| DSA device bound to the IDXD kernel driver, the device must first be configured.
49 The `accel-config <https://github.com/intel/idxd-config>`_ utility library can be used for configuration.
50
51 .. note::
52         The device configuration can also be done by directly interacting with the sysfs nodes.
53         An example of how this may be done can be seen in the script ``dpdk_idxd_cfg.py``
54         included in the driver source directory.
55
56 There are some mandatory configuration steps before being able to use a device with an application.
57 The internal engines, which do the copies or other operations,
58 and the work-queues, which are used by applications to assign work to the device,
59 need to be assigned to groups, and the various other configuration options,
60 such as priority or queue depth, need to be set for each queue.
61
62 To assign an engine to a group::
63
64         $ accel-config config-engine dsa0/engine0.0 --group-id=0
65         $ accel-config config-engine dsa0/engine0.1 --group-id=1
66
67 To assign work queues to groups for passing descriptors to the engines a similar accel-config command can be used.
68 However, the work queues also need to be configured depending on the use-case.
69 Some configuration options include:
70
71 * mode (Dedicated/Shared): Indicates whether a WQ may accept jobs from multiple queues simultaneously.
72 * priority: WQ priority between 1 and 15. Larger value means higher priority.
73 * wq-size: the size of the WQ. Sum of all WQ sizes must be less that the total-size defined by the device.
74 * type: WQ type (kernel/mdev/user). Determines how the device is presented.
75 * name: identifier given to the WQ.
76
77 Example configuration for a work queue::
78
79         $ accel-config config-wq dsa0/wq0.0 --group-id=0 \
80            --mode=dedicated --priority=10 --wq-size=8 \
81            --type=user --name=dpdk_app1
82
83 Once the devices have been configured, they need to be enabled::
84
85         $ accel-config enable-device dsa0
86         $ accel-config enable-wq dsa0/wq0.0
87
88 Check the device configuration::
89
90         $ accel-config list
91
92 Devices using VFIO/UIO drivers
93 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94
95 The HW devices to be used will need to be bound to a user-space IO driver for use.
96 The ``dpdk-devbind.py`` script can be used to view the state of the devices
97 and to bind them to a suitable DPDK-supported driver, such as ``vfio-pci``.
98 For example::
99
100         $ dpdk-devbind.py -b vfio-pci 00:04.0 00:04.1
101
102 Device Probing and Initialization
103 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
104
105 For devices bound to a suitable DPDK-supported VFIO/UIO driver, the HW devices will
106 be found as part of the device scan done at application initialization time without
107 the need to pass parameters to the application.
108
109 For Intel\ |reg| DSA devices, DPDK will automatically configure the device with the
110 maximum number of workqueues available on it, partitioning all resources equally
111 among the queues.
112 If fewer workqueues are required, then the ``max_queues`` parameter may be passed to
113 the device driver on the EAL commandline, via the ``allowlist`` or ``-a`` flag e.g.::
114
115         $ dpdk-test -a <b:d:f>,max_queues=4
116
117 For devices bound to the IDXD kernel driver,
118 the DPDK ioat driver will automatically perform a scan for available workqueues to use.
119 Any workqueues found listed in ``/dev/dsa`` on the system will be checked in ``/sys``,
120 and any which have ``dpdk_`` prefix in their name will be automatically probed by the
121 driver to make them available to the application.
122 Alternatively, to support use by multiple DPDK processes simultaneously,
123 the value used as the DPDK ``--file-prefix`` parameter may be used as a workqueue name prefix,
124 instead of ``dpdk_``,
125 allowing each DPDK application instance to only use a subset of configured queues.
126
127 Once probed successfully, irrespective of kernel driver, the device will appear as a ``rawdev``,
128 that is a "raw device type" inside DPDK, and can be accessed using APIs from the
129 ``rte_rawdev`` library.
130
131 Using IOAT Rawdev Devices
132 --------------------------
133
134 To use the devices from an application, the rawdev API can be used, along
135 with definitions taken from the device-specific header file
136 ``rte_ioat_rawdev.h``. This header is needed to get the definition of
137 structure parameters used by some of the rawdev APIs for IOAT rawdev
138 devices, as well as providing key functions for using the device for memory
139 copies.
140
141 Getting Device Information
142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
143
144 Basic information about each rawdev device can be queried using the
145 ``rte_rawdev_info_get()`` API. For most applications, this API will be
146 needed to verify that the rawdev in question is of the expected type. For
147 example, the following code snippet can be used to identify an IOAT
148 rawdev device for use by an application:
149
150 .. code-block:: C
151
152         for (i = 0; i < count && !found; i++) {
153                 struct rte_rawdev_info info = { .dev_private = NULL };
154                 found = (rte_rawdev_info_get(i, &info, 0) == 0 &&
155                                 strcmp(info.driver_name,
156                                                 IOAT_PMD_RAWDEV_NAME_STR) == 0);
157         }
158
159 When calling the ``rte_rawdev_info_get()`` API for an IOAT rawdev device,
160 the ``dev_private`` field in the ``rte_rawdev_info`` struct should either
161 be NULL, or else be set to point to a structure of type
162 ``rte_ioat_rawdev_config``, in which case the size of the configured device
163 input ring will be returned in that structure.
164
165 Device Configuration
166 ~~~~~~~~~~~~~~~~~~~~~
167
168 Configuring an IOAT rawdev device is done using the
169 ``rte_rawdev_configure()`` API, which takes the same structure parameters
170 as the, previously referenced, ``rte_rawdev_info_get()`` API. The main
171 difference is that, because the parameter is used as input rather than
172 output, the ``dev_private`` structure element cannot be NULL, and must
173 point to a valid ``rte_ioat_rawdev_config`` structure, containing the ring
174 size to be used by the device. The ring size must be a power of two,
175 between 64 and 4096.
176 If it is not needed, the tracking by the driver of user-provided completion
177 handles may be disabled by setting the ``hdls_disable`` flag in
178 the configuration structure also.
179
180 The following code shows how the device is configured in
181 ``test_ioat_rawdev.c``:
182
183 .. code-block:: C
184
185    #define IOAT_TEST_RINGSIZE 512
186         struct rte_ioat_rawdev_config p = { .ring_size = -1 };
187         struct rte_rawdev_info info = { .dev_private = &p };
188
189         /* ... */
190
191         p.ring_size = IOAT_TEST_RINGSIZE;
192         if (rte_rawdev_configure(dev_id, &info, sizeof(p)) != 0) {
193                 printf("Error with rte_rawdev_configure()\n");
194                 return -1;
195         }
196
197 Once configured, the device can then be made ready for use by calling the
198 ``rte_rawdev_start()`` API.
199
200 Performing Data Copies
201 ~~~~~~~~~~~~~~~~~~~~~~~
202
203 To perform data copies using IOAT rawdev devices, the functions
204 ``rte_ioat_enqueue_copy()`` and ``rte_ioat_perform_ops()`` should be used.
205 Once copies have been completed, the completion will be reported back when
206 the application calls ``rte_ioat_completed_ops()``.
207
208 The ``rte_ioat_enqueue_copy()`` function enqueues a single copy to the
209 device ring for copying at a later point. The parameters to that function
210 include the IOVA addresses of both the source and destination buffers,
211 as well as two "handles" to be returned to the user when the copy is
212 completed. These handles can be arbitrary values, but two are provided so
213 that the library can track handles for both source and destination on
214 behalf of the user, e.g. virtual addresses for the buffers, or mbuf
215 pointers if packet data is being copied.
216
217 While the ``rte_ioat_enqueue_copy()`` function enqueues a copy operation on
218 the device ring, the copy will not actually be performed until after the
219 application calls the ``rte_ioat_perform_ops()`` function. This function
220 informs the device hardware of the elements enqueued on the ring, and the
221 device will begin to process them. It is expected that, for efficiency
222 reasons, a burst of operations will be enqueued to the device via multiple
223 enqueue calls between calls to the ``rte_ioat_perform_ops()`` function.
224
225 The following code from ``test_ioat_rawdev.c`` demonstrates how to enqueue
226 a burst of copies to the device and start the hardware processing of them:
227
228 .. code-block:: C
229
230         struct rte_mbuf *srcs[32], *dsts[32];
231         unsigned int j;
232
233         for (i = 0; i < RTE_DIM(srcs); i++) {
234                 char *src_data;
235
236                 srcs[i] = rte_pktmbuf_alloc(pool);
237                 dsts[i] = rte_pktmbuf_alloc(pool);
238                 srcs[i]->data_len = srcs[i]->pkt_len = length;
239                 dsts[i]->data_len = dsts[i]->pkt_len = length;
240                 src_data = rte_pktmbuf_mtod(srcs[i], char *);
241
242                 for (j = 0; j < length; j++)
243                         src_data[j] = rand() & 0xFF;
244
245                 if (rte_ioat_enqueue_copy(dev_id,
246                                 srcs[i]->buf_iova + srcs[i]->data_off,
247                                 dsts[i]->buf_iova + dsts[i]->data_off,
248                                 length,
249                                 (uintptr_t)srcs[i],
250                                 (uintptr_t)dsts[i]) != 1) {
251                         printf("Error with rte_ioat_enqueue_copy for buffer %u\n",
252                                         i);
253                         return -1;
254                 }
255         }
256         rte_ioat_perform_ops(dev_id);
257
258 To retrieve information about completed copies, the API
259 ``rte_ioat_completed_ops()`` should be used. This API will return to the
260 application a set of completion handles passed in when the relevant copies
261 were enqueued.
262
263 The following code from ``test_ioat_rawdev.c`` shows the test code
264 retrieving information about the completed copies and validating the data
265 is correct before freeing the data buffers using the returned handles:
266
267 .. code-block:: C
268
269         if (rte_ioat_completed_ops(dev_id, 64, (void *)completed_src,
270                         (void *)completed_dst) != RTE_DIM(srcs)) {
271                 printf("Error with rte_ioat_completed_ops\n");
272                 return -1;
273         }
274         for (i = 0; i < RTE_DIM(srcs); i++) {
275                 char *src_data, *dst_data;
276
277                 if (completed_src[i] != srcs[i]) {
278                         printf("Error with source pointer %u\n", i);
279                         return -1;
280                 }
281                 if (completed_dst[i] != dsts[i]) {
282                         printf("Error with dest pointer %u\n", i);
283                         return -1;
284                 }
285
286                 src_data = rte_pktmbuf_mtod(srcs[i], char *);
287                 dst_data = rte_pktmbuf_mtod(dsts[i], char *);
288                 for (j = 0; j < length; j++)
289                         if (src_data[j] != dst_data[j]) {
290                                 printf("Error with copy of packet %u, byte %u\n",
291                                                 i, j);
292                                 return -1;
293                         }
294                 rte_pktmbuf_free(srcs[i]);
295                 rte_pktmbuf_free(dsts[i]);
296         }
297
298
299 Filling an Area of Memory
300 ~~~~~~~~~~~~~~~~~~~~~~~~~~
301
302 The IOAT driver also has support for the ``fill`` operation, where an area
303 of memory is overwritten, or filled, with a short pattern of data.
304 Fill operations can be performed in much the same was as copy operations
305 described above, just using the ``rte_ioat_enqueue_fill()`` function rather
306 than the ``rte_ioat_enqueue_copy()`` function.
307
308
309 Querying Device Statistics
310 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
311
312 The statistics from the IOAT rawdev device can be got via the xstats
313 functions in the ``rte_rawdev`` library, i.e.
314 ``rte_rawdev_xstats_names_get()``, ``rte_rawdev_xstats_get()`` and
315 ``rte_rawdev_xstats_by_name_get``. The statistics returned for each device
316 instance are:
317
318 * ``failed_enqueues``
319 * ``successful_enqueues``
320 * ``copies_started``
321 * ``copies_completed``