ASoC: tlv320aic32x4: Only enable with common clock
[sfrench/cifs-2.6.git] / lib / test_xarray.c
index c596a957f7643e56b45956a61ed999980568ad53..5d4bad8bd96a0621018f6dc8aaa5f4b73305decb 100644 (file)
@@ -40,9 +40,9 @@ static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp)
 
 static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp)
 {
-       u32 id = 0;
+       u32 id;
 
-       XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_index(index),
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(index), xa_limit_32b,
                                gfp) != 0);
        XA_BUG_ON(xa, id != index);
 }
@@ -107,8 +107,11 @@ static noinline void check_xas_retry(struct xarray *xa)
        XA_BUG_ON(xa, xas.xa_node != XAS_RESTART);
        XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
        XA_BUG_ON(xa, xas.xa_node != NULL);
+       rcu_read_unlock();
 
        XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
+
+       rcu_read_lock();
        XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas)));
        xas.xa_node = XAS_RESTART;
        XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
@@ -343,7 +346,7 @@ static noinline void check_cmpxchg(struct xarray *xa)
 
        XA_BUG_ON(xa, !xa_empty(xa));
        XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL);
-       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EEXIST);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EBUSY);
        XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS);
        XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS);
        XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE);
@@ -358,46 +361,65 @@ static noinline void check_reserve(struct xarray *xa)
 {
        void *entry;
        unsigned long index;
+       int count;
 
        /* An array with a reserved entry is not empty */
        XA_BUG_ON(xa, !xa_empty(xa));
-       xa_reserve(xa, 12345678, GFP_KERNEL);
+       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_empty(xa));
        XA_BUG_ON(xa, xa_load(xa, 12345678));
        xa_release(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* Releasing a used entry does nothing */
-       xa_reserve(xa, 12345678, GFP_KERNEL);
+       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL);
        xa_release(xa, 12345678);
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
-       /* cmpxchg sees a reserved entry as NULL */
-       xa_reserve(xa, 12345678, GFP_KERNEL);
-       XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, NULL, xa_mk_value(12345678),
-                               GFP_NOWAIT) != NULL);
+       /* cmpxchg sees a reserved entry as ZERO */
+       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, XA_ZERO_ENTRY,
+                               xa_mk_value(12345678), GFP_NOWAIT) != NULL);
        xa_release(xa, 12345678);
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
-       /* But xa_insert does not */
-       xa_reserve(xa, 12345678, GFP_KERNEL);
+       /* xa_insert treats it as busy */
+       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) !=
-                       -EEXIST);
+                       -EBUSY);
        XA_BUG_ON(xa, xa_empty(xa));
        XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* Can iterate through a reserved entry */
        xa_store_index(xa, 5, GFP_KERNEL);
-       xa_reserve(xa, 6, GFP_KERNEL);
+       XA_BUG_ON(xa, xa_reserve(xa, 6, GFP_KERNEL) != 0);
        xa_store_index(xa, 7, GFP_KERNEL);
 
+       count = 0;
        xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, index != 5 && index != 7);
+               count++;
+       }
+       XA_BUG_ON(xa, count != 2);
+
+       /* If we free a reserved entry, we should be able to allocate it */
+       if (xa->xa_flags & XA_FLAGS_ALLOC) {
+               u32 id;
+
+               XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_value(8),
+                                       XA_LIMIT(5, 10), GFP_KERNEL) != 0);
+               XA_BUG_ON(xa, id != 8);
+
+               xa_release(xa, 6);
+               XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_value(6),
+                                       XA_LIMIT(5, 10), GFP_KERNEL) != 0);
+               XA_BUG_ON(xa, id != 6);
        }
+
        xa_destroy(xa);
 }
 
@@ -586,64 +608,194 @@ static noinline void check_multi_store(struct xarray *xa)
 #endif
 }
 
-static DEFINE_XARRAY_ALLOC(xa0);
-
-static noinline void check_xa_alloc(void)
+static noinline void check_xa_alloc_1(struct xarray *xa, unsigned int base)
 {
        int i;
        u32 id;
 
-       /* An empty array should assign 0 to the first alloc */
-       xa_alloc_index(&xa0, 0, GFP_KERNEL);
+       XA_BUG_ON(xa, !xa_empty(xa));
+       /* An empty array should assign %base to the first alloc */
+       xa_alloc_index(xa, base, GFP_KERNEL);
 
        /* Erasing it should make the array empty again */
-       xa_erase_index(&xa0, 0);
-       XA_BUG_ON(&xa0, !xa_empty(&xa0));
+       xa_erase_index(xa, base);
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       /* And it should assign %base again */
+       xa_alloc_index(xa, base, GFP_KERNEL);
+
+       /* Allocating and then erasing a lot should not lose base */
+       for (i = base + 1; i < 2 * XA_CHUNK_SIZE; i++)
+               xa_alloc_index(xa, i, GFP_KERNEL);
+       for (i = base; i < 2 * XA_CHUNK_SIZE; i++)
+               xa_erase_index(xa, i);
+       xa_alloc_index(xa, base, GFP_KERNEL);
 
-       /* And it should assign 0 again */
-       xa_alloc_index(&xa0, 0, GFP_KERNEL);
+       /* Destroying the array should do the same as erasing */
+       xa_destroy(xa);
+
+       /* And it should assign %base again */
+       xa_alloc_index(xa, base, GFP_KERNEL);
 
-       /* The next assigned ID should be 1 */
-       xa_alloc_index(&xa0, 1, GFP_KERNEL);
-       xa_erase_index(&xa0, 1);
+       /* The next assigned ID should be base+1 */
+       xa_alloc_index(xa, base + 1, GFP_KERNEL);
+       xa_erase_index(xa, base + 1);
 
        /* Storing a value should mark it used */
-       xa_store_index(&xa0, 1, GFP_KERNEL);
-       xa_alloc_index(&xa0, 2, GFP_KERNEL);
+       xa_store_index(xa, base + 1, GFP_KERNEL);
+       xa_alloc_index(xa, base + 2, GFP_KERNEL);
 
-       /* If we then erase 0, it should be free */
-       xa_erase_index(&xa0, 0);
-       xa_alloc_index(&xa0, 0, GFP_KERNEL);
+       /* If we then erase base, it should be free */
+       xa_erase_index(xa, base);
+       xa_alloc_index(xa, base, GFP_KERNEL);
 
-       xa_erase_index(&xa0, 1);
-       xa_erase_index(&xa0, 2);
+       xa_erase_index(xa, base + 1);
+       xa_erase_index(xa, base + 2);
 
        for (i = 1; i < 5000; i++) {
-               xa_alloc_index(&xa0, i, GFP_KERNEL);
+               xa_alloc_index(xa, base + i, GFP_KERNEL);
        }
 
-       xa_destroy(&xa0);
+       xa_destroy(xa);
 
-       id = 0xfffffffeU;
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
+       /* Check that we fail properly at the limit of allocation */
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(UINT_MAX - 1),
+                               XA_LIMIT(UINT_MAX - 1, UINT_MAX),
                                GFP_KERNEL) != 0);
-       XA_BUG_ON(&xa0, id != 0xfffffffeU);
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
+       XA_BUG_ON(xa, id != 0xfffffffeU);
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(UINT_MAX),
+                               XA_LIMIT(UINT_MAX - 1, UINT_MAX),
                                GFP_KERNEL) != 0);
-       XA_BUG_ON(&xa0, id != 0xffffffffU);
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
-                               GFP_KERNEL) != -ENOSPC);
-       XA_BUG_ON(&xa0, id != 0xffffffffU);
-       xa_destroy(&xa0);
-
-       id = 10;
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
-                               GFP_KERNEL) != -ENOSPC);
-       XA_BUG_ON(&xa0, xa_store_index(&xa0, 3, GFP_KERNEL) != 0);
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
-                               GFP_KERNEL) != -ENOSPC);
-       xa_erase_index(&xa0, 3);
-       XA_BUG_ON(&xa0, !xa_empty(&xa0));
+       XA_BUG_ON(xa, id != 0xffffffffU);
+       id = 3;
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(0),
+                               XA_LIMIT(UINT_MAX - 1, UINT_MAX),
+                               GFP_KERNEL) != -EBUSY);
+       XA_BUG_ON(xa, id != 3);
+       xa_destroy(xa);
+
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(10), XA_LIMIT(10, 5),
+                               GFP_KERNEL) != -EBUSY);
+       XA_BUG_ON(xa, xa_store_index(xa, 3, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(10), XA_LIMIT(10, 5),
+                               GFP_KERNEL) != -EBUSY);
+       xa_erase_index(xa, 3);
+       XA_BUG_ON(xa, !xa_empty(xa));
+}
+
+static noinline void check_xa_alloc_2(struct xarray *xa, unsigned int base)
+{
+       unsigned int i, id;
+       unsigned long index;
+       void *entry;
+
+       /* Allocate and free a NULL and check xa_empty() behaves */
+       XA_BUG_ON(xa, !xa_empty(xa));
+       XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != base);
+       XA_BUG_ON(xa, xa_empty(xa));
+       XA_BUG_ON(xa, xa_erase(xa, id) != NULL);
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       /* Ditto, but check destroy instead of erase */
+       XA_BUG_ON(xa, !xa_empty(xa));
+       XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != base);
+       XA_BUG_ON(xa, xa_empty(xa));
+       xa_destroy(xa);
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       for (i = base; i < base + 10; i++) {
+               XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b,
+                                       GFP_KERNEL) != 0);
+               XA_BUG_ON(xa, id != i);
+       }
+
+       XA_BUG_ON(xa, xa_store(xa, 3, xa_mk_index(3), GFP_KERNEL) != NULL);
+       XA_BUG_ON(xa, xa_store(xa, 4, xa_mk_index(4), GFP_KERNEL) != NULL);
+       XA_BUG_ON(xa, xa_store(xa, 4, NULL, GFP_KERNEL) != xa_mk_index(4));
+       XA_BUG_ON(xa, xa_erase(xa, 5) != NULL);
+       XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != 5);
+
+       xa_for_each(xa, index, entry) {
+               xa_erase_index(xa, index);
+       }
+
+       for (i = base; i < base + 9; i++) {
+               XA_BUG_ON(xa, xa_erase(xa, i) != NULL);
+               XA_BUG_ON(xa, xa_empty(xa));
+       }
+       XA_BUG_ON(xa, xa_erase(xa, 8) != NULL);
+       XA_BUG_ON(xa, xa_empty(xa));
+       XA_BUG_ON(xa, xa_erase(xa, base + 9) != NULL);
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       xa_destroy(xa);
+}
+
+static noinline void check_xa_alloc_3(struct xarray *xa, unsigned int base)
+{
+       struct xa_limit limit = XA_LIMIT(1, 0x3fff);
+       u32 next = 0;
+       unsigned int i, id;
+       unsigned long index;
+       void *entry;
+
+       XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(1), limit,
+                               &next, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != 1);
+
+       next = 0x3ffd;
+       XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(0x3ffd), limit,
+                               &next, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != 0x3ffd);
+       xa_erase_index(xa, 0x3ffd);
+       xa_erase_index(xa, 1);
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       for (i = 0x3ffe; i < 0x4003; i++) {
+               if (i < 0x4000)
+                       entry = xa_mk_index(i);
+               else
+                       entry = xa_mk_index(i - 0x3fff);
+               XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, entry, limit,
+                                       &next, GFP_KERNEL) != (id == 1));
+               XA_BUG_ON(xa, xa_mk_index(id) != entry);
+       }
+
+       /* Check wrap-around is handled correctly */
+       if (base != 0)
+               xa_erase_index(xa, base);
+       xa_erase_index(xa, base + 1);
+       next = UINT_MAX;
+       XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(UINT_MAX),
+                               xa_limit_32b, &next, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != UINT_MAX);
+       XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base),
+                               xa_limit_32b, &next, GFP_KERNEL) != 1);
+       XA_BUG_ON(xa, id != base);
+       XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base + 1),
+                               xa_limit_32b, &next, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, id != base + 1);
+
+       xa_for_each(xa, index, entry)
+               xa_erase_index(xa, index);
+
+       XA_BUG_ON(xa, !xa_empty(xa));
+}
+
+static DEFINE_XARRAY_ALLOC(xa0);
+static DEFINE_XARRAY_ALLOC1(xa1);
+
+static noinline void check_xa_alloc(void)
+{
+       check_xa_alloc_1(&xa0, 0);
+       check_xa_alloc_1(&xa1, 1);
+       check_xa_alloc_2(&xa0, 0);
+       check_xa_alloc_2(&xa1, 1);
+       check_xa_alloc_3(&xa0, 0);
+       check_xa_alloc_3(&xa1, 1);
 }
 
 static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
@@ -1194,9 +1346,8 @@ static void check_align_1(struct xarray *xa, char *name)
        void *entry;
 
        for (i = 0; i < 8; i++) {
-               id = 0;
-               XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL)
-                               != 0);
+               XA_BUG_ON(xa, xa_alloc(xa, &id, name + i, xa_limit_32b,
+                                       GFP_KERNEL) != 0);
                XA_BUG_ON(xa, id != i);
        }
        xa_for_each(xa, index, entry)
@@ -1204,6 +1355,30 @@ static void check_align_1(struct xarray *xa, char *name)
        xa_destroy(xa);
 }
 
+/*
+ * We should always be able to store without allocating memory after
+ * reserving a slot.
+ */
+static void check_align_2(struct xarray *xa, char *name)
+{
+       int i;
+
+       XA_BUG_ON(xa, !xa_empty(xa));
+
+       for (i = 0; i < 8; i++) {
+               XA_BUG_ON(xa, xa_store(xa, 0, name + i, GFP_KERNEL) != NULL);
+               xa_erase(xa, 0);
+       }
+
+       for (i = 0; i < 8; i++) {
+               XA_BUG_ON(xa, xa_reserve(xa, 0, GFP_KERNEL) != 0);
+               XA_BUG_ON(xa, xa_store(xa, 0, name + i, 0) != NULL);
+               xa_erase(xa, 0);
+       }
+
+       XA_BUG_ON(xa, !xa_empty(xa));
+}
+
 static noinline void check_align(struct xarray *xa)
 {
        char name[] = "Motorola 68000";
@@ -1212,7 +1387,7 @@ static noinline void check_align(struct xarray *xa)
        check_align_1(xa, name + 1);
        check_align_1(xa, name + 2);
        check_align_1(xa, name + 3);
-//     check_align_2(xa, name);
+       check_align_2(xa, name);
 }
 
 static LIST_HEAD(shadow_nodes);
@@ -1354,6 +1529,7 @@ static int xarray_checks(void)
        check_xas_erase(&array);
        check_cmpxchg(&array);
        check_reserve(&array);
+       check_reserve(&xa0);
        check_multi_store(&array);
        check_xa_alloc();
        check_find(&array);