1afa3a1584212def4c364f2567b8d20177c42334
[dpdk.git] / drivers / crypto / virtio / virtio_cryptodev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
3  */
4 #include <rte_pci.h>
5 #include <rte_bus_pci.h>
6 #include <rte_cryptodev.h>
7 #include <rte_cryptodev_pmd.h>
8 #include <rte_eal.h>
9
10 #include "virtio_cryptodev.h"
11 #include "virtqueue.h"
12
13 int virtio_crypto_logtype_init;
14 int virtio_crypto_logtype_session;
15 int virtio_crypto_logtype_rx;
16 int virtio_crypto_logtype_tx;
17 int virtio_crypto_logtype_driver;
18
19 /*
20  * The set of PCI devices this driver supports
21  */
22 static const struct rte_pci_id pci_id_virtio_crypto_map[] = {
23         { RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID,
24                                 VIRTIO_CRYPTO_PCI_DEVICEID) },
25         { .vendor_id = 0, /* sentinel */ },
26 };
27
28 uint8_t cryptodev_virtio_driver_id;
29
30 /*
31  * dev_ops for virtio, bare necessities for basic operation
32  */
33 static struct rte_cryptodev_ops virtio_crypto_dev_ops = {
34         /* Device related operations */
35         .dev_configure                   = NULL,
36         .dev_start                       = NULL,
37         .dev_stop                        = NULL,
38         .dev_close                       = NULL,
39         .dev_infos_get                   = NULL,
40
41         .stats_get                       = NULL,
42         .stats_reset                     = NULL,
43
44         .queue_pair_setup                = NULL,
45         .queue_pair_release              = NULL,
46         .queue_pair_start                = NULL,
47         .queue_pair_stop                 = NULL,
48         .queue_pair_count                = NULL,
49
50         /* Crypto related operations */
51         .session_get_size       = NULL,
52         .session_configure      = NULL,
53         .session_clear          = NULL,
54         .qp_attach_session = NULL,
55         .qp_detach_session = NULL
56 };
57
58 static int
59 virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features)
60 {
61         uint64_t host_features;
62
63         PMD_INIT_FUNC_TRACE();
64
65         /* Prepare guest_features: feature that driver wants to support */
66         VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64,
67                 req_features);
68
69         /* Read device(host) feature bits */
70         host_features = VTPCI_OPS(hw)->get_features(hw);
71         VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64,
72                 host_features);
73
74         /*
75          * Negotiate features: Subset of device feature bits are written back
76          * guest feature bits.
77          */
78         hw->guest_features = req_features;
79         hw->guest_features = vtpci_cryptodev_negotiate_features(hw,
80                                                         host_features);
81         VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64,
82                 hw->guest_features);
83
84         if (hw->modern) {
85                 if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) {
86                         VIRTIO_CRYPTO_INIT_LOG_ERR(
87                                 "VIRTIO_F_VERSION_1 features is not enabled.");
88                         return -1;
89                 }
90                 vtpci_cryptodev_set_status(hw,
91                         VIRTIO_CONFIG_STATUS_FEATURES_OK);
92                 if (!(vtpci_cryptodev_get_status(hw) &
93                         VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
94                         VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK "
95                                                 "status!");
96                         return -1;
97                 }
98         }
99
100         hw->req_guest_features = req_features;
101
102         return 0;
103 }
104
105 /* reset device and renegotiate features if needed */
106 static int
107 virtio_crypto_init_device(struct rte_cryptodev *cryptodev,
108         uint64_t req_features)
109 {
110         struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
111         struct virtio_crypto_config local_config;
112         struct virtio_crypto_config *config = &local_config;
113
114         PMD_INIT_FUNC_TRACE();
115
116         /* Reset the device although not necessary at startup */
117         vtpci_cryptodev_reset(hw);
118
119         /* Tell the host we've noticed this device. */
120         vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
121
122         /* Tell the host we've known how to drive the device. */
123         vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
124         if (virtio_negotiate_features(hw, req_features) < 0)
125                 return -1;
126
127         /* Get status of the device */
128         vtpci_read_cryptodev_config(hw,
129                 offsetof(struct virtio_crypto_config, status),
130                 &config->status, sizeof(config->status));
131         if (config->status != VIRTIO_CRYPTO_S_HW_READY) {
132                 VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is "
133                                 "not ready");
134                 return -1;
135         }
136
137         /* Get number of data queues */
138         vtpci_read_cryptodev_config(hw,
139                 offsetof(struct virtio_crypto_config, max_dataqueues),
140                 &config->max_dataqueues,
141                 sizeof(config->max_dataqueues));
142         hw->max_dataqueues = config->max_dataqueues;
143
144         VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d",
145                 hw->max_dataqueues);
146
147         return 0;
148 }
149
150 /*
151  * This function is based on probe() function
152  * It returns 0 on success.
153  */
154 static int
155 crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev,
156                 struct rte_cryptodev_pmd_init_params *init_params)
157 {
158         struct rte_cryptodev *cryptodev;
159         struct virtio_crypto_hw *hw;
160
161         PMD_INIT_FUNC_TRACE();
162
163         cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device,
164                                         init_params);
165         if (cryptodev == NULL)
166                 return -ENODEV;
167
168         cryptodev->driver_id = cryptodev_virtio_driver_id;
169         cryptodev->dev_ops = &virtio_crypto_dev_ops;
170
171         cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst;
172         cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst;
173
174         cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
175                 RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
176
177         hw = cryptodev->data->dev_private;
178         hw->dev_id = cryptodev->data->dev_id;
179
180         VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x",
181                 cryptodev->data->dev_id, pci_dev->id.vendor_id,
182                 pci_dev->id.device_id);
183
184         /* pci device init */
185         if (vtpci_cryptodev_init(pci_dev, hw))
186                 return -1;
187
188         if (virtio_crypto_init_device(cryptodev,
189                         VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
190                 return -1;
191
192         return 0;
193 }
194
195 static int
196 crypto_virtio_pci_probe(
197         struct rte_pci_driver *pci_drv __rte_unused,
198         struct rte_pci_device *pci_dev)
199 {
200         struct rte_cryptodev_pmd_init_params init_params = {
201                 .name = "",
202                 .socket_id = rte_socket_id(),
203                 .private_data_size = sizeof(struct virtio_crypto_hw),
204                 .max_nb_sessions = RTE_VIRTIO_CRYPTO_PMD_MAX_NB_SESSIONS
205         };
206         char name[RTE_CRYPTODEV_NAME_MAX_LEN];
207
208         VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x",
209                         pci_dev->addr.bus,
210                         pci_dev->addr.devid,
211                         pci_dev->addr.function);
212
213         rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
214
215         return crypto_virtio_create(name, pci_dev, &init_params);
216 }
217
218 static int
219 crypto_virtio_pci_remove(
220         struct rte_pci_device *pci_dev __rte_unused)
221 {
222         struct rte_cryptodev *cryptodev;
223         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
224
225         if (pci_dev == NULL)
226                 return -EINVAL;
227
228         rte_pci_device_name(&pci_dev->addr, cryptodev_name,
229                         sizeof(cryptodev_name));
230
231         cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
232         if (cryptodev == NULL)
233                 return -ENODEV;
234
235         return 0;
236 }
237
238 static struct rte_pci_driver rte_virtio_crypto_driver = {
239         .id_table = pci_id_virtio_crypto_map,
240         .drv_flags = 0,
241         .probe = crypto_virtio_pci_probe,
242         .remove = crypto_virtio_pci_remove
243 };
244
245 static struct cryptodev_driver virtio_crypto_drv;
246
247 RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver);
248 RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv,
249         rte_virtio_crypto_driver.driver,
250         cryptodev_virtio_driver_id);
251
252 RTE_INIT(virtio_crypto_init_log);
253 static void
254 virtio_crypto_init_log(void)
255 {
256         virtio_crypto_logtype_init = rte_log_register("pmd.crypto.virtio.init");
257         if (virtio_crypto_logtype_init >= 0)
258                 rte_log_set_level(virtio_crypto_logtype_init, RTE_LOG_NOTICE);
259
260         virtio_crypto_logtype_session =
261                 rte_log_register("pmd.crypto.virtio.session");
262         if (virtio_crypto_logtype_session >= 0)
263                 rte_log_set_level(virtio_crypto_logtype_session,
264                                 RTE_LOG_NOTICE);
265
266         virtio_crypto_logtype_rx = rte_log_register("pmd.crypto.virtio.rx");
267         if (virtio_crypto_logtype_rx >= 0)
268                 rte_log_set_level(virtio_crypto_logtype_rx, RTE_LOG_NOTICE);
269
270         virtio_crypto_logtype_tx = rte_log_register("pmd.crypto.virtio.tx");
271         if (virtio_crypto_logtype_tx >= 0)
272                 rte_log_set_level(virtio_crypto_logtype_tx, RTE_LOG_NOTICE);
273
274         virtio_crypto_logtype_driver =
275                 rte_log_register("pmd.crypto.virtio.driver");
276         if (virtio_crypto_logtype_driver >= 0)
277                 rte_log_set_level(virtio_crypto_logtype_driver, RTE_LOG_NOTICE);
278 }