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);
    }
  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/dream397/p/13628896.html
Copyright © 2011-2022 走看看