示例#1
0
/*
 * \brief callback handler for new connect requests
 *
 * \param arg       argument passed on the init function
 * \param user_st   pointer to store the user state
 *
 * \returns SYS_ERR_OK if the connection is accepted
 *          errval if connection is rejected
 */
static errval_t dma_svc_connect_cb(void *arg,
                                   void **user_st)
{
    errval_t err;

    struct user_st *st = calloc(1, sizeof(*st));
    if (st == NULL) {
        return LIB_ERR_MALLOC_FAIL;
    }

    XDMA_DEBUG("dma_svc_connect_cb user_st = %p\n", st);

    err = dma_mem_mgr_init(&st->mem_mgr, 0x0, (1UL << 48) - 1);
    if (err_is_fail(err)) {
        free(st);
        return err;
    }

    st->phi = arg;

    dma_mem_mgr_set_convert_fn(st->mem_mgr, translate_address, st);

    *user_st = st;

    return SYS_ERR_OK;
}
示例#2
0
static void memcpy_req_cb(errval_t err,
                          dma_req_id_t id,
                          void *st)
{
    XDMA_DEBUG("memcpy_req_cb %lx, %s\n", id, err_getstring(err));
    dma_service_send_done(st, err, id);
}
示例#3
0
errval_t dma_service_init(struct xeon_phi *phi)
{
    errval_t err;

    XDMA_DEBUG("Initializing DMA service\n");

    struct waitset *ws = get_default_waitset();

    err = xeon_phi_dma_export(phi,
                              svc_export_cb,
                              svc_connect_cb,
                              ws,
                              IDC_EXPORT_FLAGS_DEFAULT);
    if (err_is_fail(err)) {
        return err;
    }

    XDMAV_DEBUG("Waiting for export...\n");
    while (svc_state == XPM_SVC_STATE_EXPORTING) {
        messages_wait_and_handle_next();
    }

    if (svc_state == XPM_SVC_STATE_EXPORT_FAIL) {
        return FLOUNDER_ERR_BIND;
    }

    svc_state = XPM_SVC_STATE_NS_REGISTERING;

    char buf[50];
#ifdef __k1om__
    snprintf(buf, 50, "%s.%u", XEON_PHI_DMA_SERVICE_NAME, 0);
#else
    snprintf(buf, 50, "%s.%u", XEON_PHI_DMA_SERVICE_NAME, phi->id);
#endif

    XDMA_DEBUG("Registering iref [%u] with name [%s]\n", dma_iref, buf);
    err = nameservice_register(buf, dma_iref);
    if (err_is_fail(err)) {
        svc_state = XPM_SVC_STATE_NS_REGISTER_FAIL;
        return err;
    }

    svc_state = XPM_SVC_STATE_RUNNING;

    return SYS_ERR_OK;

}
示例#4
0
/**
 * \brief deregisters a memory region with the client
 *
 * \param user_st   pointer to stored user state
 * \param cap       the capability to deregister
 *
 * \returns SYS_ERR_OK if the memory region was removed
 *          errval if the memory region removal was rejected
 */
static errval_t dma_svc_removeregion_cb(dma_svc_handle_t svc_handle,
                                        struct capref cap)
{
    struct user_st *user_st = dma_service_get_user_state(svc_handle);

    XDMA_DEBUG("dma_svc_removeregion_cb user_st = %p\n", user_st);

    return dma_mem_deregister(user_st->mem_mgr, cap);
}
示例#5
0
/**
 * \brief executes a DMA memcpy
 *
 * \param user_st   pointer to stored user state
 * \param dst       the physical destination address
 * \param src       the physical source address
 * \param bytes     size of the transfer in bytes
 * \param id        returns the DMA request ID of the transfer
 *
 * \returns SYS_ERR_OK if the memory region was removed
 *          errval if the memory region removal was rejected
 */
static errval_t dma_svc_memcpy_cb(dma_svc_handle_t svc_handle,
                                  lpaddr_t dst,
                                  lpaddr_t src,
                                  size_t bytes,
                                  dma_req_id_t *id)
{
    errval_t err;

    struct user_st *st = dma_service_get_user_state(svc_handle);

    XDMA_DEBUG("dma_svc_memcpy_cb user_st = %p\n", st);

    lpaddr_t dma_dst, dma_src;
    err = dma_mem_verify(st->mem_mgr, dst, bytes, &dma_dst);
    if (err_is_fail(err)) {
        return err;
    }
    err = dma_mem_verify(st->mem_mgr, src, bytes, &dma_src);
    if (err_is_fail(err)) {
        return err;
    }

    XDMA_DEBUG("[%016lx]->[%016lx] of %lu bytes\n", dma_src, dma_dst, bytes);

    /* both addresses are valid and have been translated now */
    struct dma_device *dev = st->phi->dma;
    assert(dev);

    struct dma_req_setup setup = {
        .type = DMA_REQ_TYPE_MEMCPY,
        .done_cb = memcpy_req_cb,
        .cb_arg = svc_handle,
        .args = {
            .memcpy = {
                .src = dma_src,
                .dst = dma_dst,
                .bytes = bytes
            }
        }
    };

    return dma_request_memcpy(dev, &setup, id);
}
示例#6
0
/**
 * \brief Xeon Phi DMA service connect handler
 *
 * \param st pointer to struct xeon_phi
 * \param b  Flounder binding
 */
static errval_t svc_connect_cb(void *st,
                               struct xeon_phi_dma_binding *b)
{
    errval_t err;

    XDMA_DEBUG("New connection to the DMA service.\n");
    b->rx_vtbl = dma_rx_vtbl;

    struct xeon_phi *phi = st;
    err = xdma_mem_init(b, phi);
    if (err_is_fail(err)) {
        return err;
    }

    return SYS_ERR_OK;
}
示例#7
0
static void dma_exec_response_tx(void *a)
{
    errval_t err;

    struct dma_exec_resp_st *st = a;

    struct event_closure txcont = MKCONT(dma_exec_response_sent, a);

    err = xeon_phi_dma_exec_response__tx(st->b, txcont, st->err, st->id);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(dma_exec_response_tx, a);
            XDMA_DEBUG("dma_exec_response_tx: register sending...\n");
            err = st->b->register_send(st->b, get_default_waitset(), txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "could not send reply");
            }
        }
        return;
    }
}
示例#8
0
static void dma_exec_call_rx(struct xeon_phi_dma_binding *_binding,
                             uint64_t src,
                             uint64_t dst,
                             uint64_t length)
{
    XDMAV_DEBUG("memcopy request [0x%016lx]->[0x%016lx] of size 0x%lx\n",
                           src, dst, length);

    struct dma_exec_resp_st st;

    st.b = _binding;
    st.sent = 0x0;
    lpaddr_t dma_src = xdma_mem_verify(_binding, src, length);
    lpaddr_t dma_dst = xdma_mem_verify(_binding, dst, length);
    if (!dma_src || !dma_dst) {
        st.err = XEON_PHI_ERR_DMA_MEM_REGISTERED;
        st.id = 0;
#ifdef XDEBUG_DMA
        if (!dma_src) {
            XDMA_DEBUG("Memory range not registered: [0x%016lx] [0x%016lx]\n",
                       src, src+length);
        }
        if (!dma_dst) {
            XDMA_DEBUG("Memory range not registered: [0x%016lx] [0x%016lx]\n",
                       dst, dst+length);
        }
#endif

        dma_exec_response_tx(&st);
        return;
    }

    /*
     * DMA transfers from host to host are not supported.
     */
    if (dma_src > XEON_PHI_SYSMEM_BASE && dma_dst > XEON_PHI_SYSMEM_BASE) {
        st.err = XEON_PHI_ERR_DMA_NOT_SUPPORTED;
        st.id = 0;
        dma_exec_response_tx(&st);
        return;
    }

    struct dma_req_setup setup = {
        .type = XDMA_REQ_TYPE_MEMCPY,
        .st = _binding,
        .cb = dma_service_send_done,
    };
    setup.info.mem.src = dma_src;
    setup.info.mem.dst = dma_dst;
    setup.info.mem.bytes = length;
    setup.info.mem.dma_id = &st.id;

    struct xeon_phi *phi = xdma_mem_get_phi(_binding);

    st.err = dma_do_request(phi, &setup);

    dma_exec_response_tx(&st);

    /*
     * XXX: we must wait until the message has been sent, otherwise we may
     *      trigger sending the done message when we poll in the main message
     *      loop. This causes the client library to receive a done message
     *      of an invalid id.
     */
    volatile uint8_t *sent_flag = &st.sent;
    while(!(*sent_flag)) {
        messages_wait_and_handle_next();
    }
}