cpu_rmap.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * cpu_rmap.c: CPU affinity reverse-map support
  3. * Copyright 2011 Solarflare Communications Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published
  7. * by the Free Software Foundation, incorporated herein by reference.
  8. */
  9. #include <linux/cpu_rmap.h>
  10. #ifdef CONFIG_GENERIC_HARDIRQS
  11. #include <linux/interrupt.h>
  12. #endif
  13. #include <linux/module.h>
  14. /*
  15. * These functions maintain a mapping from CPUs to some ordered set of
  16. * objects with CPU affinities. This can be seen as a reverse-map of
  17. * CPU affinity. However, we do not assume that the object affinities
  18. * cover all CPUs in the system. For those CPUs not directly covered
  19. * by object affinities, we attempt to find a nearest object based on
  20. * CPU topology.
  21. */
  22. /**
  23. * alloc_cpu_rmap - allocate CPU affinity reverse-map
  24. * @size: Number of objects to be mapped
  25. * @flags: Allocation flags e.g. %GFP_KERNEL
  26. */
  27. struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags)
  28. {
  29. struct cpu_rmap *rmap;
  30. unsigned int cpu;
  31. size_t obj_offset;
  32. /* This is a silly number of objects, and we use u16 indices. */
  33. if (size > 0xffff)
  34. return NULL;
  35. /* Offset of object pointer array from base structure */
  36. obj_offset = ALIGN(offsetof(struct cpu_rmap, near[nr_cpu_ids]),
  37. sizeof(void *));
  38. rmap = kzalloc(obj_offset + size * sizeof(rmap->obj[0]), flags);
  39. if (!rmap)
  40. return NULL;
  41. rmap->obj = (void **)((char *)rmap + obj_offset);
  42. /* Initially assign CPUs to objects on a rota, since we have
  43. * no idea where the objects are. Use infinite distance, so
  44. * any object with known distance is preferable. Include the
  45. * CPUs that are not present/online, since we definitely want
  46. * any newly-hotplugged CPUs to have some object assigned.
  47. */
  48. for_each_possible_cpu(cpu) {
  49. rmap->near[cpu].index = cpu % size;
  50. rmap->near[cpu].dist = CPU_RMAP_DIST_INF;
  51. }
  52. rmap->size = size;
  53. return rmap;
  54. }
  55. EXPORT_SYMBOL(alloc_cpu_rmap);
  56. /* Reevaluate nearest object for given CPU, comparing with the given
  57. * neighbours at the given distance.
  58. */
  59. static bool cpu_rmap_copy_neigh(struct cpu_rmap *rmap, unsigned int cpu,
  60. const struct cpumask *mask, u16 dist)
  61. {
  62. int neigh;
  63. for_each_cpu(neigh, mask) {
  64. if (rmap->near[cpu].dist > dist &&
  65. rmap->near[neigh].dist <= dist) {
  66. rmap->near[cpu].index = rmap->near[neigh].index;
  67. rmap->near[cpu].dist = dist;
  68. return true;
  69. }
  70. }
  71. return false;
  72. }
  73. #ifdef DEBUG
  74. static void debug_print_rmap(const struct cpu_rmap *rmap, const char *prefix)
  75. {
  76. unsigned index;
  77. unsigned int cpu;
  78. pr_info("cpu_rmap %p, %s:\n", rmap, prefix);
  79. for_each_possible_cpu(cpu) {
  80. index = rmap->near[cpu].index;
  81. pr_info("cpu %d -> obj %u (distance %u)\n",
  82. cpu, index, rmap->near[cpu].dist);
  83. }
  84. }
  85. #else
  86. static inline void
  87. debug_print_rmap(const struct cpu_rmap *rmap, const char *prefix)
  88. {
  89. }
  90. #endif
  91. /**
  92. * cpu_rmap_add - add object to a rmap
  93. * @rmap: CPU rmap allocated with alloc_cpu_rmap()
  94. * @obj: Object to add to rmap
  95. *
  96. * Return index of object.
  97. */
  98. int cpu_rmap_add(struct cpu_rmap *rmap, void *obj)
  99. {
  100. u16 index;
  101. BUG_ON(rmap->used >= rmap->size);
  102. index = rmap->used++;
  103. rmap->obj[index] = obj;
  104. return index;
  105. }
  106. EXPORT_SYMBOL(cpu_rmap_add);
  107. /**
  108. * cpu_rmap_update - update CPU rmap following a change of object affinity
  109. * @rmap: CPU rmap to update
  110. * @index: Index of object whose affinity changed
  111. * @affinity: New CPU affinity of object
  112. */
  113. int cpu_rmap_update(struct cpu_rmap *rmap, u16 index,
  114. const struct cpumask *affinity)
  115. {
  116. cpumask_var_t update_mask;
  117. unsigned int cpu;
  118. if (unlikely(!zalloc_cpumask_var(&update_mask, GFP_KERNEL)))
  119. return -ENOMEM;
  120. /* Invalidate distance for all CPUs for which this used to be
  121. * the nearest object. Mark those CPUs for update.
  122. */
  123. for_each_online_cpu(cpu) {
  124. if (rmap->near[cpu].index == index) {
  125. rmap->near[cpu].dist = CPU_RMAP_DIST_INF;
  126. cpumask_set_cpu(cpu, update_mask);
  127. }
  128. }
  129. debug_print_rmap(rmap, "after invalidating old distances");
  130. /* Set distance to 0 for all CPUs in the new affinity mask.
  131. * Mark all CPUs within their NUMA nodes for update.
  132. */
  133. for_each_cpu(cpu, affinity) {
  134. rmap->near[cpu].index = index;
  135. rmap->near[cpu].dist = 0;
  136. cpumask_or(update_mask, update_mask,
  137. cpumask_of_node(cpu_to_node(cpu)));
  138. }
  139. debug_print_rmap(rmap, "after updating neighbours");
  140. /* Update distances based on topology */
  141. for_each_cpu(cpu, update_mask) {
  142. if (cpu_rmap_copy_neigh(rmap, cpu,
  143. topology_thread_cpumask(cpu), 1))
  144. continue;
  145. if (cpu_rmap_copy_neigh(rmap, cpu,
  146. topology_core_cpumask(cpu), 2))
  147. continue;
  148. if (cpu_rmap_copy_neigh(rmap, cpu,
  149. cpumask_of_node(cpu_to_node(cpu)), 3))
  150. continue;
  151. /* We could continue into NUMA node distances, but for now
  152. * we give up.
  153. */
  154. }
  155. debug_print_rmap(rmap, "after copying neighbours");
  156. free_cpumask_var(update_mask);
  157. return 0;
  158. }
  159. EXPORT_SYMBOL(cpu_rmap_update);
  160. #ifdef CONFIG_GENERIC_HARDIRQS
  161. /* Glue between IRQ affinity notifiers and CPU rmaps */
  162. struct irq_glue {
  163. struct irq_affinity_notify notify;
  164. struct cpu_rmap *rmap;
  165. u16 index;
  166. };
  167. /**
  168. * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs
  169. * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL
  170. *
  171. * Must be called in process context, before freeing the IRQs, and
  172. * without holding any locks required by global workqueue items.
  173. */
  174. void free_irq_cpu_rmap(struct cpu_rmap *rmap)
  175. {
  176. struct irq_glue *glue;
  177. u16 index;
  178. if (!rmap)
  179. return;
  180. for (index = 0; index < rmap->used; index++) {
  181. glue = rmap->obj[index];
  182. irq_set_affinity_notifier(glue->notify.irq, NULL);
  183. }
  184. irq_run_affinity_notifiers();
  185. kfree(rmap);
  186. }
  187. EXPORT_SYMBOL(free_irq_cpu_rmap);
  188. static void
  189. irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask)
  190. {
  191. struct irq_glue *glue =
  192. container_of(notify, struct irq_glue, notify);
  193. int rc;
  194. rc = cpu_rmap_update(glue->rmap, glue->index, mask);
  195. if (rc)
  196. pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc);
  197. }
  198. static void irq_cpu_rmap_release(struct kref *ref)
  199. {
  200. struct irq_glue *glue =
  201. container_of(ref, struct irq_glue, notify.kref);
  202. kfree(glue);
  203. }
  204. /**
  205. * irq_cpu_rmap_add - add an IRQ to a CPU affinity reverse-map
  206. * @rmap: The reverse-map
  207. * @irq: The IRQ number
  208. *
  209. * This adds an IRQ affinity notifier that will update the reverse-map
  210. * automatically.
  211. *
  212. * Must be called in process context, after the IRQ is allocated but
  213. * before it is bound with request_irq().
  214. */
  215. int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
  216. {
  217. struct irq_glue *glue = kzalloc(sizeof(*glue), GFP_KERNEL);
  218. int rc;
  219. if (!glue)
  220. return -ENOMEM;
  221. glue->notify.notify = irq_cpu_rmap_notify;
  222. glue->notify.release = irq_cpu_rmap_release;
  223. glue->rmap = rmap;
  224. glue->index = cpu_rmap_add(rmap, glue);
  225. rc = irq_set_affinity_notifier(irq, &glue->notify);
  226. if (rc)
  227. kfree(glue);
  228. return rc;
  229. }
  230. EXPORT_SYMBOL(irq_cpu_rmap_add);
  231. #endif /* CONFIG_GENERIC_HARDIRQS */