zoukankan      html  css  js  c++  java
  • dpdk 中断映射

     

    /* set up interrupt support (but not enable interrupts) */
    static int
    pci_vfio_setup_interrupts(struct rte_pci_device *dev, int vfio_dev_fd)
    {
        int i, ret, intr_idx;
    
        /* default to invalid index */
        intr_idx = VFIO_PCI_NUM_IRQS;
    
        /* get interrupt type from internal config (MSI-X by default, can be
         * overriden from the command line
         */
        switch (internal_config.vfio_intr_mode) {
        case RTE_INTR_MODE_MSIX:
            intr_idx = VFIO_PCI_MSIX_IRQ_INDEX;
            break;
        case RTE_INTR_MODE_MSI:
            intr_idx = VFIO_PCI_MSI_IRQ_INDEX;
            break;
        case RTE_INTR_MODE_LEGACY:
            intr_idx = VFIO_PCI_INTX_IRQ_INDEX;
            break;
        /* don't do anything if we want to automatically determine interrupt type */
        case RTE_INTR_MODE_NONE:
            break;
        default:
            RTE_LOG(ERR, EAL, "  unknown default interrupt type!
    ");
            return -1;
        }
    
        /* start from MSI-X interrupt type */
        for (i = VFIO_PCI_MSIX_IRQ_INDEX; i >= 0; i--) {
            struct vfio_irq_info irq = { .argsz = sizeof(irq) };
            int fd = -1;
    
            /* skip interrupt modes we don't want */
            if (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE &&
                    i != intr_idx)
                continue;
    
            irq.index = i;
    
            ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
            if (ret < 0) {
                RTE_LOG(ERR, EAL, "  cannot get IRQ info, "
                        "error %i (%s)
    ", errno, strerror(errno));
                return -1;
            }
    
            /* if this vector cannot be used with eventfd, fail if we explicitly
             * specified interrupt type, otherwise continue */
            if ((irq.flags & VFIO_IRQ_INFO_EVENTFD) == 0) {
                if (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE) {
                    RTE_LOG(ERR, EAL,
                            "  interrupt vector does not support eventfd!
    ");
                    return -1;
                } else
                    continue;
            }
    
            /* set up an eventfd for interrupts */
            fd = eventfd(0, 0);
            if (fd < 0) {
                RTE_LOG(ERR, EAL, "  cannot set up eventfd, "
                        "error %i (%s)
    ", errno, strerror(errno));
                return -1;
            }
    
            dev->intr_handle.fd = fd;
            dev->intr_handle.vfio_dev_fd = vfio_dev_fd;
    
            switch (i) {
            case VFIO_PCI_MSIX_IRQ_INDEX:
                internal_config.vfio_intr_mode = RTE_INTR_MODE_MSIX;
                dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSIX;
                break;
            case VFIO_PCI_MSI_IRQ_INDEX:
                internal_config.vfio_intr_mode = RTE_INTR_MODE_MSI;
                dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSI;
                break;
            case VFIO_PCI_INTX_IRQ_INDEX:
                internal_config.vfio_intr_mode = RTE_INTR_MODE_LEGACY;
                dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_LEGACY;
                break;
            default:
                RTE_LOG(ERR, EAL, "  unknown interrupt type!
    ");
                return -1;
            }
    
            return 0;
        }
    
        /* if we're here, we haven't found a suitable interrupt vector */
        return -1;
    }
    // 查询eventfd的支持情况
        ioctl(s->device, VFIO_DEVICE_GET_IRQ_INFO, &irq_info)
    
        // 将eventfd的fd传递到内核态
        *irq_set = (struct vfio_irq_set) {
            .argsz = irq_set_size,
            .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
            .index = irq_info.index,
            .start = 0,
            .count = 1,
        };
    
        *(int *)&irq_set->data = event_notifier_get_fd(e);
        r = ioctl(s->device, VFIO_DEVICE_SET_IRQS, irq_set);
    static int
    uio_intr_enable(const struct rte_intr_handle *intr_handle)
    {
            const int value = 1;
    
            if (write(intr_handle->fd, &value, sizeof(value)) < 0) {
                    RTE_LOG(ERR, EAL,
                            "Error enabling interrupts for fd %d (%s)
    ",
                            intr_handle->fd, strerror(errno));
                    return -1;
            }
            return 0;
    }

     

    ixgbe_configure_msix(struct rte_eth_dev *dev)
             /* set up to autoclear timer, and the vectors */
            mask = IXGBE_EIMS_ENABLE_MASK;
            mask &= ~(IXGBE_EIMS_OTHER |
                      IXGBE_EIMS_MAILBOX |
                      IXGBE_EIMS_LSC);
    
            IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
    
    
    static int
    ixgbe_dev_start(struct rte_eth_dev *dev)
    {
                  /* confiugre msix for sleep until rx interrupt */
            ixgbe_configure_msix(dev);
    
            /* initialize transmission unit */
            ixgbe_dev_tx_init(dev);
    
            /* This can fail when allocating mbufs for descriptor rings */
            err = ixgbe_dev_rx_init(dev);
    static struct rte_pci_driver rte_ixgbe_pmd = {
            .id_table = pci_id_ixgbe_map,
            .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
            .probe = eth_ixgbe_pci_probe,
            .remove = eth_ixgbe_pci_remove,
    }
    
    eth_ixgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                    struct rte_pci_device *pci_dev)
    {
     
    
            retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
                    sizeof(struct ixgbe_adapter),
                    eth_dev_pci_specific_init, pci_dev,
                    eth_ixgbe_dev_init, NULL);
    eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
    {
    
                /* enable uio/vfio intr/eventfd mapping */
            rte_intr_enable(intr_handle);
    
            /* enable support intr */
            ixgbe_enable_intr(eth_dev); 
    }
    static inline void
    ixgbe_enable_intr(struct rte_eth_dev *dev)
    {
            struct ixgbe_interrupt *intr =
                    IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
            struct ixgbe_hw *hw =
                    IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    
            IXGBE_WRITE_REG(hw, IXGBE_EIMS, intr->mask);
            IXGBE_WRITE_FLUSH(hw);
    }
  • 相关阅读:
    设计模式
    idea多个项目
    多个tomcat配置
    mysql数据库默认时间字段格式
    读取文件
    上传图片
    数据库创建用户授权
    统计12个月份的数据
    行列转换
    分页
  • 原文地址:https://www.cnblogs.com/dream397/p/13628896.html
Copyright © 2011-2022 走看看