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 } 279