blk-mq-cpumap.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * CPU <-> hardware queue mapping helpers
  4. *
  5. * Copyright (C) 2013-2014 Jens Axboe
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/threads.h>
  9. #include <linux/module.h>
  10. #include <linux/mm.h>
  11. #include <linux/smp.h>
  12. #include <linux/cpu.h>
  13. #include <linux/blk-mq.h>
  14. #include "blk.h"
  15. #include "blk-mq.h"
  16. static int queue_index(struct blk_mq_queue_map *qmap,
  17. unsigned int nr_queues, const int q)
  18. {
  19. return qmap->queue_offset + (q % nr_queues);
  20. }
  21. static int get_first_sibling(unsigned int cpu)
  22. {
  23. unsigned int ret;
  24. ret = cpumask_first(topology_sibling_cpumask(cpu));
  25. if (ret < nr_cpu_ids)
  26. return ret;
  27. return cpu;
  28. }
  29. void blk_mq_map_queues(struct blk_mq_queue_map *qmap)
  30. {
  31. unsigned int *map = qmap->mq_map;
  32. unsigned int nr_queues = qmap->nr_queues;
  33. unsigned int cpu, first_sibling, q = 0;
  34. for_each_possible_cpu(cpu)
  35. map[cpu] = -1;
  36. /*
  37. * Spread queues among present CPUs first for minimizing
  38. * count of dead queues which are mapped by all un-present CPUs
  39. */
  40. for_each_present_cpu(cpu) {
  41. if (q >= nr_queues)
  42. break;
  43. map[cpu] = queue_index(qmap, nr_queues, q++);
  44. }
  45. for_each_possible_cpu(cpu) {
  46. if (map[cpu] != -1)
  47. continue;
  48. /*
  49. * First do sequential mapping between CPUs and queues.
  50. * In case we still have CPUs to map, and we have some number of
  51. * threads per cores then map sibling threads to the same queue
  52. * for performance optimizations.
  53. */
  54. if (q < nr_queues) {
  55. map[cpu] = queue_index(qmap, nr_queues, q++);
  56. } else {
  57. first_sibling = get_first_sibling(cpu);
  58. if (first_sibling == cpu)
  59. map[cpu] = queue_index(qmap, nr_queues, q++);
  60. else
  61. map[cpu] = map[first_sibling];
  62. }
  63. }
  64. }
  65. EXPORT_SYMBOL_GPL(blk_mq_map_queues);
  66. /**
  67. * blk_mq_hw_queue_to_node - Look up the memory node for a hardware queue index
  68. * @qmap: CPU to hardware queue map.
  69. * @index: hardware queue index.
  70. *
  71. * We have no quick way of doing reverse lookups. This is only used at
  72. * queue init time, so runtime isn't important.
  73. */
  74. int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int index)
  75. {
  76. int i;
  77. for_each_possible_cpu(i) {
  78. if (index == qmap->mq_map[i])
  79. return cpu_to_node(i);
  80. }
  81. return NUMA_NO_NODE;
  82. }