1*25500d4bSJay Zhou /* SPDX-License-Identifier: BSD-3-Clause 2*25500d4bSJay Zhou * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD. 3*25500d4bSJay Zhou */ 4*25500d4bSJay Zhou 5*25500d4bSJay Zhou #include <stdint.h> 6*25500d4bSJay Zhou 7*25500d4bSJay Zhou #ifdef RTE_EXEC_ENV_LINUXAPP 8*25500d4bSJay Zhou #include <dirent.h> 9*25500d4bSJay Zhou #include <fcntl.h> 10*25500d4bSJay Zhou #endif 11*25500d4bSJay Zhou 12*25500d4bSJay Zhou #include <rte_io.h> 13*25500d4bSJay Zhou #include <rte_bus.h> 14*25500d4bSJay Zhou 15*25500d4bSJay Zhou #include "virtio_pci.h" 16*25500d4bSJay Zhou #include "virtqueue.h" 17*25500d4bSJay Zhou 18*25500d4bSJay Zhou /* 19*25500d4bSJay Zhou * Following macros are derived from linux/pci_regs.h, however, 20*25500d4bSJay Zhou * we can't simply include that header here, as there is no such 21*25500d4bSJay Zhou * file for non-Linux platform. 22*25500d4bSJay Zhou */ 23*25500d4bSJay Zhou #define PCI_CAPABILITY_LIST 0x34 24*25500d4bSJay Zhou #define PCI_CAP_ID_VNDR 0x09 25*25500d4bSJay Zhou #define PCI_CAP_ID_MSIX 0x11 26*25500d4bSJay Zhou 27*25500d4bSJay Zhou /* 28*25500d4bSJay Zhou * The remaining space is defined by each driver as the per-driver 29*25500d4bSJay Zhou * configuration space. 30*25500d4bSJay Zhou */ 31*25500d4bSJay Zhou #define VIRTIO_PCI_CONFIG(hw) \ 32*25500d4bSJay Zhou (((hw)->use_msix == VIRTIO_MSIX_ENABLED) ? 24 : 20) 33*25500d4bSJay Zhou 34*25500d4bSJay Zhou struct virtio_hw_internal virtio_hw_internal[RTE_MAX_VIRTIO_CRYPTO]; 35*25500d4bSJay Zhou 36*25500d4bSJay Zhou static inline int 37*25500d4bSJay Zhou check_vq_phys_addr_ok(struct virtqueue *vq) 38*25500d4bSJay Zhou { 39*25500d4bSJay Zhou /* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, 40*25500d4bSJay Zhou * and only accepts 32 bit page frame number. 41*25500d4bSJay Zhou * Check if the allocated physical memory exceeds 16TB. 42*25500d4bSJay Zhou */ 43*25500d4bSJay Zhou if ((vq->vq_ring_mem + vq->vq_ring_size - 1) >> 44*25500d4bSJay Zhou (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { 45*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be above 16TB!"); 46*25500d4bSJay Zhou return 0; 47*25500d4bSJay Zhou } 48*25500d4bSJay Zhou 49*25500d4bSJay Zhou return 1; 50*25500d4bSJay Zhou } 51*25500d4bSJay Zhou 52*25500d4bSJay Zhou static inline void 53*25500d4bSJay Zhou io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi) 54*25500d4bSJay Zhou { 55*25500d4bSJay Zhou rte_write32(val & ((1ULL << 32) - 1), lo); 56*25500d4bSJay Zhou rte_write32(val >> 32, hi); 57*25500d4bSJay Zhou } 58*25500d4bSJay Zhou 59*25500d4bSJay Zhou static void 60*25500d4bSJay Zhou modern_read_dev_config(struct virtio_crypto_hw *hw, size_t offset, 61*25500d4bSJay Zhou void *dst, int length) 62*25500d4bSJay Zhou { 63*25500d4bSJay Zhou int i; 64*25500d4bSJay Zhou uint8_t *p; 65*25500d4bSJay Zhou uint8_t old_gen, new_gen; 66*25500d4bSJay Zhou 67*25500d4bSJay Zhou do { 68*25500d4bSJay Zhou old_gen = rte_read8(&hw->common_cfg->config_generation); 69*25500d4bSJay Zhou 70*25500d4bSJay Zhou p = dst; 71*25500d4bSJay Zhou for (i = 0; i < length; i++) 72*25500d4bSJay Zhou *p++ = rte_read8((uint8_t *)hw->dev_cfg + offset + i); 73*25500d4bSJay Zhou 74*25500d4bSJay Zhou new_gen = rte_read8(&hw->common_cfg->config_generation); 75*25500d4bSJay Zhou } while (old_gen != new_gen); 76*25500d4bSJay Zhou } 77*25500d4bSJay Zhou 78*25500d4bSJay Zhou static void 79*25500d4bSJay Zhou modern_write_dev_config(struct virtio_crypto_hw *hw, size_t offset, 80*25500d4bSJay Zhou const void *src, int length) 81*25500d4bSJay Zhou { 82*25500d4bSJay Zhou int i; 83*25500d4bSJay Zhou const uint8_t *p = src; 84*25500d4bSJay Zhou 85*25500d4bSJay Zhou for (i = 0; i < length; i++) 86*25500d4bSJay Zhou rte_write8((*p++), (((uint8_t *)hw->dev_cfg) + offset + i)); 87*25500d4bSJay Zhou } 88*25500d4bSJay Zhou 89*25500d4bSJay Zhou static uint64_t 90*25500d4bSJay Zhou modern_get_features(struct virtio_crypto_hw *hw) 91*25500d4bSJay Zhou { 92*25500d4bSJay Zhou uint32_t features_lo, features_hi; 93*25500d4bSJay Zhou 94*25500d4bSJay Zhou rte_write32(0, &hw->common_cfg->device_feature_select); 95*25500d4bSJay Zhou features_lo = rte_read32(&hw->common_cfg->device_feature); 96*25500d4bSJay Zhou 97*25500d4bSJay Zhou rte_write32(1, &hw->common_cfg->device_feature_select); 98*25500d4bSJay Zhou features_hi = rte_read32(&hw->common_cfg->device_feature); 99*25500d4bSJay Zhou 100*25500d4bSJay Zhou return ((uint64_t)features_hi << 32) | features_lo; 101*25500d4bSJay Zhou } 102*25500d4bSJay Zhou 103*25500d4bSJay Zhou static void 104*25500d4bSJay Zhou modern_set_features(struct virtio_crypto_hw *hw, uint64_t features) 105*25500d4bSJay Zhou { 106*25500d4bSJay Zhou rte_write32(0, &hw->common_cfg->guest_feature_select); 107*25500d4bSJay Zhou rte_write32(features & ((1ULL << 32) - 1), 108*25500d4bSJay Zhou &hw->common_cfg->guest_feature); 109*25500d4bSJay Zhou 110*25500d4bSJay Zhou rte_write32(1, &hw->common_cfg->guest_feature_select); 111*25500d4bSJay Zhou rte_write32(features >> 32, 112*25500d4bSJay Zhou &hw->common_cfg->guest_feature); 113*25500d4bSJay Zhou } 114*25500d4bSJay Zhou 115*25500d4bSJay Zhou static uint8_t 116*25500d4bSJay Zhou modern_get_status(struct virtio_crypto_hw *hw) 117*25500d4bSJay Zhou { 118*25500d4bSJay Zhou return rte_read8(&hw->common_cfg->device_status); 119*25500d4bSJay Zhou } 120*25500d4bSJay Zhou 121*25500d4bSJay Zhou static void 122*25500d4bSJay Zhou modern_set_status(struct virtio_crypto_hw *hw, uint8_t status) 123*25500d4bSJay Zhou { 124*25500d4bSJay Zhou rte_write8(status, &hw->common_cfg->device_status); 125*25500d4bSJay Zhou } 126*25500d4bSJay Zhou 127*25500d4bSJay Zhou static void 128*25500d4bSJay Zhou modern_reset(struct virtio_crypto_hw *hw) 129*25500d4bSJay Zhou { 130*25500d4bSJay Zhou modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET); 131*25500d4bSJay Zhou modern_get_status(hw); 132*25500d4bSJay Zhou } 133*25500d4bSJay Zhou 134*25500d4bSJay Zhou static uint8_t 135*25500d4bSJay Zhou modern_get_isr(struct virtio_crypto_hw *hw) 136*25500d4bSJay Zhou { 137*25500d4bSJay Zhou return rte_read8(hw->isr); 138*25500d4bSJay Zhou } 139*25500d4bSJay Zhou 140*25500d4bSJay Zhou static uint16_t 141*25500d4bSJay Zhou modern_set_config_irq(struct virtio_crypto_hw *hw, uint16_t vec) 142*25500d4bSJay Zhou { 143*25500d4bSJay Zhou rte_write16(vec, &hw->common_cfg->msix_config); 144*25500d4bSJay Zhou return rte_read16(&hw->common_cfg->msix_config); 145*25500d4bSJay Zhou } 146*25500d4bSJay Zhou 147*25500d4bSJay Zhou static uint16_t 148*25500d4bSJay Zhou modern_set_queue_irq(struct virtio_crypto_hw *hw, struct virtqueue *vq, 149*25500d4bSJay Zhou uint16_t vec) 150*25500d4bSJay Zhou { 151*25500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 152*25500d4bSJay Zhou rte_write16(vec, &hw->common_cfg->queue_msix_vector); 153*25500d4bSJay Zhou return rte_read16(&hw->common_cfg->queue_msix_vector); 154*25500d4bSJay Zhou } 155*25500d4bSJay Zhou 156*25500d4bSJay Zhou static uint16_t 157*25500d4bSJay Zhou modern_get_queue_num(struct virtio_crypto_hw *hw, uint16_t queue_id) 158*25500d4bSJay Zhou { 159*25500d4bSJay Zhou rte_write16(queue_id, &hw->common_cfg->queue_select); 160*25500d4bSJay Zhou return rte_read16(&hw->common_cfg->queue_size); 161*25500d4bSJay Zhou } 162*25500d4bSJay Zhou 163*25500d4bSJay Zhou static int 164*25500d4bSJay Zhou modern_setup_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq) 165*25500d4bSJay Zhou { 166*25500d4bSJay Zhou uint64_t desc_addr, avail_addr, used_addr; 167*25500d4bSJay Zhou uint16_t notify_off; 168*25500d4bSJay Zhou 169*25500d4bSJay Zhou if (!check_vq_phys_addr_ok(vq)) 170*25500d4bSJay Zhou return -1; 171*25500d4bSJay Zhou 172*25500d4bSJay Zhou desc_addr = vq->vq_ring_mem; 173*25500d4bSJay Zhou avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc); 174*25500d4bSJay Zhou used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail, 175*25500d4bSJay Zhou ring[vq->vq_nentries]), 176*25500d4bSJay Zhou VIRTIO_PCI_VRING_ALIGN); 177*25500d4bSJay Zhou 178*25500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 179*25500d4bSJay Zhou 180*25500d4bSJay Zhou io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo, 181*25500d4bSJay Zhou &hw->common_cfg->queue_desc_hi); 182*25500d4bSJay Zhou io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo, 183*25500d4bSJay Zhou &hw->common_cfg->queue_avail_hi); 184*25500d4bSJay Zhou io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo, 185*25500d4bSJay Zhou &hw->common_cfg->queue_used_hi); 186*25500d4bSJay Zhou 187*25500d4bSJay Zhou notify_off = rte_read16(&hw->common_cfg->queue_notify_off); 188*25500d4bSJay Zhou vq->notify_addr = (void *)((uint8_t *)hw->notify_base + 189*25500d4bSJay Zhou notify_off * hw->notify_off_multiplier); 190*25500d4bSJay Zhou 191*25500d4bSJay Zhou rte_write16(1, &hw->common_cfg->queue_enable); 192*25500d4bSJay Zhou 193*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("queue %u addresses:", vq->vq_queue_index); 194*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t desc_addr: %" PRIx64, desc_addr); 195*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t aval_addr: %" PRIx64, avail_addr); 196*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t used_addr: %" PRIx64, used_addr); 197*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("\t notify addr: %p (notify offset: %u)", 198*25500d4bSJay Zhou vq->notify_addr, notify_off); 199*25500d4bSJay Zhou 200*25500d4bSJay Zhou return 0; 201*25500d4bSJay Zhou } 202*25500d4bSJay Zhou 203*25500d4bSJay Zhou static void 204*25500d4bSJay Zhou modern_del_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq) 205*25500d4bSJay Zhou { 206*25500d4bSJay Zhou rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); 207*25500d4bSJay Zhou 208*25500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_desc_lo, 209*25500d4bSJay Zhou &hw->common_cfg->queue_desc_hi); 210*25500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_avail_lo, 211*25500d4bSJay Zhou &hw->common_cfg->queue_avail_hi); 212*25500d4bSJay Zhou io_write64_twopart(0, &hw->common_cfg->queue_used_lo, 213*25500d4bSJay Zhou &hw->common_cfg->queue_used_hi); 214*25500d4bSJay Zhou 215*25500d4bSJay Zhou rte_write16(0, &hw->common_cfg->queue_enable); 216*25500d4bSJay Zhou } 217*25500d4bSJay Zhou 218*25500d4bSJay Zhou static void 219*25500d4bSJay Zhou modern_notify_queue(struct virtio_crypto_hw *hw __rte_unused, 220*25500d4bSJay Zhou struct virtqueue *vq) 221*25500d4bSJay Zhou { 222*25500d4bSJay Zhou rte_write16(vq->vq_queue_index, vq->notify_addr); 223*25500d4bSJay Zhou } 224*25500d4bSJay Zhou 225*25500d4bSJay Zhou const struct virtio_pci_ops virtio_crypto_modern_ops = { 226*25500d4bSJay Zhou .read_dev_cfg = modern_read_dev_config, 227*25500d4bSJay Zhou .write_dev_cfg = modern_write_dev_config, 228*25500d4bSJay Zhou .reset = modern_reset, 229*25500d4bSJay Zhou .get_status = modern_get_status, 230*25500d4bSJay Zhou .set_status = modern_set_status, 231*25500d4bSJay Zhou .get_features = modern_get_features, 232*25500d4bSJay Zhou .set_features = modern_set_features, 233*25500d4bSJay Zhou .get_isr = modern_get_isr, 234*25500d4bSJay Zhou .set_config_irq = modern_set_config_irq, 235*25500d4bSJay Zhou .set_queue_irq = modern_set_queue_irq, 236*25500d4bSJay Zhou .get_queue_num = modern_get_queue_num, 237*25500d4bSJay Zhou .setup_queue = modern_setup_queue, 238*25500d4bSJay Zhou .del_queue = modern_del_queue, 239*25500d4bSJay Zhou .notify_queue = modern_notify_queue, 240*25500d4bSJay Zhou }; 241*25500d4bSJay Zhou 242*25500d4bSJay Zhou void 243*25500d4bSJay Zhou vtpci_read_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset, 244*25500d4bSJay Zhou void *dst, int length) 245*25500d4bSJay Zhou { 246*25500d4bSJay Zhou VTPCI_OPS(hw)->read_dev_cfg(hw, offset, dst, length); 247*25500d4bSJay Zhou } 248*25500d4bSJay Zhou 249*25500d4bSJay Zhou void 250*25500d4bSJay Zhou vtpci_write_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset, 251*25500d4bSJay Zhou const void *src, int length) 252*25500d4bSJay Zhou { 253*25500d4bSJay Zhou VTPCI_OPS(hw)->write_dev_cfg(hw, offset, src, length); 254*25500d4bSJay Zhou } 255*25500d4bSJay Zhou 256*25500d4bSJay Zhou uint64_t 257*25500d4bSJay Zhou vtpci_cryptodev_negotiate_features(struct virtio_crypto_hw *hw, 258*25500d4bSJay Zhou uint64_t host_features) 259*25500d4bSJay Zhou { 260*25500d4bSJay Zhou uint64_t features; 261*25500d4bSJay Zhou 262*25500d4bSJay Zhou /* 263*25500d4bSJay Zhou * Limit negotiated features to what the driver, virtqueue, and 264*25500d4bSJay Zhou * host all support. 265*25500d4bSJay Zhou */ 266*25500d4bSJay Zhou features = host_features & hw->guest_features; 267*25500d4bSJay Zhou VTPCI_OPS(hw)->set_features(hw, features); 268*25500d4bSJay Zhou 269*25500d4bSJay Zhou return features; 270*25500d4bSJay Zhou } 271*25500d4bSJay Zhou 272*25500d4bSJay Zhou void 273*25500d4bSJay Zhou vtpci_cryptodev_reset(struct virtio_crypto_hw *hw) 274*25500d4bSJay Zhou { 275*25500d4bSJay Zhou VTPCI_OPS(hw)->set_status(hw, VIRTIO_CONFIG_STATUS_RESET); 276*25500d4bSJay Zhou /* flush status write */ 277*25500d4bSJay Zhou VTPCI_OPS(hw)->get_status(hw); 278*25500d4bSJay Zhou } 279*25500d4bSJay Zhou 280*25500d4bSJay Zhou void 281*25500d4bSJay Zhou vtpci_cryptodev_reinit_complete(struct virtio_crypto_hw *hw) 282*25500d4bSJay Zhou { 283*25500d4bSJay Zhou vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); 284*25500d4bSJay Zhou } 285*25500d4bSJay Zhou 286*25500d4bSJay Zhou void 287*25500d4bSJay Zhou vtpci_cryptodev_set_status(struct virtio_crypto_hw *hw, uint8_t status) 288*25500d4bSJay Zhou { 289*25500d4bSJay Zhou if (status != VIRTIO_CONFIG_STATUS_RESET) 290*25500d4bSJay Zhou status |= VTPCI_OPS(hw)->get_status(hw); 291*25500d4bSJay Zhou 292*25500d4bSJay Zhou VTPCI_OPS(hw)->set_status(hw, status); 293*25500d4bSJay Zhou } 294*25500d4bSJay Zhou 295*25500d4bSJay Zhou uint8_t 296*25500d4bSJay Zhou vtpci_cryptodev_get_status(struct virtio_crypto_hw *hw) 297*25500d4bSJay Zhou { 298*25500d4bSJay Zhou return VTPCI_OPS(hw)->get_status(hw); 299*25500d4bSJay Zhou } 300*25500d4bSJay Zhou 301*25500d4bSJay Zhou uint8_t 302*25500d4bSJay Zhou vtpci_cryptodev_isr(struct virtio_crypto_hw *hw) 303*25500d4bSJay Zhou { 304*25500d4bSJay Zhou return VTPCI_OPS(hw)->get_isr(hw); 305*25500d4bSJay Zhou } 306*25500d4bSJay Zhou 307*25500d4bSJay Zhou static void * 308*25500d4bSJay Zhou get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap) 309*25500d4bSJay Zhou { 310*25500d4bSJay Zhou uint8_t bar = cap->bar; 311*25500d4bSJay Zhou uint32_t length = cap->length; 312*25500d4bSJay Zhou uint32_t offset = cap->offset; 313*25500d4bSJay Zhou uint8_t *base; 314*25500d4bSJay Zhou 315*25500d4bSJay Zhou if (bar >= PCI_MAX_RESOURCE) { 316*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("invalid bar: %u", bar); 317*25500d4bSJay Zhou return NULL; 318*25500d4bSJay Zhou } 319*25500d4bSJay Zhou 320*25500d4bSJay Zhou if (offset + length < offset) { 321*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("offset(%u) + length(%u) overflows", 322*25500d4bSJay Zhou offset, length); 323*25500d4bSJay Zhou return NULL; 324*25500d4bSJay Zhou } 325*25500d4bSJay Zhou 326*25500d4bSJay Zhou if (offset + length > dev->mem_resource[bar].len) { 327*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR( 328*25500d4bSJay Zhou "invalid cap: overflows bar space: %u > %" PRIu64, 329*25500d4bSJay Zhou offset + length, dev->mem_resource[bar].len); 330*25500d4bSJay Zhou return NULL; 331*25500d4bSJay Zhou } 332*25500d4bSJay Zhou 333*25500d4bSJay Zhou base = dev->mem_resource[bar].addr; 334*25500d4bSJay Zhou if (base == NULL) { 335*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("bar %u base addr is NULL", bar); 336*25500d4bSJay Zhou return NULL; 337*25500d4bSJay Zhou } 338*25500d4bSJay Zhou 339*25500d4bSJay Zhou return base + offset; 340*25500d4bSJay Zhou } 341*25500d4bSJay Zhou 342*25500d4bSJay Zhou #define PCI_MSIX_ENABLE 0x8000 343*25500d4bSJay Zhou 344*25500d4bSJay Zhou static int 345*25500d4bSJay Zhou virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) 346*25500d4bSJay Zhou { 347*25500d4bSJay Zhou uint8_t pos; 348*25500d4bSJay Zhou struct virtio_pci_cap cap; 349*25500d4bSJay Zhou int ret; 350*25500d4bSJay Zhou 351*25500d4bSJay Zhou if (rte_pci_map_device(dev)) { 352*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("failed to map pci device!"); 353*25500d4bSJay Zhou return -1; 354*25500d4bSJay Zhou } 355*25500d4bSJay Zhou 356*25500d4bSJay Zhou ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); 357*25500d4bSJay Zhou if (ret < 0) { 358*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("failed to read pci capability list"); 359*25500d4bSJay Zhou return -1; 360*25500d4bSJay Zhou } 361*25500d4bSJay Zhou 362*25500d4bSJay Zhou while (pos) { 363*25500d4bSJay Zhou ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos); 364*25500d4bSJay Zhou if (ret < 0) { 365*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR( 366*25500d4bSJay Zhou "failed to read pci cap at pos: %x", pos); 367*25500d4bSJay Zhou break; 368*25500d4bSJay Zhou } 369*25500d4bSJay Zhou 370*25500d4bSJay Zhou if (cap.cap_vndr == PCI_CAP_ID_MSIX) { 371*25500d4bSJay Zhou /* Transitional devices would also have this capability, 372*25500d4bSJay Zhou * that's why we also check if msix is enabled. 373*25500d4bSJay Zhou * 1st byte is cap ID; 2nd byte is the position of next 374*25500d4bSJay Zhou * cap; next two bytes are the flags. 375*25500d4bSJay Zhou */ 376*25500d4bSJay Zhou uint16_t flags = ((uint16_t *)&cap)[1]; 377*25500d4bSJay Zhou 378*25500d4bSJay Zhou if (flags & PCI_MSIX_ENABLE) 379*25500d4bSJay Zhou hw->use_msix = VIRTIO_MSIX_ENABLED; 380*25500d4bSJay Zhou else 381*25500d4bSJay Zhou hw->use_msix = VIRTIO_MSIX_DISABLED; 382*25500d4bSJay Zhou } 383*25500d4bSJay Zhou 384*25500d4bSJay Zhou if (cap.cap_vndr != PCI_CAP_ID_VNDR) { 385*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG( 386*25500d4bSJay Zhou "[%2x] skipping non VNDR cap id: %02x", 387*25500d4bSJay Zhou pos, cap.cap_vndr); 388*25500d4bSJay Zhou goto next; 389*25500d4bSJay Zhou } 390*25500d4bSJay Zhou 391*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG( 392*25500d4bSJay Zhou "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u", 393*25500d4bSJay Zhou pos, cap.cfg_type, cap.bar, cap.offset, cap.length); 394*25500d4bSJay Zhou 395*25500d4bSJay Zhou switch (cap.cfg_type) { 396*25500d4bSJay Zhou case VIRTIO_PCI_CAP_COMMON_CFG: 397*25500d4bSJay Zhou hw->common_cfg = get_cfg_addr(dev, &cap); 398*25500d4bSJay Zhou break; 399*25500d4bSJay Zhou case VIRTIO_PCI_CAP_NOTIFY_CFG: 400*25500d4bSJay Zhou rte_pci_read_config(dev, &hw->notify_off_multiplier, 401*25500d4bSJay Zhou 4, pos + sizeof(cap)); 402*25500d4bSJay Zhou hw->notify_base = get_cfg_addr(dev, &cap); 403*25500d4bSJay Zhou break; 404*25500d4bSJay Zhou case VIRTIO_PCI_CAP_DEVICE_CFG: 405*25500d4bSJay Zhou hw->dev_cfg = get_cfg_addr(dev, &cap); 406*25500d4bSJay Zhou break; 407*25500d4bSJay Zhou case VIRTIO_PCI_CAP_ISR_CFG: 408*25500d4bSJay Zhou hw->isr = get_cfg_addr(dev, &cap); 409*25500d4bSJay Zhou break; 410*25500d4bSJay Zhou } 411*25500d4bSJay Zhou 412*25500d4bSJay Zhou next: 413*25500d4bSJay Zhou pos = cap.cap_next; 414*25500d4bSJay Zhou } 415*25500d4bSJay Zhou 416*25500d4bSJay Zhou if (hw->common_cfg == NULL || hw->notify_base == NULL || 417*25500d4bSJay Zhou hw->dev_cfg == NULL || hw->isr == NULL) { 418*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("no modern virtio pci device found."); 419*25500d4bSJay Zhou return -1; 420*25500d4bSJay Zhou } 421*25500d4bSJay Zhou 422*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("found modern virtio pci device."); 423*25500d4bSJay Zhou 424*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("common cfg mapped at: %p", hw->common_cfg); 425*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("device cfg mapped at: %p", hw->dev_cfg); 426*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("isr cfg mapped at: %p", hw->isr); 427*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("notify base: %p, notify off multiplier: %u", 428*25500d4bSJay Zhou hw->notify_base, hw->notify_off_multiplier); 429*25500d4bSJay Zhou 430*25500d4bSJay Zhou return 0; 431*25500d4bSJay Zhou } 432*25500d4bSJay Zhou 433*25500d4bSJay Zhou /* 434*25500d4bSJay Zhou * Return -1: 435*25500d4bSJay Zhou * if there is error mapping with VFIO/UIO. 436*25500d4bSJay Zhou * if port map error when driver type is KDRV_NONE. 437*25500d4bSJay Zhou * if whitelisted but driver type is KDRV_UNKNOWN. 438*25500d4bSJay Zhou * Return 1 if kernel driver is managing the device. 439*25500d4bSJay Zhou * Return 0 on success. 440*25500d4bSJay Zhou */ 441*25500d4bSJay Zhou int 442*25500d4bSJay Zhou vtpci_cryptodev_init(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) 443*25500d4bSJay Zhou { 444*25500d4bSJay Zhou /* 445*25500d4bSJay Zhou * Try if we can succeed reading virtio pci caps, which exists 446*25500d4bSJay Zhou * only on modern pci device. If failed, we fallback to legacy 447*25500d4bSJay Zhou * virtio handling. 448*25500d4bSJay Zhou */ 449*25500d4bSJay Zhou if (virtio_read_caps(dev, hw) == 0) { 450*25500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_INFO("modern virtio pci detected."); 451*25500d4bSJay Zhou virtio_hw_internal[hw->dev_id].vtpci_ops = 452*25500d4bSJay Zhou &virtio_crypto_modern_ops; 453*25500d4bSJay Zhou hw->modern = 1; 454*25500d4bSJay Zhou return 0; 455*25500d4bSJay Zhou } 456*25500d4bSJay Zhou 457*25500d4bSJay Zhou /* 458*25500d4bSJay Zhou * virtio crypto conforms to virtio 1.0 and doesn't support 459*25500d4bSJay Zhou * legacy mode 460*25500d4bSJay Zhou */ 461*25500d4bSJay Zhou return -1; 462*25500d4bSJay Zhou } 463