gpio: gpiolib: Support for open source/emitter gpios
[linux-2.6.git] / include / linux / nodemask.h
index 52c54a5..7afc363 100644 (file)
@@ -14,6 +14,8 @@
  * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c.
  * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c.
+ * For details of nodes_onto(), see bitmap_onto in lib/bitmap.c.
+ * For details of nodes_fold(), see bitmap_fold in lib/bitmap.c.
  *
  * The available nodemask operations are:
  *
  * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
  * int nodelist_parse(buf, map)                Parse ascii string as nodelist
  * int node_remap(oldbit, old, new)    newbit = map(old, new)(oldbit)
- * int nodes_remap(dst, src, old, new) *dst = map(old, new)(dst)
+ * void nodes_remap(dst, src, old, new)        *dst = map(old, new)(src)
+ * void nodes_onto(dst, orig, relmap)  *dst = orig relative to relmap
+ * void nodes_fold(dst, orig, sz)      dst bits = orig bits mod sz
  *
  * for_each_node_mask(node, mask)      for-loop node over mask
  *
  * int num_online_nodes()              Number of online Nodes
  * int num_possible_nodes()            Number of all possible Nodes
  *
+ * int node_random(mask)               Random node with set bit in mask
+ *
  * int node_online(node)               Is some node online?
  * int node_possible(node)             Is some node possible?
  *
- * int any_online_node(mask)           First online node in mask
- *
  * node_set_online(node)               set bit 'node' in node_online_map
  * node_set_offline(node)              clear bit 'node' in node_online_map
  *
  *    to generate slightly worse code.  So use a simple one-line #define
  *    for node_isset(), instead of wrapping an inline inside a macro, the
  *    way we do the other calls.
+ *
+ * NODEMASK_SCRATCH
+ * When doing above logical AND, OR, XOR, Remap operations the callers tend to
+ * need temporary nodemask_t's on the stack. But if NODES_SHIFT is large,
+ * nodemask_t's consume too much stack space.  NODEMASK_SCRATCH is a helper
+ * for such situations. See below and CPUMASK_ALLOC also.
  */
 
 #include <linux/kernel.h>
@@ -235,14 +245,19 @@ static inline int __next_node(int n, const nodemask_t *srcp)
        return min_t(int,MAX_NUMNODES,find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
 }
 
+static inline void init_nodemask_of_node(nodemask_t *mask, int node)
+{
+       nodes_clear(*mask);
+       node_set(node, *mask);
+}
+
 #define nodemask_of_node(node)                                         \
 ({                                                                     \
        typeof(_unused_nodemask_arg_) m;                                \
        if (sizeof(m) == sizeof(unsigned long)) {                       \
-               m.bits[0] = 1UL<<(node);                                \
+               m.bits[0] = 1UL << (node);                              \
        } else {                                                        \
-               nodes_clear(m);                                         \
-               node_set((node), m);                                    \
+               init_nodemask_of_node(&m, (node));                      \
        }                                                               \
        m;                                                              \
 })
@@ -326,6 +341,22 @@ static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
        bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
 }
 
+#define nodes_onto(dst, orig, relmap) \
+               __nodes_onto(&(dst), &(orig), &(relmap), MAX_NUMNODES)
+static inline void __nodes_onto(nodemask_t *dstp, const nodemask_t *origp,
+               const nodemask_t *relmapp, int nbits)
+{
+       bitmap_onto(dstp->bits, origp->bits, relmapp->bits, nbits);
+}
+
+#define nodes_fold(dst, orig, sz) \
+               __nodes_fold(&(dst), &(orig), sz, MAX_NUMNODES)
+static inline void __nodes_fold(nodemask_t *dstp, const nodemask_t *origp,
+               int sz, int nbits)
+{
+       bitmap_fold(dstp->bits, origp->bits, sz, nbits);
+}
+
 #if MAX_NUMNODES > 1
 #define for_each_node_mask(node, mask)                 \
        for ((node) = first_node(mask);                 \
@@ -338,44 +369,147 @@ static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
 #endif /* MAX_NUMNODES */
 
 /*
+ * Bitmasks that are kept for all the nodes.
+ */
+enum node_states {
+       N_POSSIBLE,             /* The node could become online at some point */
+       N_ONLINE,               /* The node is online */
+       N_NORMAL_MEMORY,        /* The node has regular memory */
+#ifdef CONFIG_HIGHMEM
+       N_HIGH_MEMORY,          /* The node has regular or high memory */
+#else
+       N_HIGH_MEMORY = N_NORMAL_MEMORY,
+#endif
+       N_CPU,          /* The node has one or more cpus */
+       NR_NODE_STATES
+};
+
+/*
  * The following particular system nodemasks and operations
  * on them manage all possible and online nodes.
  */
 
-extern nodemask_t node_online_map;
-extern nodemask_t node_possible_map;
+extern nodemask_t node_states[NR_NODE_STATES];
 
 #if MAX_NUMNODES > 1
-#define num_online_nodes()     nodes_weight(node_online_map)
-#define num_possible_nodes()   nodes_weight(node_possible_map)
-#define node_online(node)      node_isset((node), node_online_map)
-#define node_possible(node)    node_isset((node), node_possible_map)
-#define first_online_node      first_node(node_online_map)
-#define next_online_node(nid)  next_node((nid), node_online_map)
+static inline int node_state(int node, enum node_states state)
+{
+       return node_isset(node, node_states[state]);
+}
+
+static inline void node_set_state(int node, enum node_states state)
+{
+       __node_set(node, &node_states[state]);
+}
+
+static inline void node_clear_state(int node, enum node_states state)
+{
+       __node_clear(node, &node_states[state]);
+}
+
+static inline int num_node_state(enum node_states state)
+{
+       return nodes_weight(node_states[state]);
+}
+
+#define for_each_node_state(__node, __state) \
+       for_each_node_mask((__node), node_states[__state])
+
+#define first_online_node      first_node(node_states[N_ONLINE])
+#define next_online_node(nid)  next_node((nid), node_states[N_ONLINE])
+
 extern int nr_node_ids;
+extern int nr_online_nodes;
+
+static inline void node_set_online(int nid)
+{
+       node_set_state(nid, N_ONLINE);
+       nr_online_nodes = num_node_state(N_ONLINE);
+}
+
+static inline void node_set_offline(int nid)
+{
+       node_clear_state(nid, N_ONLINE);
+       nr_online_nodes = num_node_state(N_ONLINE);
+}
+
 #else
-#define num_online_nodes()     1
-#define num_possible_nodes()   1
-#define node_online(node)      ((node) == 0)
-#define node_possible(node)    ((node) == 0)
+
+static inline int node_state(int node, enum node_states state)
+{
+       return node == 0;
+}
+
+static inline void node_set_state(int node, enum node_states state)
+{
+}
+
+static inline void node_clear_state(int node, enum node_states state)
+{
+}
+
+static inline int num_node_state(enum node_states state)
+{
+       return 1;
+}
+
+#define for_each_node_state(node, __state) \
+       for ( (node) = 0; (node) == 0; (node) = 1)
+
 #define first_online_node      0
 #define next_online_node(nid)  (MAX_NUMNODES)
 #define nr_node_ids            1
+#define nr_online_nodes                1
+
+#define node_set_online(node)     node_set_state((node), N_ONLINE)
+#define node_set_offline(node)    node_clear_state((node), N_ONLINE)
+
 #endif
 
-#define any_online_node(mask)                  \
-({                                             \
-       int node;                               \
-       for_each_node_mask(node, (mask))        \
-               if (node_online(node))          \
-                       break;                  \
-       node;                                   \
-})
+#if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1)
+extern int node_random(const nodemask_t *maskp);
+#else
+static inline int node_random(const nodemask_t *mask)
+{
+       return 0;
+}
+#endif
+
+#define node_online_map        node_states[N_ONLINE]
+#define node_possible_map      node_states[N_POSSIBLE]
+
+#define num_online_nodes()     num_node_state(N_ONLINE)
+#define num_possible_nodes()   num_node_state(N_POSSIBLE)
+#define node_online(node)      node_state((node), N_ONLINE)
+#define node_possible(node)    node_state((node), N_POSSIBLE)
+
+#define for_each_node(node)       for_each_node_state(node, N_POSSIBLE)
+#define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
+
+/*
+ * For nodemask scrach area.
+ * NODEMASK_ALLOC(type, name) allocates an object with a specified type and
+ * name.
+ */
+#if NODES_SHIFT > 8 /* nodemask_t > 256 bytes */
+#define NODEMASK_ALLOC(type, name, gfp_flags)  \
+                       type *name = kmalloc(sizeof(*name), gfp_flags)
+#define NODEMASK_FREE(m)                       kfree(m)
+#else
+#define NODEMASK_ALLOC(type, name, gfp_flags)  type _##name, *name = &_##name
+#define NODEMASK_FREE(m)                       do {} while (0)
+#endif
+
+/* A example struture for using NODEMASK_ALLOC, used in mempolicy. */
+struct nodemask_scratch {
+       nodemask_t      mask1;
+       nodemask_t      mask2;
+};
 
-#define node_set_online(node)     set_bit((node), node_online_map.bits)
-#define node_set_offline(node)    clear_bit((node), node_online_map.bits)
+#define NODEMASK_SCRATCH(x)                                            \
+                       NODEMASK_ALLOC(struct nodemask_scratch, x,      \
+                                       GFP_KERNEL | __GFP_NORETRY)
+#define NODEMASK_SCRATCH_FREE(x)       NODEMASK_FREE(x)
 
-#define for_each_node(node)       for_each_node_mask((node), node_possible_map)
-#define for_each_online_node(node) for_each_node_mask((node), node_online_map)
 
 #endif /* __LINUX_NODEMASK_H */