125500d4bSJay Zhou /* SPDX-License-Identifier: BSD-3-Clause 225500d4bSJay Zhou * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD. 325500d4bSJay Zhou */ 425500d4bSJay Zhou 525500d4bSJay Zhou #include <stdint.h> 625500d4bSJay Zhou 7742bde12SBruce Richardson #ifdef RTE_EXEC_ENV_LINUX 825500d4bSJay Zhou #include <dirent.h> 925500d4bSJay Zhou #include <fcntl.h> 1025500d4bSJay Zhou #endif 1125500d4bSJay Zhou 1225500d4bSJay Zhou #include <rte_io.h> 1325500d4bSJay Zhou 1425500d4bSJay Zhou #include "virtio_pci.h" 1525500d4bSJay Zhou #include "virtqueue.h" 1625500d4bSJay Zhou 1725500d4bSJay Zhou /* 1825500d4bSJay Zhou * Following macros are derived from linux/pci_regs.h, however, 1925500d4bSJay Zhou * we can't simply include that header here, as there is no such 2025500d4bSJay Zhou * file for non-Linux platform. 2125500d4bSJay Zhou */ 2225500d4bSJay Zhou #define PCI_CAP_ID_VNDR 0x09 2325500d4bSJay Zhou #define PCI_CAP_ID_MSIX 0x11 2425500d4bSJay Zhou 2525500d4bSJay Zhou /* 2625500d4bSJay Zhou * The remaining space is defined by each driver as the per-driver 2725500d4bSJay Zhou * configuration space. 2825500d4bSJay Zhou */ 2925500d4bSJay Zhou #define VIRTIO_PCI_CONFIG(hw) \ 3025500d4bSJay Zhou (((hw)->use_msix == VIRTIO_MSIX_ENABLED) ? 24 : 20) 3125500d4bSJay Zhou 322c449644SFerruh Yigit struct virtio_hw_internal crypto_virtio_hw_internal[RTE_MAX_VIRTIO_CRYPTO]; 3325500d4bSJay Zhou 3425500d4bSJay Zhou static inline int 3525500d4bSJay Zhou check_vq_phys_addr_ok(struct virtqueue *vq) 3625500d4bSJay Zhou { 3725500d4bSJay Zhou /* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, 3825500d4bSJay Zhou * and only accepts 32 bit page frame number. 3925500d4bSJay Zhou * Check if the allocated physical memory exceeds 16TB. 4025500d4bSJay Zhou */ 4125500d4bSJay Zhou if ((vq->vq_ring_mem + vq->vq_ring_size - 1) >> 4225500d4bSJay Zhou (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { 4325500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be above 16TB!"); 4425500d4bSJay Zhou return 0; 4525500d4bSJay Zhou } 4625500d4bSJay Zhou 4725500d4bSJay Zhou return 1; 4825500d4bSJay Zhou } 4925500d4bSJay Zhou 5025500d4bSJay Zhou static inline void 5125500d4bSJay Zhou io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi) 5225500d4bSJay Zhou { 5325500d4bSJay Zhou rte_write32(val & ((1ULL << 32) - 1), lo); 5425500d4bSJay Zhou rte_write32(val >> 32, hi); 5525500d4bSJay Zhou } 5625500d4bSJay Zhou 5725500d4bSJay Zhou static void 5825500d4bSJay Zhou modern_read_dev_config(struct virtio_crypto_hw *hw, size_t offset, 5925500d4bSJay Zhou void *dst, int length) 6025500d4bSJay Zhou { 6125500d4bSJay Zhou int i; 6225500d4bSJay Zhou uint8_t *p; 6325500d4bSJay Zhou uint8_t old_gen, new_gen; 6425500d4bSJay Zhou 6525500d4bSJay Zhou do { 6625500d4bSJay Zhou old_gen = rte_read8(&hw->common_cfg->config_generation); 6725500d4bSJay Zhou 6825500d4bSJay Zhou p = dst; 6925500d4bSJay Zhou for (i = 0; i < length; i++) 7025500d4bSJay Zhou *p++ = rte_read8((uint8_t *)hw->dev_cfg + offset + i); 7125500d4bSJay Zhou 7225500d4bSJay Zhou new_gen = rte_read8(&hw->common_cfg->config_generation); 7325500d4bSJay Zhou } while (old_gen != new_gen); 7425500d4bSJay Zhou } 7525500d4bSJay Zhou 7625500d4bSJay Zhou static void 7725500d4bSJay Zhou modern_write_dev_config(struct virtio_crypto_hw *hw, size_t offset, 7825500d4bSJay Zhou const void *src, int length) 7925500d4bSJay Zhou { 8025500d4bSJay Zhou int i; 8125500d4bSJay Zhou const uint8_t *p = src; 8225500d4bSJay Zhou 8325500d4bSJay Zhou for (i = 0; i < length; i++) 8425500d4bSJay Zhou rte_write8((*p++), (((uint8_t *)hw->dev_cfg) + offset + i)); 8525500d4bSJay Zhou } 8625500d4bSJay Zhou 8725500d4bSJay Zhou static uint64_t 8825500d4bSJay Zhou modern_get_features(struct virtio_crypto_hw *hw) 8925500d4bSJay Zhou { 9025500d4bSJay Zhou uint32_t features_lo, features_hi; 9125500d4bSJay Zhou 9225500d4bSJay Zhou rte_write32(0, &hw->common_cfg->device_feature_select); 9325500d4bSJay Zhou features_lo = rte_read32(&hw->common_cfg->device_feature); 9425500d4bSJay Zhou 9525500d4bSJay Zhou rte_write32(1, &hw->common_cfg->device_feature_select); 9625500d4bSJay Zhou features_hi = rte_read32(&hw->common_cfg->device_feature); 9725500d4bSJay Zhou 9825500d4bSJay Zhou return ((uint64_t)features_hi << 32) | features_lo; 9925500d4bSJay Zhou } 10025500d4bSJay Zhou 10125500d4bSJay Zhou static void 10225500d4bSJay Zhou modern_set_features(struct virtio_crypto_hw *hw, uint64_t features) 10325500d4bSJay Zhou { 10425500d4bSJay Zhou rte_write32(0, &hw->common_cfg->guest_feature_select); 10525500d4bSJay Zhou rte_write32(features & ((1ULL << 32) - 1), 10625500d4bSJay Zhou &hw->common_cfg->guest_feature); 10725500d4bSJay Zhou 10825500d4bSJay Zhou rte_write32(1, &hw->common_cfg->guest_feature_select); 10925500d4bSJay Zhou rte_write32(features >> 32, 11025500d4bSJay Zhou &hw->common_cfg->guest_feature); 11125500d4bSJay Zhou } 11225500d4bSJay Zhou 11325500d4bSJay Zhou static uint8_t 11425500d4bSJay Zhou modern_get_status(struct virtio_crypto_hw *hw) 11525500d4bSJay Zhou { 11625500d4bSJay Zhou return rte_read8(&hw->common_cfg->device_status); 11725500d4bSJay Zhou } 11825500d4bSJay Zhou 11925500d4bSJay Zhou static void 12025500d4bSJay Zhou modern_set_status(struct virtio_crypto_hw *hw, uint8_t status) 12125500d4bSJay Zhou { 12225500d4bSJay Zhou rte_write8(status, &hw->common_cfg->device_status); 12325500d4bSJay Zhou } 12425500d4bSJay Zhou 12525500d4bSJay Zhou static void 12625500d4bSJay Zhou modern_reset(struct virtio_crypto_hw *hw) 12725500d4bSJay Zhou { 12825500d4bSJay Zhou modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET); 12925500d4bSJay Zhou modern_get_status(hw); 13025500d4bSJay Zhou } 13125500d4bSJay Zhou 13225500d4bSJay Zhou static uint8_t 13325500d4bSJay Zhou modern_get_isr(struct virtio_crypto_hw *hw) 13425500d4bSJay Zhou { 13525500d4bSJay Zhou return rte_read8(hw->isr); 13625500d4bSJay Zhou } 13725500d4bSJay Zhou 13825500d4bSJay Zhou static uint16_t 13925500d4bSJay Zhou modern_set_config_irq(struct virtio_crypto_hw *hw, uint16_t vec) 14025500d4bSJay Zhou { 14125500d4bSJay Zhou rte_write16(vec, &hw->common_cfg->msix_config); 14225500d4bSJay Zhou return rte_read16(&hw->common_cfg->msix_config); 14325500d4bSJay Zhou } 14425500d4bSJay Zhou 14525500d4bSJay Zhou static uint16_t 14625500d4bSJay Zhou modern_set_queue_irq(struct virtio_crypto_hw *hw, struct virtqueue *vq, 14725500d4bSJay Zhou uint16_t vec) 14825500d4bSJay Zhou { 14925500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 15025500d4bSJay Zhou rte_write16(vec, &hw->common_cfg->queue_msix_vector); 15125500d4bSJay Zhou return rte_read16(&hw->common_cfg->queue_msix_vector); 15225500d4bSJay Zhou } 15325500d4bSJay Zhou 15425500d4bSJay Zhou static uint16_t 15525500d4bSJay Zhou modern_get_queue_num(struct virtio_crypto_hw *hw, uint16_t queue_id) 15625500d4bSJay Zhou { 15725500d4bSJay Zhou rte_write16(queue_id, &hw->common_cfg->queue_select); 15825500d4bSJay Zhou return rte_read16(&hw->common_cfg->queue_size); 15925500d4bSJay Zhou } 16025500d4bSJay Zhou 16125500d4bSJay Zhou static int 16225500d4bSJay Zhou modern_setup_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq) 16325500d4bSJay Zhou { 16425500d4bSJay Zhou uint64_t desc_addr, avail_addr, used_addr; 16525500d4bSJay Zhou uint16_t notify_off; 16625500d4bSJay Zhou 16725500d4bSJay Zhou if (!check_vq_phys_addr_ok(vq)) 16825500d4bSJay Zhou return -1; 16925500d4bSJay Zhou 17025500d4bSJay Zhou desc_addr = vq->vq_ring_mem; 17125500d4bSJay Zhou avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc); 17225500d4bSJay Zhou used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail, 17325500d4bSJay Zhou ring[vq->vq_nentries]), 17425500d4bSJay Zhou VIRTIO_PCI_VRING_ALIGN); 17525500d4bSJay Zhou 17625500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 17725500d4bSJay Zhou 17825500d4bSJay Zhou io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo, 17925500d4bSJay Zhou &hw->common_cfg->queue_desc_hi); 18025500d4bSJay Zhou io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo, 18125500d4bSJay Zhou &hw->common_cfg->queue_avail_hi); 18225500d4bSJay Zhou io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo, 18325500d4bSJay Zhou &hw->common_cfg->queue_used_hi); 18425500d4bSJay Zhou 18525500d4bSJay Zhou notify_off = rte_read16(&hw->common_cfg->queue_notify_off); 18625500d4bSJay Zhou vq->notify_addr = (void *)((uint8_t *)hw->notify_base + 18725500d4bSJay Zhou notify_off * hw->notify_off_multiplier); 18825500d4bSJay Zhou 18925500d4bSJay Zhou rte_write16(1, &hw->common_cfg->queue_enable); 19025500d4bSJay Zhou 19125500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("queue %u addresses:", vq->vq_queue_index); 19225500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t desc_addr: %" PRIx64, desc_addr); 19325500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t aval_addr: %" PRIx64, avail_addr); 19425500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t used_addr: %" PRIx64, used_addr); 19525500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t notify addr: %p (notify offset: %u)", 19625500d4bSJay Zhou vq->notify_addr, notify_off); 19725500d4bSJay Zhou 19825500d4bSJay Zhou return 0; 19925500d4bSJay Zhou } 20025500d4bSJay Zhou 20125500d4bSJay Zhou static void 20225500d4bSJay Zhou modern_del_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq) 20325500d4bSJay Zhou { 20425500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 20525500d4bSJay Zhou 20625500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_desc_lo, 20725500d4bSJay Zhou &hw->common_cfg->queue_desc_hi); 20825500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_avail_lo, 20925500d4bSJay Zhou &hw->common_cfg->queue_avail_hi); 21025500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_used_lo, 21125500d4bSJay Zhou &hw->common_cfg->queue_used_hi); 21225500d4bSJay Zhou 21325500d4bSJay Zhou rte_write16(0, &hw->common_cfg->queue_enable); 21425500d4bSJay Zhou } 21525500d4bSJay Zhou 21625500d4bSJay Zhou static void 21725500d4bSJay Zhou modern_notify_queue(struct virtio_crypto_hw *hw __rte_unused, 21825500d4bSJay Zhou struct virtqueue *vq) 21925500d4bSJay Zhou { 22025500d4bSJay Zhou rte_write16(vq->vq_queue_index, vq->notify_addr); 22125500d4bSJay Zhou } 22225500d4bSJay Zhou 22325500d4bSJay Zhou const struct virtio_pci_ops virtio_crypto_modern_ops = { 22425500d4bSJay Zhou .read_dev_cfg = modern_read_dev_config, 22525500d4bSJay Zhou .write_dev_cfg = modern_write_dev_config, 22625500d4bSJay Zhou .reset = modern_reset, 22725500d4bSJay Zhou .get_status = modern_get_status, 22825500d4bSJay Zhou .set_status = modern_set_status, 22925500d4bSJay Zhou .get_features = modern_get_features, 23025500d4bSJay Zhou .set_features = modern_set_features, 23125500d4bSJay Zhou .get_isr = modern_get_isr, 23225500d4bSJay Zhou .set_config_irq = modern_set_config_irq, 23325500d4bSJay Zhou .set_queue_irq = modern_set_queue_irq, 23425500d4bSJay Zhou .get_queue_num = modern_get_queue_num, 23525500d4bSJay Zhou .setup_queue = modern_setup_queue, 23625500d4bSJay Zhou .del_queue = modern_del_queue, 23725500d4bSJay Zhou .notify_queue = modern_notify_queue, 23825500d4bSJay Zhou }; 23925500d4bSJay Zhou 24025500d4bSJay Zhou void 24125500d4bSJay Zhou vtpci_read_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset, 24225500d4bSJay Zhou void *dst, int length) 24325500d4bSJay Zhou { 24425500d4bSJay Zhou VTPCI_OPS(hw)->read_dev_cfg(hw, offset, dst, length); 24525500d4bSJay Zhou } 24625500d4bSJay Zhou 24725500d4bSJay Zhou void 24825500d4bSJay Zhou vtpci_write_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset, 24925500d4bSJay Zhou const void *src, int length) 25025500d4bSJay Zhou { 25125500d4bSJay Zhou VTPCI_OPS(hw)->write_dev_cfg(hw, offset, src, length); 25225500d4bSJay Zhou } 25325500d4bSJay Zhou 25425500d4bSJay Zhou uint64_t 25525500d4bSJay Zhou vtpci_cryptodev_negotiate_features(struct virtio_crypto_hw *hw, 25625500d4bSJay Zhou uint64_t host_features) 25725500d4bSJay Zhou { 25825500d4bSJay Zhou uint64_t features; 25925500d4bSJay Zhou 26025500d4bSJay Zhou /* 26125500d4bSJay Zhou * Limit negotiated features to what the driver, virtqueue, and 26225500d4bSJay Zhou * host all support. 26325500d4bSJay Zhou */ 26425500d4bSJay Zhou features = host_features & hw->guest_features; 26525500d4bSJay Zhou VTPCI_OPS(hw)->set_features(hw, features); 26625500d4bSJay Zhou 26725500d4bSJay Zhou return features; 26825500d4bSJay Zhou } 26925500d4bSJay Zhou 27025500d4bSJay Zhou void 27125500d4bSJay Zhou vtpci_cryptodev_reset(struct virtio_crypto_hw *hw) 27225500d4bSJay Zhou { 27325500d4bSJay Zhou VTPCI_OPS(hw)->set_status(hw, VIRTIO_CONFIG_STATUS_RESET); 27425500d4bSJay Zhou /* flush status write */ 27525500d4bSJay Zhou VTPCI_OPS(hw)->get_status(hw); 27625500d4bSJay Zhou } 27725500d4bSJay Zhou 27825500d4bSJay Zhou void 27925500d4bSJay Zhou vtpci_cryptodev_reinit_complete(struct virtio_crypto_hw *hw) 28025500d4bSJay Zhou { 28125500d4bSJay Zhou vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); 28225500d4bSJay Zhou } 28325500d4bSJay Zhou 28425500d4bSJay Zhou void 28525500d4bSJay Zhou vtpci_cryptodev_set_status(struct virtio_crypto_hw *hw, uint8_t status) 28625500d4bSJay Zhou { 28725500d4bSJay Zhou if (status != VIRTIO_CONFIG_STATUS_RESET) 28825500d4bSJay Zhou status |= VTPCI_OPS(hw)->get_status(hw); 28925500d4bSJay Zhou 29025500d4bSJay Zhou VTPCI_OPS(hw)->set_status(hw, status); 29125500d4bSJay Zhou } 29225500d4bSJay Zhou 29325500d4bSJay Zhou uint8_t 29425500d4bSJay Zhou vtpci_cryptodev_get_status(struct virtio_crypto_hw *hw) 29525500d4bSJay Zhou { 29625500d4bSJay Zhou return VTPCI_OPS(hw)->get_status(hw); 29725500d4bSJay Zhou } 29825500d4bSJay Zhou 29925500d4bSJay Zhou uint8_t 30025500d4bSJay Zhou vtpci_cryptodev_isr(struct virtio_crypto_hw *hw) 30125500d4bSJay Zhou { 30225500d4bSJay Zhou return VTPCI_OPS(hw)->get_isr(hw); 30325500d4bSJay Zhou } 30425500d4bSJay Zhou 30525500d4bSJay Zhou static void * 30625500d4bSJay Zhou get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap) 30725500d4bSJay Zhou { 30825500d4bSJay Zhou uint8_t bar = cap->bar; 30925500d4bSJay Zhou uint32_t length = cap->length; 31025500d4bSJay Zhou uint32_t offset = cap->offset; 31125500d4bSJay Zhou uint8_t *base; 31225500d4bSJay Zhou 31325500d4bSJay Zhou if (bar >= PCI_MAX_RESOURCE) { 31425500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("invalid bar: %u", bar); 31525500d4bSJay Zhou return NULL; 31625500d4bSJay Zhou } 31725500d4bSJay Zhou 31825500d4bSJay Zhou if (offset + length < offset) { 31925500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("offset(%u) + length(%u) overflows", 32025500d4bSJay Zhou offset, length); 32125500d4bSJay Zhou return NULL; 32225500d4bSJay Zhou } 32325500d4bSJay Zhou 32425500d4bSJay Zhou if (offset + length > dev->mem_resource[bar].len) { 32525500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR( 32625500d4bSJay Zhou "invalid cap: overflows bar space: %u > %" PRIu64, 32725500d4bSJay Zhou offset + length, dev->mem_resource[bar].len); 32825500d4bSJay Zhou return NULL; 32925500d4bSJay Zhou } 33025500d4bSJay Zhou 33125500d4bSJay Zhou base = dev->mem_resource[bar].addr; 33225500d4bSJay Zhou if (base == NULL) { 33325500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("bar %u base addr is NULL", bar); 33425500d4bSJay Zhou return NULL; 33525500d4bSJay Zhou } 33625500d4bSJay Zhou 33725500d4bSJay Zhou return base + offset; 33825500d4bSJay Zhou } 33925500d4bSJay Zhou 34025500d4bSJay Zhou #define PCI_MSIX_ENABLE 0x8000 34125500d4bSJay Zhou 34225500d4bSJay Zhou static int 34325500d4bSJay Zhou virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) 34425500d4bSJay Zhou { 34525500d4bSJay Zhou struct virtio_pci_cap cap; 346*a10b6e53SDavid Marchand uint16_t flags; 347*a10b6e53SDavid Marchand off_t pos; 34825500d4bSJay Zhou int ret; 34925500d4bSJay Zhou 35025500d4bSJay Zhou if (rte_pci_map_device(dev)) { 35125500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("failed to map pci device!"); 35225500d4bSJay Zhou return -1; 35325500d4bSJay Zhou } 35425500d4bSJay Zhou 355*a10b6e53SDavid Marchand /* 356*a10b6e53SDavid Marchand * Transitional devices would also have this capability, 35725500d4bSJay Zhou * that's why we also check if msix is enabled. 35825500d4bSJay Zhou */ 359*a10b6e53SDavid Marchand pos = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX); 360*a10b6e53SDavid Marchand if (pos > 0 && rte_pci_read_config(dev, &flags, sizeof(flags), 361*a10b6e53SDavid Marchand pos + 2) == sizeof(flags)) { 36225500d4bSJay Zhou if (flags & PCI_MSIX_ENABLE) 36325500d4bSJay Zhou hw->use_msix = VIRTIO_MSIX_ENABLED; 36425500d4bSJay Zhou else 36525500d4bSJay Zhou hw->use_msix = VIRTIO_MSIX_DISABLED; 366*a10b6e53SDavid Marchand } else { 367*a10b6e53SDavid Marchand hw->use_msix = VIRTIO_MSIX_NONE; 36825500d4bSJay Zhou } 36925500d4bSJay Zhou 370*a10b6e53SDavid Marchand pos = rte_pci_find_capability(dev, PCI_CAP_ID_VNDR); 371*a10b6e53SDavid Marchand while (pos > 0) { 372*a10b6e53SDavid Marchand if (rte_pci_read_config(dev, &cap, sizeof(cap), pos) != sizeof(cap)) 373*a10b6e53SDavid Marchand break; 37425500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG( 37525500d4bSJay Zhou "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u", 376*a10b6e53SDavid Marchand (unsigned int)pos, cap.cfg_type, cap.bar, cap.offset, cap.length); 37725500d4bSJay Zhou 37825500d4bSJay Zhou switch (cap.cfg_type) { 37925500d4bSJay Zhou case VIRTIO_PCI_CAP_COMMON_CFG: 38025500d4bSJay Zhou hw->common_cfg = get_cfg_addr(dev, &cap); 38125500d4bSJay Zhou break; 38225500d4bSJay Zhou case VIRTIO_PCI_CAP_NOTIFY_CFG: 383691733e7SChenbo Xia ret = rte_pci_read_config(dev, &hw->notify_off_multiplier, 38425500d4bSJay Zhou 4, pos + sizeof(cap)); 385691733e7SChenbo Xia if (ret != 4) 386691733e7SChenbo Xia VIRTIO_CRYPTO_INIT_LOG_ERR( 387691733e7SChenbo Xia "failed to read notify_off_multiplier: ret %d", ret); 388691733e7SChenbo Xia else 38925500d4bSJay Zhou hw->notify_base = get_cfg_addr(dev, &cap); 39025500d4bSJay Zhou break; 39125500d4bSJay Zhou case VIRTIO_PCI_CAP_DEVICE_CFG: 39225500d4bSJay Zhou hw->dev_cfg = get_cfg_addr(dev, &cap); 39325500d4bSJay Zhou break; 39425500d4bSJay Zhou case VIRTIO_PCI_CAP_ISR_CFG: 39525500d4bSJay Zhou hw->isr = get_cfg_addr(dev, &cap); 39625500d4bSJay Zhou break; 39725500d4bSJay Zhou } 39825500d4bSJay Zhou 399*a10b6e53SDavid Marchand pos = rte_pci_find_next_capability(dev, PCI_CAP_ID_VNDR, pos); 40025500d4bSJay Zhou } 40125500d4bSJay Zhou 40225500d4bSJay Zhou if (hw->common_cfg == NULL || hw->notify_base == NULL || 40325500d4bSJay Zhou hw->dev_cfg == NULL || hw->isr == NULL) { 40425500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("no modern virtio pci device found."); 40525500d4bSJay Zhou return -1; 40625500d4bSJay Zhou } 40725500d4bSJay Zhou 40825500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("found modern virtio pci device."); 40925500d4bSJay Zhou 41025500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("common cfg mapped at: %p", hw->common_cfg); 41125500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("device cfg mapped at: %p", hw->dev_cfg); 41225500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("isr cfg mapped at: %p", hw->isr); 41325500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("notify base: %p, notify off multiplier: %u", 41425500d4bSJay Zhou hw->notify_base, hw->notify_off_multiplier); 41525500d4bSJay Zhou 41625500d4bSJay Zhou return 0; 41725500d4bSJay Zhou } 41825500d4bSJay Zhou 41925500d4bSJay Zhou /* 42025500d4bSJay Zhou * Return -1: 42125500d4bSJay Zhou * if there is error mapping with VFIO/UIO. 42225500d4bSJay Zhou * if port map error when driver type is KDRV_NONE. 423a65a34a8SStephen Hemminger * if marked as allowed but driver type is KDRV_UNKNOWN. 42425500d4bSJay Zhou * Return 1 if kernel driver is managing the device. 42525500d4bSJay Zhou * Return 0 on success. 42625500d4bSJay Zhou */ 42725500d4bSJay Zhou int 42825500d4bSJay Zhou vtpci_cryptodev_init(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) 42925500d4bSJay Zhou { 43025500d4bSJay Zhou /* 43125500d4bSJay Zhou * Try if we can succeed reading virtio pci caps, which exists 43225500d4bSJay Zhou * only on modern pci device. If failed, we fallback to legacy 43325500d4bSJay Zhou * virtio handling. 43425500d4bSJay Zhou */ 43525500d4bSJay Zhou if (virtio_read_caps(dev, hw) == 0) { 43625500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("modern virtio pci detected."); 4372c449644SFerruh Yigit crypto_virtio_hw_internal[hw->dev_id].vtpci_ops = 43825500d4bSJay Zhou &virtio_crypto_modern_ops; 43925500d4bSJay Zhou hw->modern = 1; 44025500d4bSJay Zhou return 0; 44125500d4bSJay Zhou } 44225500d4bSJay Zhou 44325500d4bSJay Zhou /* 44425500d4bSJay Zhou * virtio crypto conforms to virtio 1.0 and doesn't support 44525500d4bSJay Zhou * legacy mode 44625500d4bSJay Zhou */ 44725500d4bSJay Zhou return -1; 44825500d4bSJay Zhou } 449