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. const struct cpumask *online_mask)
  30. {
  31. unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
  32. cpumask_var_t cpus;
  33. if (!alloc_cpumask_var(&cpus, GFP_ATOMIC))
  34. return 1;
  35. cpumask_clear(cpus);
  36. nr_cpus = nr_uniq_cpus = 0;
  37. for_each_cpu(i, online_mask) {
  38. nr_cpus++;
  39. first_sibling = get_first_sibling(i);
  40. if (!cpumask_test_cpu(first_sibling, cpus))
  41. nr_uniq_cpus++;
  42. cpumask_set_cpu(i, cpus);
  43. }
  44. queue = 0;
  45. for_each_possible_cpu(i) {
  46. if (!cpumask_test_cpu(i, online_mask)) {
  47. map[i] = 0;
  48. continue;
  49. }
  50. /*
  51. * Easy case - we have equal or more hardware queues. Or
  52. * there are no thread siblings to take into account. Do
  53. * 1:1 if enough, or sequential mapping if less.
  54. */
  55. if (nr_queues >= nr_cpus || nr_cpus == nr_uniq_cpus) {
  56. map[i] = cpu_to_queue_index(nr_cpus, nr_queues, queue);
  57. queue++;
  58. continue;
  59. }
  60. /*
  61. * Less then nr_cpus queues, and we have some number of
  62. * threads per cores. Map sibling threads to the same
  63. * queue.
  64. */
  65. first_sibling = get_first_sibling(i);
  66. if (first_sibling == i) {
  67. map[i] = cpu_to_queue_index(nr_uniq_cpus, nr_queues,
  68. queue);
  69. queue++;
  70. } else
  71. map[i] = map[first_sibling];
  72. }
  73. free_cpumask_var(cpus);
  74. return 0;
  75. }
  76. unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
  77. {
  78. unsigned int *map;
  79. /* If cpus are offline, map them to first hctx */
  80. map = kzalloc_node(sizeof(*map) * nr_cpu_ids, GFP_KERNEL,
  81. set->numa_node);
  82. if (!map)
  83. return NULL;
  84. if (!blk_mq_update_queue_map(map, set->nr_hw_queues, cpu_online_mask))
  85. return map;
  86. kfree(map);
  87. return NULL;
  88. }
  89. /*
  90. * We have no quick way of doing reverse lookups. This is only used at
  91. * queue init time, so runtime isn't important.
  92. */
  93. int blk_mq_hw_queue_to_node(unsigned int *mq_map, unsigned int index)
  94. {
  95. int i;
  96. for_each_possible_cpu(i) {
  97. if (index == mq_map[i])
  98. return cpu_to_node(i);
  99. }
  100. return NUMA_NO_NODE;
  101. }