blk-mq-cpumap.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * CPU <-> hardware queue mapping helpers
  3. *
  4. * Copyright (C) 2013-2014 Jens Axboe
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/threads.h>
  8. #include <linux/module.h>
  9. #include <linux/mm.h>
  10. #include <linux/smp.h>
  11. #include <linux/cpu.h>
  12. #include <linux/blk-mq.h>
  13. #include "blk.h"
  14. #include "blk-mq.h"
  15. static int cpu_to_queue_index(unsigned int nr_cpus, unsigned int nr_queues,
  16. const int cpu)
  17. {
  18. return cpu * nr_queues / nr_cpus;
  19. }
  20. static int get_first_sibling(unsigned int cpu)
  21. {
  22. unsigned int ret;
  23. ret = cpumask_first(topology_sibling_cpumask(cpu));
  24. if (ret < nr_cpu_ids)
  25. return ret;
  26. return cpu;
  27. }
  28. int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
  29. {
  30. unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
  31. cpumask_var_t cpus;
  32. if (!alloc_cpumask_var(&cpus, GFP_ATOMIC))
  33. return 1;
  34. cpumask_clear(cpus);
  35. nr_cpus = nr_uniq_cpus = 0;
  36. for_each_online_cpu(i) {
  37. nr_cpus++;
  38. first_sibling = get_first_sibling(i);
  39. if (!cpumask_test_cpu(first_sibling, cpus))
  40. nr_uniq_cpus++;
  41. cpumask_set_cpu(i, cpus);
  42. }
  43. queue = 0;
  44. for_each_possible_cpu(i) {
  45. if (!cpu_online(i)) {
  46. map[i] = 0;
  47. continue;
  48. }
  49. /*
  50. * Easy case - we have equal or more hardware queues. Or
  51. * there are no thread siblings to take into account. Do
  52. * 1:1 if enough, or sequential mapping if less.
  53. */
  54. if (nr_queues >= nr_cpus || nr_cpus == nr_uniq_cpus) {
  55. map[i] = cpu_to_queue_index(nr_cpus, nr_queues, queue);
  56. queue++;
  57. continue;
  58. }
  59. /*
  60. * Less then nr_cpus queues, and we have some number of
  61. * threads per cores. Map sibling threads to the same
  62. * queue.
  63. */
  64. first_sibling = get_first_sibling(i);
  65. if (first_sibling == i) {
  66. map[i] = cpu_to_queue_index(nr_uniq_cpus, nr_queues,
  67. queue);
  68. queue++;
  69. } else
  70. map[i] = map[first_sibling];
  71. }
  72. free_cpumask_var(cpus);
  73. return 0;
  74. }
  75. unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
  76. {
  77. unsigned int *map;
  78. /* If cpus are offline, map them to first hctx */
  79. map = kzalloc_node(sizeof(*map) * nr_cpu_ids, GFP_KERNEL,
  80. set->numa_node);
  81. if (!map)
  82. return NULL;
  83. if (!blk_mq_update_queue_map(map, set->nr_hw_queues))
  84. return map;
  85. kfree(map);
  86. return NULL;
  87. }
  88. /*
  89. * We have no quick way of doing reverse lookups. This is only used at
  90. * queue init time, so runtime isn't important.
  91. */
  92. int blk_mq_hw_queue_to_node(unsigned int *mq_map, unsigned int index)
  93. {
  94. int i;
  95. for_each_possible_cpu(i) {
  96. if (index == mq_map[i])
  97. return cpu_to_node(i);
  98. }
  99. return NUMA_NO_NODE;
  100. }