ALSA: hda - Add support for Thinkpad Edge conexant chip
[safe/jmp/linux-2.6] / net / tipc / ref.c
index 1853cca..8dea665 100644 (file)
 
 #include "core.h"
 #include "ref.h"
-#include "port.h"
-#include "subscr.h"
-#include "name_distr.h"
-#include "name_table.h"
-#include "config.h"
-#include "discover.h"
-#include "bearer.h"
-#include "node.h"
-#include "bcast.h"
 
 /**
  * struct reference - TIPC object reference entry
  * @object: pointer to object associated with reference entry
  * @lock: spinlock controlling access to object
- * @data: reference value for object (combines instance & array index info)
+ * @ref: reference value for object (combines instance & array index info)
  */
 
 struct reference {
        void *object;
        spinlock_t lock;
-       union {
-               u32 next_plus_upper;
-               u32 reference;
-       } data;
+       u32 ref;
 };
 
 /**
@@ -135,7 +123,7 @@ int tipc_ref_table_init(u32 requested_size, u32 start)
        tipc_ref_table.index_mask = actual_size - 1;
        tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask;
 
-       return TIPC_OK;
+       return 0;
 }
 
 /**
@@ -154,18 +142,22 @@ void tipc_ref_table_stop(void)
 /**
  * tipc_ref_acquire - create reference to an object
  *
- * Return a unique reference value which can be translated back to the pointer
- * 'object' at a later time.  Also, pass back a pointer to the lock protecting
- * the object, but without locking it.
+ * Register an object pointer in reference table and lock the object.
+ * Returns a unique reference value that is used from then on to retrieve the
+ * object pointer, or to determine that the object has been deregistered.
+ *
+ * Note: The object is returned in the locked state so that the caller can
+ * register a partially initialized object, without running the risk that
+ * the object will be accessed before initialization is complete.
  */
 
 u32 tipc_ref_acquire(void *object, spinlock_t **lock)
 {
-       struct reference *entry;
        u32 index;
        u32 index_mask;
        u32 next_plus_upper;
-       u32 reference;
+       u32 ref;
+       struct reference *entry = NULL;
 
        if (!object) {
                err("Attempt to acquire reference to non-existent object\n");
@@ -183,31 +175,37 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
                index = tipc_ref_table.first_free;
                entry = &(tipc_ref_table.entries[index]);
                index_mask = tipc_ref_table.index_mask;
-               /* take lock in case a previous user of entry still holds it */
-               spin_lock_bh(&entry->lock);
-               next_plus_upper = entry->data.next_plus_upper;
+               next_plus_upper = entry->ref;
                tipc_ref_table.first_free = next_plus_upper & index_mask;
-               reference = (next_plus_upper & ~index_mask) + index;
-               entry->data.reference = reference;
-               entry->object = object;
-               spin_unlock_bh(&entry->lock);
-               *lock = &entry->lock;
+               ref = (next_plus_upper & ~index_mask) + index;
        }
        else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
                index = tipc_ref_table.init_point++;
                entry = &(tipc_ref_table.entries[index]);
                spin_lock_init(&entry->lock);
-               reference = tipc_ref_table.start_mask + index;
-               entry->data.reference = reference;
-               entry->object = object;
-               *lock = &entry->lock;
+               ref = tipc_ref_table.start_mask + index;
        }
        else {
-               reference = 0;
+               ref = 0;
        }
        write_unlock_bh(&ref_table_lock);
 
-       return reference;
+       /*
+        * Grab the lock so no one else can modify this entry
+        * While we assign its ref value & object pointer
+        */
+       if (entry) {
+               spin_lock_bh(&entry->lock);
+               entry->ref = ref;
+               entry->object = object;
+               *lock = &entry->lock;
+               /*
+                * keep it locked, the caller is responsible
+                * for unlocking this when they're done with it
+                */
+       }
+
+       return ref;
 }
 
 /**
@@ -238,26 +236,25 @@ void tipc_ref_discard(u32 ref)
                err("Attempt to discard reference to non-existent object\n");
                goto exit;
        }
-       if (entry->data.reference != ref) {
+       if (entry->ref != ref) {
                err("Attempt to discard non-existent reference\n");
                goto exit;
        }
 
        /*
-        * mark entry as unused; increment upper bits of entry's data field
+        * mark entry as unused; increment instance part of entry's reference
         * to invalidate any subsequent references
         */
 
        entry->object = NULL;
-       entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
+       entry->ref = (ref & ~index_mask) + (index_mask + 1);
 
        /* append entry to free entry list */
 
        if (tipc_ref_table.first_free == 0)
                tipc_ref_table.first_free = index;
        else
-               tipc_ref_table.entries[tipc_ref_table.last_free].
-                       data.next_plus_upper |= index;
+               tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index;
        tipc_ref_table.last_free = index;
 
 exit:
@@ -271,15 +268,15 @@ exit:
 void *tipc_ref_lock(u32 ref)
 {
        if (likely(tipc_ref_table.entries)) {
-               struct reference *r;
-
-               r = &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
-
-               if (likely(r->data.reference != 0)) {
-                       spin_lock_bh(&r->lock);
-                       if (likely((r->data.reference == ref) && (r->object)))
-                               return r->object;
-                       spin_unlock_bh(&r->lock);
+               struct reference *entry;
+
+               entry = &tipc_ref_table.entries[ref &
+                                               tipc_ref_table.index_mask];
+               if (likely(entry->ref != 0)) {
+                       spin_lock_bh(&entry->lock);
+                       if (likely((entry->ref == ref) && (entry->object)))
+                               return entry->object;
+                       spin_unlock_bh(&entry->lock);
                }
        }
        return NULL;
@@ -292,15 +289,14 @@ void *tipc_ref_lock(u32 ref)
 void tipc_ref_unlock(u32 ref)
 {
        if (likely(tipc_ref_table.entries)) {
-               struct reference *r;
-
-               r = &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+               struct reference *entry;
 
-               if (likely((r->data.reference == ref) && (r->object)))
-                       spin_unlock_bh(&r->lock);
+               entry = &tipc_ref_table.entries[ref &
+                                               tipc_ref_table.index_mask];
+               if (likely((entry->ref == ref) && (entry->object)))
+                       spin_unlock_bh(&entry->lock);
                else
-                       err("tipc_ref_unlock() invoked using "
-                           "invalid reference\n");
+                       err("Attempt to unlock non-existent reference\n");
        }
 }
 
@@ -311,11 +307,12 @@ void tipc_ref_unlock(u32 ref)
 void *tipc_ref_deref(u32 ref)
 {
        if (likely(tipc_ref_table.entries)) {
-               struct reference *r;
+               struct reference *entry;
 
-               r = &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
-               if (likely(r->data.reference == ref))
-                       return r->object;
+               entry = &tipc_ref_table.entries[ref &
+                                               tipc_ref_table.index_mask];
+               if (likely(entry->ref == ref))
+                       return entry->object;
        }
        return NULL;
 }