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);
}
原文地址:https://www.cnblogs.com/dream397/p/13628896.html