/** * \brief globally enables the interrupts for the given device * * \param dev IOAT DMA device * \param type the interrupt type to enable */ errval_t ioat_dma_device_irq_setup(struct ioat_dma_device *dev, dma_irq_t type) { ioat_dma_intrctrl_t intcrtl = 0; intcrtl = ioat_dma_intrctrl_intp_en_insert(intcrtl, 1); dev->common.irq_type = type; switch (type) { case DMA_IRQ_MSIX: IOATDEV_DEBUG("Initializing MSI-X interrupts \n", dev->common.id); assert(!"NYI"); break; case DMA_IRQ_MSI: IOATDEV_DEBUG("Initializing MSI interrupts \n", dev->common.id); assert(!"NYI"); break; case DMA_IRQ_INTX: IOATDEV_DEBUG("Initializing INTx interrupts \n", dev->common.id); assert(!"NYI"); break; default: /* disabled */ intcrtl = 0; IOATDEV_DEBUG("Disabling interrupts \n", dev->common.id); break; } ioat_dma_intrctrl_wr(&dev->device, intcrtl); return SYS_ERR_OK; }
/** * \brief globally enables the interrupts for the given device * * \param dev IOAT DMA device * \param type the interrupt type to enable */ errval_t ioat_dma_device_irq_setup(struct ioat_dma_device *dev, dma_irq_t type) { errval_t err; ioat_dma_intrctrl_t intcrtl = 0; intcrtl = ioat_dma_intrctrl_intp_en_insert(intcrtl, 1); dev->common.irq_type = type; switch (type) { case DMA_IRQ_MSIX: /* The number of MSI-X vectors should equal the number of channels */ IOATDEV_DEBUG("MSI-X interrupt setup for device (%u, %u, %u)\n", dev->common.id, dev->pci_addr.bus, dev->pci_addr.device, dev->pci_addr.function); err = pci_msix_enable_addr(&dev->pci_addr, &dev->irq_msix_count); if (err_is_fail(err)) { return err; } assert(dev->irq_msix_count > 0); IOATDEV_DEBUG("MSI-X enabled #vecs=%d\n", dev->common.id, dev->irq_msix_count); err = pci_setup_inthandler(ioat_dma_device_irq_handler, dev, &dev->irq_msix_vector); assert(err_is_ok(err)); uint8_t dest = get_local_apic_id(); IOATDEV_DEBUG("MSI-X routing to apic=%u\n", dev->common.id, dest); err = pci_msix_vector_init_addr(&dev->pci_addr, 0, dest, dev->irq_msix_vector); assert(err_is_ok(err)); /* enable the interrupts */ intcrtl = ioat_dma_intrctrl_msix_vec_insert(intcrtl, 1); intcrtl = ioat_dma_intrctrl_intp_en_insert(intcrtl, 1); break; case DMA_IRQ_MSI: IOATDEV_DEBUG("Initializing MSI interrupts \n", dev->common.id); assert(!"NYI"); break; case DMA_IRQ_INTX: IOATDEV_DEBUG("Initializing INTx interrupts \n", dev->common.id); assert(!"NYI"); break; default: /* disabled */ intcrtl = 0; IOATDEV_DEBUG("Disabling interrupts \n", dev->common.id); break; } ioat_dma_intrctrl_wr(&dev->device, intcrtl); #if IOAT_DEBUG_INTR_ENABLED /* * check if interrupts are working. */ msix_intr_happened = 0; struct ioat_dma_channel *chan; chan = (struct ioat_dma_channel *)dev->common.channels.c[0]; ioat_dma_request_nop_chan(chan); err = ioat_dma_channel_issue_pending(chan); if (err_is_fail(err)) { return err; } while(msix_intr_happened == 0) { uint64_t status = ioat_dma_channel_get_status(chan); err = event_dispatch_non_block(get_default_waitset()); if (!ioat_dma_channel_is_active(status) && !ioat_dma_channel_is_idle(status)) { USER_PANIC("DMA request turned channel into erroneous state.") } switch(err_no(err)) { case LIB_ERR_NO_EVENT: thread_yield(); break; case SYS_ERR_OK: continue; default: USER_PANIC_ERR(err, "dispatching event"); } } #endif return SYS_ERR_OK; }