static void ioat_dma_device_irq_handler(void* arg)
{
    errval_t err;
    struct dma_device *dev = arg;

    IOATDEV_DEBUG("############ MSIX INTERRUPT HAPPENED.\n", dev->id);

#if IOAT_DEBUG_INTR_ENABLED
    msix_intr_happened=1;
#endif

    err = ioat_dma_device_poll_channels(dev);
    if (err_is_fail(err)) {
        if (err_no(err) == DMA_ERR_DEVICE_IDLE) {
            IOATDEV_DEBUG("WARNING: MSI-X interrupt on idle device\n", dev->id);
            return;
        }
        USER_PANIC_ERR(err, "dma poll device returned an error\n");
    }
}
Example #2
0
errval_t ioat_device_poll(void)
{
    errval_t err;

    uint8_t idle = 0x1;
    for (uint8_t i = 0; i < device_count; ++i) {
        err = ioat_dma_device_poll_channels((struct dma_device *)devices[i]);
        switch (err_no(err)) {
            case SYS_ERR_OK:
                idle = 0;
                break;
            case DMA_ERR_DEVICE_IDLE:
                break;
            default:
                return err;
        }
    }
    if (idle) {
        return DMA_ERR_DEVICE_IDLE;
    }
    return SYS_ERR_OK;
}
Example #3
0
static void impl_test(void)
{
    errval_t err;

    debug_printf("Doing an implementation test\n");

    struct capref frame;
    err = frame_alloc(&frame, 2 * BUFFER_SIZE, NULL);
    assert(err_is_ok(err));

    struct frame_identity id;
    err = invoke_frame_identify(frame, &id);
    assert(err_is_ok(err));

    void *buf;
    err = vspace_map_one_frame(&buf, 1UL << id.bits, frame, NULL, NULL);
    assert(err_is_ok(err));

    memset(buf, 0, 1UL << id.bits);
    memset(buf, 0xA5, BUFFER_SIZE);

    struct ioat_dma_req_setup setup = {
        .type = IOAT_DMA_REQ_TYPE_MEMCPY,
        .src = id.base,
        .dst = id.base + BUFFER_SIZE,
        .bytes = BUFFER_SIZE,
        .done_cb = impl_test_cb,
        .arg = buf
    };
    int reps = 10;
    do {
        debug_printf("!!!!!! NEW ROUND\n");
        err = ioat_dma_request_memcpy(dma_ctrl.devices, &setup);
        assert(err_is_ok(err));

        uint32_t i = 10;
        while(i--) {
            ioat_dma_device_poll_channels(dma_ctrl.devices);
        }
    }while(reps--);
}
#endif

int main(int argc,
         char *argv[])
{
    errval_t err;

    debug_printf("I/O AT DMA driver started\n");

    /*
     * Parsing of cmdline arguments.
     *
     * When started by Kaluga, the last element of the cmdline will contain
     * the basic PCI information of the device.
     * VENDORID:DEVICEID:BUS:DEV:FUN
     */
    uint32_t vendor_id, device_id;

    struct pci_addr addr = {
        .bus = PCI_ADDR_DONT_CARE,
        .device = PCI_ADDR_DONT_CARE,
        .device = PCI_ADDR_DONT_CARE
    };

    enum device_type devtype = IOAT_DEVICE_INVAL;

    if (argc > 1) {
        uint32_t parsed = sscanf(argv[argc - 1], "%x:%x:%x:%x:%x", &vendor_id,
                                 &device_id, &addr.bus, &addr.device,
                                 &addr.function);
        if (parsed != 5) {
            DEBUGPRINT("WARNING: cmdline parsing failed. Using PCI Address [0,0,0]");
        } else {
            if (vendor_id != 0x8086) {
                USER_PANIC("unexpected vendor [%x]", vendor_id);
            }
            switch ((device_id & 0xFFF0)) {
                case PCI_DEVICE_IOAT_IVB0:
                    devtype = IOAT_DEVICE_IVB;
                    break;
                case PCI_DEVICE_IOAT_HSW0:
                    devtype = IOAT_DEVICE_HSW;
                    break;
                default:
                    USER_PANIC("unexpected device [%x]", device_id)
                    ;
                    break;
            }

            DEBUGPRINT("Initializing I/O AT DMA device with PCI address [%u,%u,%u]\n",
                       addr.bus, addr.device, addr.function);
        }
    } else {
        DEBUGPRINT("WARNING: Initializing I/O AT DMA device with unknown PCI address "
                   "[0,0,0]\n");
    }

    err = ioat_device_discovery(addr, devtype, IOAT_DMA_OPERATION);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "DMA Device discovery failed");
    }

#if DMA_BENCH_RUN_BENCHMARK
    struct ioat_dma_device *dev = ioat_device_get_next();
    dma_bench_run_default(dev);
#endif

#if IOAT_DMA_OPERATION == IOAT_DMA_OPERATION_SERVICE

    iref_t svc_iref;
    char svc_name[30];
    uint8_t numa_node = (disp_get_core_id() >= 20);
    snprintf(svc_name, 30, "%s.%u", IOAT_DMA_SERVICE_NAME, numa_node);
    err = dma_service_init_with_name(svc_name, &dma_svc_cb, NULL, &svc_iref);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "Failed to start the DMA service");
    }

    err = dma_manager_register_driver(0, 1ULL << 40, DMA_DEV_TYPE_IOAT, svc_iref);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "Failed to register with the DMA manager\n");
    }

    DEBUGPRINT("Driver registered with DMA manager. Serving requests now.\n");

#endif

#if IOAT_DMA_OPERATION == IOAT_DMA_OPERATION_LIBRARY

#endif
    uint8_t idle = 0x1;
    uint32_t idle_counter = 0xFF;
    while (1) {
        err = ioat_device_poll();
        switch (err_no(err)) {
            case DMA_ERR_DEVICE_IDLE:
                idle = idle && 0x1;
                break;
            case SYS_ERR_OK:
                idle = 0;
                break;
            default:
                debug_printf("I/O AT DMA driver terminated: in poll, %s\n",
                             err_getstring(err));
                return err;
        }
        err = event_dispatch_non_block(get_default_waitset());
        switch (err_no(err)) {
            case SYS_ERR_OK:
                idle = 0;
                break;
            case LIB_ERR_NO_EVENT:
                idle &= 1;
                break;
            default:
                debug_printf("I/O AT DMA driver terminated in dispatch,  %s\n",
                             err_getstring(err));
                return err;
        }
        if (idle) {
            idle_counter--;
        }
        if (idle_counter == 0) {
            idle_counter = 0xFF;
            thread_yield();
        }
    }

    return 0;
}