blk-mq-cpumap.c 2.3 KB

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