Module: xenomai-3
Branch: master
Commit: 778b648d4b8b5845c52397bab02a1eba55c143bc
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=778b648d4b8b5845c52397bab02a1eba55c143bc

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Apr 24 10:39:32 2015 +0200

drivers/udd: add sync mode to IRQ enable/disable requests

---

 include/cobalt/kernel/rtdm/udd.h |   24 +++++++++++++++--
 include/rtdm/uapi/udd.h          |   14 +++++-----
 kernel/drivers/udd/udd.c         |   55 +++++++++++++++++++++++++++-----------
 3 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/udd.h b/include/cobalt/kernel/rtdm/udd.h
index 028e602..67ca6ed 100644
--- a/include/cobalt/kernel/rtdm/udd.h
+++ b/include/cobalt/kernel/rtdm/udd.h
@@ -211,16 +211,30 @@ struct udd_device {
                /**
                 * Ancillary open() handler, optional. See
                 * rtdm_open_handler().
+                *
+                * @note This handler is called from secondary mode
+                * only.
                 */
                int (*open)(struct rtdm_fd *fd, int oflags);
                /**
                 * Ancillary close() handler, optional. See
                 * rtdm_close_handler().
+                *
+                * @note This handler is called from secondary mode
+                * only.
                 */
                void (*close)(struct rtdm_fd *fd);
                /**
                 * Ancillary ioctl() handler, optional. See
                 * rtdm_ioctl_handler().
+                *
+                * If this routine returns -ENOSYS, the default action
+                * implemented by the UDD core for the corresponding
+                * request will be applied, as if no ioctl handler had
+                * been defined.
+                *
+                * @note This handler is called from primary mode
+                * only.
                 */
                int (*ioctl)(struct rtdm_fd *fd,
                             unsigned int request, void *arg);
@@ -234,6 +248,9 @@ struct udd_device {
                 * If this handler is NULL, the UDD core establishes
                 * the mapping automatically, depending on the memory
                 * type defined for the region.
+                *
+                * @note This handler is called from secondary mode
+                * only.
                 */
                int (*mmap)(struct rtdm_fd *fd,
                            struct vm_area_struct *vma);
@@ -261,6 +278,9 @@ struct udd_device {
                 * Once the ->interrupt() handler has returned, the
                 * UDD core notifies user-space Cobalt threads waiting
                 * for IRQ events (if any).
+                *
+                * @note This handler is called from primary mode
+                * only.
                 */
                int (*interrupt)(struct udd_device *udd);
        } ops;
@@ -304,9 +324,9 @@ struct udd_device *udd_get_device(struct rtdm_fd *fd);
 
 void udd_notify_event(struct udd_device *udd);
 
-void udd_post_irq_enable(int irq);
+void udd_post_irq_enable(int irq, rtdm_event_t *done);
 
-void udd_post_irq_disable(int irq);
+void udd_post_irq_disable(int irq, rtdm_event_t *done);
 
 /** @} */
 
diff --git a/include/rtdm/uapi/udd.h b/include/rtdm/uapi/udd.h
index 210f0ce..5ac9b92 100644
--- a/include/rtdm/uapi/udd.h
+++ b/include/rtdm/uapi/udd.h
@@ -64,15 +64,17 @@ struct udd_signotify {
  */
 
 /**
- * Enable the interrupt line. The UDD-class mini-driver in kernel
- * space should act upon this request appropriately when received via
- * its ->ioctl() handler.
+ * Enable the interrupt line. The UDD-class mini-driver should handle
+ * this request when received through its ->ioctl() handler if
+ * provided. Otherwise, the UDD core enables the interrupt line in the
+ * interrupt controller.
  */
 #define UDD_RTIOC_IRQEN                _IO(RTDM_CLASS_UDD, 0)
 /**
- * Disable the interrupt line. The UDD-class mini-driver in kernel
- * should act upon this request appropriately when received via its
- * ->ioctl() handler.
+ * Disable the interrupt line. The UDD-class mini-driver should handle
+ * this request when received through its ->ioctl() handler if
+ * provided. Otherwise, the UDD core disables the interrupt line in
+ * the interrupt controller.
  */
 #define UDD_RTIOC_IRQDIS       _IO(RTDM_CLASS_UDD, 1)
 /**
diff --git a/kernel/drivers/udd/udd.c b/kernel/drivers/udd/udd.c
index edac81a..aaae6f7 100644
--- a/kernel/drivers/udd/udd.c
+++ b/kernel/drivers/udd/udd.c
@@ -63,7 +63,8 @@ static int udd_ioctl_rt(struct rtdm_fd *fd,
        struct udd_signotify signfy;
        struct udd_reserved *ur;
        struct udd_device *udd;
-       int ret = 0;
+       rtdm_event_t done;
+       int ret;
 
        udd = container_of(rtdm_fd_device(fd), struct udd_device, 
__reserved.device);
        if (udd->ops.ioctl) {
@@ -91,15 +92,20 @@ static int udd_ioctl_rt(struct rtdm_fd *fd,
                }
                break;
        case UDD_RTIOC_IRQEN:
-               if (udd->irq == UDD_IRQ_NONE)
-                       return -EIO;
-               udd_post_irq_enable(udd->irq);
-               break;
        case UDD_RTIOC_IRQDIS:
                if (udd->irq == UDD_IRQ_NONE)
                        return -EIO;
-               udd_post_irq_disable(udd->irq);
+               rtdm_event_init(&done, 0);
+               if (request == UDD_RTIOC_IRQEN)
+                       udd_post_irq_enable(udd->irq, &done);
+               else
+                       udd_post_irq_disable(udd->irq, &done);
+               ret = rtdm_event_wait(&done);
+               if (ret != -EIDRM)
+                       rtdm_event_destroy(&done);
                break;
+       default:
+               ret = -EINVAL;
        }
 
        return ret;
@@ -513,6 +519,7 @@ struct irqswitch_work {
        struct ipipe_work_header work; /* Must be first. */
        int irq;
        int enabled;
+       rtdm_event_t *done;
 };
 
 static void lostage_irqswitch_line(struct ipipe_work_header *work)
@@ -528,9 +535,12 @@ static void lostage_irqswitch_line(struct 
ipipe_work_header *work)
                ipipe_enable_irq(rq->irq);
        else
                ipipe_disable_irq(rq->irq);
+
+       if (rq->done)
+               rtdm_event_signal(rq->done);
 }
 
-static void switch_irq_line(int irq, int enable)
+static void switch_irq_line(int irq, int enable, rtdm_event_t *done)
 {
        struct irqswitch_work switchwork = {
                .work = {
@@ -539,6 +549,7 @@ static void switch_irq_line(int irq, int enable)
                },
                .irq = irq,
                .enabled = enable,
+               .done = done,
        };
 
        /*
@@ -556,19 +567,26 @@ static void switch_irq_line(int irq, int enable)
  * This service issues a request to the regular kernel for enabling
  * the IRQ line mentioned. If the caller runs in primary mode, the
  * request is scheduled but deferred until the current CPU leaves the
- * real-time domain. Otherwise, the request is immediately handled.
+ * real-time domain (see note). Otherwise, the request is immediately
+ * handled.
  *
  * @param irq IRQ line to enable.
  *
+ * @param done Optional event to signal upon completion. If non-NULL,
+ * @a done will be posted by a call to rtdm_event_signal() after the
+ * interrupt line is enabled.
+ *
  * @coretags{unrestricted}
  *
  * @note The deferral is required as some interrupt management code
  * involved in enabling interrupt lines may not be safely executed
- * from primary mode.
+ * from primary mode. By passing a valid @a done object address, the
+ * caller can wait for the request to complete, by sleeping on
+ * rtdm_event_wait().
  */
-void udd_post_irq_enable(int irq)
+void udd_post_irq_enable(int irq, rtdm_event_t *done)
 {
-       switch_irq_line(irq, 1);
+       switch_irq_line(irq, 1, done);
 }
 EXPORT_SYMBOL_GPL(udd_post_irq_enable);
 
@@ -578,19 +596,26 @@ EXPORT_SYMBOL_GPL(udd_post_irq_enable);
  * This service issues a request to the regular kernel for disabling
  * the IRQ line mentioned. If the caller runs in primary mode, the
  * request is scheduled but deferred until the current CPU leaves the
- * real-time domain. Otherwise, the request is immediately handled.
+ * real-time domain (see note). Otherwise, the request is immediately
+ * handled.
  *
  * @param irq IRQ line to disable.
  *
+ * @param done Optional event to signal upon completion. If non-NULL,
+ * @a done will be posted by a call to rtdm_event_signal() after the
+ * interrupt line is disabled.
+ *
  * @coretags{unrestricted}
  *
  * @note The deferral is required as some interrupt management code
  * involved in disabling interrupt lines may not be safely executed
- * from primary mode.
+ * from primary mode. By passing a valid @a done object address, the
+ * caller can wait for the request to complete, by sleeping on
+ * rtdm_event_wait().
  */
-void udd_post_irq_disable(int irq)
+void udd_post_irq_disable(int irq, rtdm_event_t *done)
 {
-       switch_irq_line(irq, 0);
+       switch_irq_line(irq, 0, done);
 }
 EXPORT_SYMBOL_GPL(udd_post_irq_disable);
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to