qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/9] dma-helpers: Add support for ioctl operations


From: Alex Pyrgiotis
Subject: [Qemu-devel] [PATCH 2/9] dma-helpers: Add support for ioctl operations
Date: Wed, 16 Dec 2015 18:55:10 +0200

Allow ioctl operations to benefit from the DMA functionality created for
the read/write operations. More specifically, create a function called
"dma_blk_ioctl" that uses the existing code for mapping scatter-gather
lists to qiovs and ultimately calls the blk_aio_ioctl() function to
perform the actual ioctl operation.

Also, in order to use the qiov in the ioctl request, the user
can specify a qiov handler when calling dma_blk_ioctl(). This handler
will be called after the creation of the qiov and before the actual
ioctl request. This allows the user to update the ioctl request with the
iovec stored in the qiov.

Signed-off-by: Alex Pyrgiotis <address@hidden>
Signed-off-by: Dimitris Aragiorgis <address@hidden>

diff --git a/dma-helpers.c b/dma-helpers.c
index c38661e..e1ea7b3 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -79,10 +79,14 @@ typedef struct {
     QEMUIOVector iov;
     QEMUBH *bh;
     DMAIOFunc *io_func;
+    unsigned int ioctl_req_type;
+    void *ioctl_req;
+    void (*handle_iov)(void *opaque, QEMUIOVector *iov);
     BlockCompletionFunc *dma_cb;
 } DMAAIOCB;
 
 static void dma_blk_io_cb(void *opaque, int ret);
+static void dma_blk_ioctl_cb(void *opaque, int ret);
 
 static void reschedule_dma(void *opaque)
 {
@@ -196,6 +200,42 @@ static void dma_blk_io_cb(void *opaque, int ret)
     assert(dbs->acb);
 }
 
+/*
+ * Callback function for DMA ioctl operations.
+ *
+ * This function is similar to the dma_blk_io_cb() function. The only addition
+ * is that it checks if a caller has specified a handler resulting iovec, and
+ * calls it before starting the ioctl operation.
+ */
+static void dma_blk_ioctl_cb(void *opaque, int ret)
+{
+    DMAAIOCB *dbs = (DMAAIOCB *)opaque;
+
+    trace_dma_blk_ioctl_cb(dbs, ret);
+
+    dbs->acb = NULL;
+
+    if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
+        dma_complete(dbs, ret);
+        return;
+    }
+
+    dma_map_sg(dbs);
+
+    /*
+     * If the user has specified a handler for the resulting iovec, call it
+     * before starting the ioctl.
+     */
+    if (dbs->handle_iov) {
+        dbs->handle_iov(dbs->common.opaque, &dbs->iov);
+    }
+
+    dbs->acb = blk_aio_ioctl(dbs->blk, dbs->ioctl_req_type, dbs->ioctl_req,
+            dma_blk_ioctl_cb, dbs);
+
+    assert(dbs->acb);
+}
+
 static void dma_aio_cancel(BlockAIOCB *acb)
 {
     DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
@@ -267,6 +307,54 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk,
                       DMA_DIRECTION_TO_DEVICE);
 }
 
+/**
+ * dma_blk_ioctl - perform an ioctl request using a scatter-gather list
+ * @blk:             The BlockBackend struct of the underlying device
+ * @ioctl_req_type:  The type of the control function to perform
+ * @ioctl_req:       The payload for the action
+ * @dir:             The direction of the DMA request
+ * @iov_cb:          The callback for handling the qiov that results from the
+ *                   mapping of the scatter gather lists.
+ *                   Expected parameters:
+ *                   @ opaque:          The opaque struct that is provided
+ *                                      with this call (see below)
+ *                   @ iov:             The QEMUIOVector that is mapped to the
+ *                                      scatter-gather list
+ * @complete_cb:     The completion callback for this request.
+ *                   Expected parameters:
+ *                   @ opaque:          The opaque struct that is provided
+ *                                      with this call (see below)
+ *                   @ ret:             The return value of the ioctl call
+ * @opaque:          Private data of the caller
+ *
+ * Description:
+ *     This function calls dma_map_sg, which maps the provided scatter-gather
+ *     list to a qiov. Next, the iov_cb handler is called with the `opaque' and
+ *     qiov as arguments. Then, the ioctl request is enqueued and the function
+ *     returns.  The caller will be notified about the completion of the
+ *     request with the complete_cb handler.
+ */
+BlockAIOCB *dma_blk_ioctl(BlockBackend *blk,
+                          unsigned long int ioctl_req_type,
+                          void *ioctl_req,
+                          QEMUSGList *sg,
+                          DMADirection dir,
+                          void (*iov_cb)(void *opaque, QEMUIOVector *iov),
+                          void (*complete_cb)(void *opaque, int ret),
+                          void *opaque)
+{
+    DMAAIOCB *dbs = blk_aio_get(&dma_aiocb_info, blk, complete_cb, opaque);
+
+    trace_dma_blk_ioctl(dbs, blk, (dir == DMA_DIRECTION_TO_DEVICE));
+
+    dma_init_dbs(dbs, blk, sg, dir);
+    dbs->handle_iov = iov_cb;
+    dbs->ioctl_req = ioctl_req;
+    dbs->ioctl_req_type = ioctl_req_type;
+    dbs->dma_cb = dma_blk_ioctl_cb;
+    dbs->dma_cb(dbs, 0);
+    return &dbs->common;
+}
 
 static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg,
                            DMADirection dir)
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index efa8b99..aaf561d 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -212,6 +212,14 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk,
 BlockAIOCB *dma_blk_write(BlockBackend *blk,
                           QEMUSGList *sg, uint64_t sector,
                           BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *dma_blk_ioctl(BlockBackend *blk,
+                          unsigned long int ioctl_req_type,
+                          void *ioctl_req,
+                          QEMUSGList *sg,
+                          DMADirection dir,
+                          void (*iov_cb)(void *opaque, QEMUIOVector *iov),
+                          void (*complete_cb)(void *opaque, int ret),
+                          void *opaque);
 uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 
diff --git a/trace-events b/trace-events
index 120cdd4..0cee005 100644
--- a/trace-events
+++ b/trace-events
@@ -1125,9 +1125,11 @@ win_helper_retry(uint32_t tl) "tl=%d"
 
 # dma-helpers.c
 dma_blk_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p 
sector_num=%" PRId64 " to_dev=%d"
+dma_blk_ioctl(void *dbs, void *bs, bool to_dev) "dbs=%p bs=%p to_dev=%d"
 dma_aio_cancel(void *dbs) "dbs=%p"
 dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p"
 dma_blk_io_cb(void *dbs, int ret) "dbs=%p ret=%d"
+dma_blk_ioctl_cb(void *dbs, int ret) "dbs=%p ret=%d"
 dma_map_wait(void *dbs) "dbs=%p"
 
 # ui/console.c
-- 
2.6.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]