diff mbox

[3/3] DSPBRIDGE: simplify and make more use of kernel function in notify module

Message ID 496565EC904933469F292DDA3F1663E602CADC2FF4@dlee06.ent.ti.com (mailing list archive)
State Accepted
Delegated to:
Headers show

Commit Message

Guzman Lugo, Fernando March 25, 2010, 3:54 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
index 4544259..dfda615 100644
--- a/arch/arm/plat-omap/include/dspbridge/ntfy.h
+++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
@@ -19,18 +19,49 @@ 
 #ifndef NTFY_
 #define NTFY_

-#include <dspbridge/list.h>
+#include <dspbridge/host_os.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/sync.h>

-/*
- *  ======== ntfy_object ========
+/**
+ * ntfy_object - head structure to nofify dspbridge events
+ * @head:      List of notify objects
+ * @ntfy_lock: lock for list access.
+ *
  */
 struct ntfy_object {
-       u32 dw_signature;       /* For object validation */
-       struct lst_list *notify_list;   /* List of notifier objects */
+       struct raw_notifier_head head;/* List of notifier objects */
        spinlock_t ntfy_lock;   /* For critical sections */
 };

 /**
+ * ntfy_event - structure store specify event to be notified
+ * @noti_block:        List of notify objects
+ * @event:     event that it respond
+ * @type:      event type (only DSP_SIGNALEVENT supported)
+ * @sync_obj:  sync_event used to set the event
+ *
+ */
+struct ntfy_event {
+       struct notifier_block noti_block;
+       u32 event;      /* Events to be notified about */
+       u32 type;       /* Type of notification to be sent */
+       struct sync_object sync_obj;
+};
+
+
+/**
+ * dsp_notifier_event() - callback function to nofity events
+ * @this:              pointer to itself struct notifier_block
+ * @event:     event to be notified.
+ * @data:              Currently not used.
+ *
+ */
+int dsp_notifier_event(struct notifier_block *this, unsigned long event,
+                          void *data);
+
+/**
  * ntfy_init() - Set the initial state of the ntfy_object structure.
  * @no:                pointer to ntfy_object structure.
  *
@@ -40,65 +71,148 @@  struct ntfy_object {

 static inline void ntfy_init(struct ntfy_object *no)
 {
-       INIT_LIST_HEAD(&no->notify_list->head);
+       spin_lock_init(&no->ntfy_lock);
+       RAW_INIT_NOTIFIER_HEAD(&no->head);
 }

-/*
- *  ======== ntfy_delete ========
- *  Purpose:
- *      Free resources allocated in ntfy_create.
- *  Parameters:
- *      ntfy_obj:  Handle returned from ntfy_create().
- *  Returns:
- *  Requires:
- *      IS_VALID(ntfy_obj).
- *  Ensures:
+/**
+ * ntfy_delete() - delete list of nofy events registered.
+ * @ntfy_obj:  Pointer to the ntfy object structure.
+ *
+ * This function is used to remove all the notify events  registered.
+ * unregister function is not needed in this function, to unregister
+ * a ntfy_event please look at ntfy_register function.
+ *
  */
-extern void ntfy_delete(IN struct ntfy_object *ntfy_obj);
+static inline void ntfy_delete(struct ntfy_object *ntfy_obj)
+{
+       struct ntfy_event *ne;
+       struct notifier_block *nb;

-/*
- *  ======== ntfy_notify ========
- *  Purpose:
- *      Execute notify function (signal event or post message) for every
- *      element in the notification list that is to be notified about the
- *      event specified in event_mask.
- *  Parameters:
- *      ntfy_obj:      Handle returned from ntfy_create().
- *      event_mask: The type of event that has occurred.
- *  Returns:
- *  Requires:
- *      IS_VALID(ntfy_obj).
- *  Ensures:
+       spin_lock_bh(&ntfy_obj->ntfy_lock);
+       nb = ntfy_obj->head.head;
+       while (nb) {
+               ne = container_of(nb, struct ntfy_event, noti_block);
+               nb = nb->next;
+               kfree(ne);
+       }
+       spin_unlock_bh(&ntfy_obj->ntfy_lock);
+}
+
+/**
+ * ntfy_notify() - nofity all event register for an specific event.
+ * @ntfy_obj:  Pointer to the ntfy_object structure.
+ * @event:     event to be notified.
+ *
+ * This function traverses all the ntfy events registers and
+ * set the event with mach with @event.
  */
-extern void ntfy_notify(IN struct ntfy_object *ntfy_obj, IN u32 event_mask);
+static inline void ntfy_notify(struct ntfy_object *ntfy_obj, u32 event)
+{
+       spin_lock_bh(&ntfy_obj->ntfy_lock);
+       raw_notifier_call_chain(&ntfy_obj->head, event, NULL);
+       spin_unlock_bh(&ntfy_obj->ntfy_lock);
+}

-/*
- *  ======== ntfy_register ========
- *  Purpose:
- *      Add a notification element to the list. If the notification is already
- *      registered, and event_mask != 0, the notification will get posted for
- *      events specified in the new event mask. If the notification is already
- *      registered and event_mask == 0, the notification will be unregistered.
- *  Parameters:
- *      ntfy_obj:              Handle returned from ntfy_create().
- *      hnotification:      Handle to a dsp_notification object.
- *      event_mask:         Events to be notified about.
- *      notify_type:        Type of notification: DSP_SIGNALEVENT.
- *  Returns:
- *      DSP_SOK:            Success.
- *      DSP_EMEMORY:        Insufficient memory.
- *      DSP_EVALUE:         event_mask is 0 and hnotification was not
- *                          previously registered.
- *      DSP_EHANDLE:        NULL hnotification, hnotification event name
- *                          too long, or hnotification event name NULL.
- *  Requires:
- *      IS_VALID(ntfy_obj).
- *      hnotification != NULL.
- *      notify_type is DSP_SIGNALEVENT
- *  Ensures:
+
+
+/**
+ * ntfy_init() - Create and initialize a ntfy_event structure.
+ * @event:     event that the ntfy event will respond
+ * @type               event type (only DSP_SIGNALEVENT supported)
+ *
+ * This function create a ntfy_event element and sets the event it will
+ * respond the ntfy_event in order it can be used by the other ntfy functions.
+ * In case of success it will return a pointer to the ntfy_event struct
+ * created. Otherwise it will return NULL;
+ */
+
+static inline struct ntfy_event *ntfy_event_create(u32 event, u32 type)
+{
+       struct ntfy_event *ne;
+       ne = kmalloc(sizeof(struct ntfy_event), GFP_KERNEL);
+       if (ne) {
+               sync_init_event(&ne->sync_obj);
+               ne->noti_block.notifier_call = dsp_notifier_event;
+               ne->event = event;
+               ne->type = type;
+       }
+       return ne;
+}
+
+/**
+ * ntfy_register() - register new ntfy_event into a given ntfy_object
+ * @ntfy_obj:  Pointer to the ntfy_object structure.
+ * @noti:              Pointer to the handle to be returned to the user space.
+ * @event      event that the ntfy event will respond
+ * @type               event type (only DSP_SIGNALEVENT supported)
+ *
+ * This function register a new ntfy_event into the ntfy_object list,
+ * which will respond to the @event passed.
+ * This function will return DSP_SOK in case of error.
+ * DSP_EHANDLE in case of bad pointers and
+ * DSP_EMemory in case of no memory to create ntfy_event.
  */
-extern dsp_status ntfy_register(IN struct ntfy_object *ntfy_obj,
-                               IN struct dsp_notification *hnotification,
-                               IN u32 event_mask, IN u32 notify_type);
+static  inline dsp_status ntfy_register(struct ntfy_object *ntfy_obj,
+                        struct dsp_notification *noti,
+                        u32 event, u32 type)
+{
+       struct ntfy_event *ne;
+       dsp_status status = DSP_SOK;
+
+       if (!noti || !ntfy_obj) {
+               status = DSP_EHANDLE;
+               goto func_end;
+       }
+       if (!event) {
+               status = DSP_EINVALIDARG;
+               goto func_end;
+       }
+       ne = ntfy_event_create(event, type);
+       if (!ne) {
+               status = DSP_EMEMORY;
+               goto func_end;
+       }
+       noti->handle = &ne->sync_obj;
+
+       spin_lock_bh(&ntfy_obj->ntfy_lock);
+       raw_notifier_chain_register(&ntfy_obj->head, &ne->noti_block);
+       spin_unlock_bh(&ntfy_obj->ntfy_lock);
+func_end:
+       return status;
+}
+
+/**
+ * ntfy_unregister() - unregister a ntfy_event from a given ntfy_object
+ * @ntfy_obj:  Pointer to the ntfy_object structure.
+ * @noti:              Pointer to the event that will be removed.
+ *
+ * This function unregister a ntfy_event from the ntfy_object list,
+ * @noti contains the event which is wanted to be removed.
+ * This function will return DSP_SOK in case of error.
+ * DSP_EHANDLE in case of bad pointers and
+ * DSP_EMemory in case of no memory to create ntfy_event.
+ */
+static  inline dsp_status ntfy_unregister(struct ntfy_object *ntfy_obj,
+                        struct dsp_notification *noti)
+{
+       dsp_status status = DSP_SOK;
+       struct ntfy_event *ne;
+
+       if (!noti || !ntfy_obj) {
+               status = DSP_EHANDLE;
+               goto func_end;
+       }
+
+       ne = container_of((struct sync_object *)noti, struct ntfy_event,
+                                                               sync_obj);
+       spin_lock_bh(&ntfy_obj->ntfy_lock);
+       raw_notifier_chain_unregister(&ntfy_obj->head,
+                                               &ne->noti_block);
+       kfree(ne);
+       spin_unlock_bh(&ntfy_obj->ntfy_lock);
+func_end:
+       return status;
+}

-#endif /* NTFY_ */
+#endif                         /* NTFY_ */
diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
index 462d54a..a2ea698 100644
--- a/drivers/dsp/bridge/services/ntfy.c
+++ b/drivers/dsp/bridge/services/ntfy.c
@@ -16,214 +16,16 @@ 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */

-/*  ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/*  ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/std.h>
-#include <dspbridge/dbdefs.h>
-#include <dspbridge/errbase.h>
-
-/*  ----------------------------------- Trace & Debug */
-#include <dspbridge/dbc.h>
-
-/*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
-#include <dspbridge/mem.h>
-#include <dspbridge/sync.h>
-
 /*  ----------------------------------- This */
 #include <dspbridge/ntfy.h>

-/*  ----------------------------------- Defines, Data Structures, Typedefs */
-#define NTFY_SIGNATURE      0x5946544e /* "YFTN" */
-
-/*
- *  ======== notifier ========
- *  This object will be created when a client registers for events.
- */
-struct notifier {
-       struct list_head list_elem;
-       u32 event_mask;         /* Events to be notified about */
-       u32 notify_type;        /* Type of notification to be sent */
-
-       /*
-        *  We keep a copy of the event name to check if the event has
-        *  already been registered. (SYNC also keeps a copy of the name).
-        */
-       char *pstr_name;        /* Name of event */
-       bhandle event_obj;      /* Handle for notification */
-       struct sync_object *sync_obj;
-};
-
-/*  ----------------------------------- Function Prototypes */
-static void delete_notify(struct notifier *notifier_obj);
-
-/*
- *  ======== ntfy_delete ========
- *  Purpose:
- *      Free resources allocated in ntfy_create.
- */
-void ntfy_delete(struct ntfy_object *ntfy_obj)
+int dsp_notifier_event(struct notifier_block *this, unsigned long event,
+                          void *data)
 {
-       struct notifier *notifier_obj;
-
-       DBC_REQUIRE(MEM_IS_VALID_HANDLE(ntfy_obj, NTFY_SIGNATURE));
-
-       /* Remove any elements remaining in list */
-       if (ntfy_obj->notify_list) {
-               while ((notifier_obj =
-                     (struct notifier *)lst_get_head(ntfy_obj->notify_list))) {
-                       delete_notify(notifier_obj);
-               }
-               DBC_ASSERT(LST_IS_EMPTY(ntfy_obj->notify_list));
-               kfree(ntfy_obj->notify_list);
-       }
+       struct  ntfy_event *ne = container_of(this, struct ntfy_event,
+                                                       noti_block);
+       if (ne->event & event)
+               sync_set_event(&ne->sync_obj);
+       return NOTIFY_OK;
 }

-/*
- *  ======== ntfy_notify ========
- *  Purpose:
- *      Execute notify function (signal event) for every
- *      element in the notification list that is to be notified about the
- *      event specified in event_mask.
- */
-void ntfy_notify(struct ntfy_object *ntfy_obj, u32 event_mask)
-{
-       struct notifier *notifier_obj;
-
-       DBC_REQUIRE(MEM_IS_VALID_HANDLE(ntfy_obj, NTFY_SIGNATURE));
-
-       /*
-        *  Go through notify_list and notify all clients registered for
-        *  event_mask events.
-        */
-
-       spin_lock_bh(&ntfy_obj->ntfy_lock);
-
-       notifier_obj = (struct notifier *)lst_first(ntfy_obj->notify_list);
-       while (notifier_obj != NULL) {
-               if (notifier_obj->event_mask & event_mask) {
-                       /* Notify */
-                       if (notifier_obj->notify_type == DSP_SIGNALEVENT)
-                               (void)sync_set_event(notifier_obj->sync_obj);
-
-               }
-               notifier_obj =
-                   (struct notifier *)lst_next(ntfy_obj->notify_list,
-                                               (struct list_head *)
-                                               notifier_obj);
-       }
-
-       spin_unlock_bh(&ntfy_obj->ntfy_lock);
-}
-
-/*
- *  ======== ntfy_register ========
- *  Purpose:
- *      Add a notification element to the list. If the notification is already
- *      registered, and event_mask != 0, the notification will get posted for
- *      events specified in the new event mask. If the notification is already
- *      registered and event_mask == 0, the notification will be unregistered.
- */
-dsp_status ntfy_register(struct ntfy_object *ntfy_obj,
-                        struct dsp_notification *hnotification,
-                        u32 event_mask, u32 notify_type)
-{
-       struct notifier *notifier_obj;
-       dsp_status status = DSP_SOK;
-
-       DBC_REQUIRE(MEM_IS_VALID_HANDLE(ntfy_obj, NTFY_SIGNATURE));
-
-       if (hnotification == NULL)
-               status = DSP_EHANDLE;
-
-       /* Return DSP_ENOTIMPL if notify_type is not supported */
-       if (DSP_SUCCEEDED(status)) {
-               if (!IS_VALID_NOTIFY_MASK(notify_type))
-                       status = DSP_ENOTIMPL;
-
-       }
-
-       if (DSP_FAILED(status))
-               return status;
-
-       spin_lock_bh(&ntfy_obj->ntfy_lock);
-
-       notifier_obj = (struct notifier *)lst_first(ntfy_obj->notify_list);
-       while (notifier_obj != NULL) {
-               /* If there is more than one notification type, each
-                * type may require its own handler code. */
-
-               if (hnotification->handle == notifier_obj->sync_obj) {
-                       /* found */
-                       break;
-               }
-               notifier_obj =
-                   (struct notifier *)lst_next(ntfy_obj->notify_list,
-                                               (struct list_head *)
-                                               notifier_obj);
-       }
-       if (notifier_obj == NULL) {
-               /* Not registered */
-               if (event_mask == 0) {
-                       status = DSP_EVALUE;
-               } else {
-                       /* Allocate notifier object, add to list */
-                       notifier_obj = mem_calloc(sizeof(struct notifier),
-                                                 MEM_PAGED);
-                       if (notifier_obj == NULL)
-                               status = DSP_EMEMORY;
-
-               }
-               if (DSP_SUCCEEDED(status)) {
-                       lst_init_elem((struct list_head *)notifier_obj);
-                       /* If there is more than one notification type, each
-                        * type may require its own handler code. */
-                       notifier_obj->sync_obj = kzalloc(
-                                       sizeof(struct sync_object), GFP_KERNEL);
-
-                       if (notifier_obj->sync_obj)
-                               sync_init_event(notifier_obj->sync_obj);
-                       else
-                               status = DSP_EMEMORY;
-
-                       hnotification->handle = notifier_obj->sync_obj;
-
-                       if (DSP_SUCCEEDED(status)) {
-                               notifier_obj->event_mask = event_mask;
-                               notifier_obj->notify_type = notify_type;
-                               lst_put_tail(ntfy_obj->notify_list,
-                                            (struct list_head *)notifier_obj);
-                       } else {
-                               delete_notify(notifier_obj);
-                       }
-               }
-       } else {
-               /* Found in list */
-               if (event_mask == 0) {
-                       /* Remove from list and free */
-                       lst_remove_elem(ntfy_obj->notify_list,
-                                       (struct list_head *)notifier_obj);
-                       delete_notify(notifier_obj);
-               } else {
-                       /* Update notification mask (type shouldn't change) */
-                       notifier_obj->event_mask = event_mask;
-               }
-       }
-       spin_unlock_bh(&ntfy_obj->ntfy_lock);
-       return status;
-}
-
-/*
- *  ======== delete_notify ========
- *  Purpose:
- *      Free the notification object.
- */
-static void delete_notify(struct notifier *notifier_obj)
-{
-       kfree(notifier_obj->sync_obj);
-       kfree(notifier_obj->pstr_name);
-
-       kfree(notifier_obj);
-}
diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
index e969d35..a2f98e9 100644
--- a/drivers/dsp/bridge/wmd/chnl_sm.c
+++ b/drivers/dsp/bridge/wmd/chnl_sm.c
@@ -924,8 +924,11 @@  dsp_status bridge_chnl_register_notify(struct chnl_object *chnl_obj,

        DBC_ASSERT(!(event_mask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));

-       status = ntfy_register(chnl_obj->ntfy_obj, hnotification, event_mask,
-                              notify_type);
+       if (event_mask)
+               status = ntfy_register(chnl_obj->ntfy_obj, hnotification,
+                                               event_mask, notify_type);
+       else
+               status = ntfy_unregister(chnl_obj->ntfy_obj, hnotification);

        return status;
 }
diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
index 1bfef23..dae6e67 100644
--- a/drivers/dsp/bridge/wmd/msg_sm.c
+++ b/drivers/dsp/bridge/wmd/msg_sm.c
@@ -526,9 +526,12 @@  dsp_status bridge_msg_register_notify(struct msg_queue *msg_queue_obj,
                goto func_end;
        }

-       status =
-           ntfy_register(msg_queue_obj->ntfy_obj, hnotification, event_mask,
-                         notify_type);
+       if (event_mask)
+               status = ntfy_register(msg_queue_obj->ntfy_obj, hnotification,
+                                               event_mask, notify_type);
+       else
+               status = ntfy_unregister(msg_queue_obj->ntfy_obj,
+                                                       hnotification);

        if (status == DSP_EVALUE) {
                /*  Not registered. Ok, since we couldn't have known. Node
diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
index dff8132..231b05e 100644
--- a/drivers/dsp/bridge/wmd/ue_deh.c
+++ b/drivers/dsp/bridge/wmd/ue_deh.c
@@ -173,8 +173,12 @@  dsp_status bridge_deh_register_notify(struct deh_mgr *hdeh_mgr, u32 event_mask,
        struct deh_mgr *deh_mgr_obj = (struct deh_mgr *)hdeh_mgr;

        if (MEM_IS_VALID_HANDLE(deh_mgr_obj, SIGNATURE)) {
-               status = ntfy_register(deh_mgr_obj->ntfy_obj, hnotification,
-                                      event_mask, notify_type);
+               if (event_mask)
+                       status = ntfy_register(deh_mgr_obj->ntfy_obj,
+                               hnotification, event_mask, notify_type);
+               else
+                       status = ntfy_unregister(deh_mgr_obj->ntfy_obj,
+                                                       hnotification);
        }

        return status;