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