blk-mq-cpumap.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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/group_cpus.h>
  14. #include <linux/device/bus.h>
  15. #include <linux/sched/isolation.h>
  16. #include "blk.h"
  17. #include "blk-mq.h"
  18. static unsigned int blk_mq_num_queues(const struct cpumask *mask,
  19. unsigned int max_queues)
  20. {
  21. unsigned int num;
  22. num = cpumask_weight(mask);
  23. return min_not_zero(num, max_queues);
  24. }
  25. /**
  26. * blk_mq_num_possible_queues - Calc nr of queues for multiqueue devices
  27. * @max_queues: The maximum number of queues the hardware/driver
  28. * supports. If max_queues is 0, the argument is
  29. * ignored.
  30. *
  31. * Calculates the number of queues to be used for a multiqueue
  32. * device based on the number of possible CPUs.
  33. */
  34. unsigned int blk_mq_num_possible_queues(unsigned int max_queues)
  35. {
  36. return blk_mq_num_queues(cpu_possible_mask, max_queues);
  37. }
  38. EXPORT_SYMBOL_GPL(blk_mq_num_possible_queues);
  39. /**
  40. * blk_mq_num_online_queues - Calc nr of queues for multiqueue devices
  41. * @max_queues: The maximum number of queues the hardware/driver
  42. * supports. If max_queues is 0, the argument is
  43. * ignored.
  44. *
  45. * Calculates the number of queues to be used for a multiqueue
  46. * device based on the number of online CPUs.
  47. */
  48. unsigned int blk_mq_num_online_queues(unsigned int max_queues)
  49. {
  50. return blk_mq_num_queues(cpu_online_mask, max_queues);
  51. }
  52. EXPORT_SYMBOL_GPL(blk_mq_num_online_queues);
  53. void blk_mq_map_queues(struct blk_mq_queue_map *qmap)
  54. {
  55. const struct cpumask *masks;
  56. unsigned int queue, cpu, nr_masks;
  57. masks = group_cpus_evenly(qmap->nr_queues, &nr_masks);
  58. if (!masks) {
  59. for_each_possible_cpu(cpu)
  60. qmap->mq_map[cpu] = qmap->queue_offset;
  61. return;
  62. }
  63. for (queue = 0; queue < qmap->nr_queues; queue++) {
  64. for_each_cpu(cpu, &masks[queue % nr_masks])
  65. qmap->mq_map[cpu] = qmap->queue_offset + queue;
  66. }
  67. kfree(masks);
  68. }
  69. EXPORT_SYMBOL_GPL(blk_mq_map_queues);
  70. /**
  71. * blk_mq_hw_queue_to_node - Look up the memory node for a hardware queue index
  72. * @qmap: CPU to hardware queue map.
  73. * @index: hardware queue index.
  74. *
  75. * We have no quick way of doing reverse lookups. This is only used at
  76. * queue init time, so runtime isn't important.
  77. */
  78. int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int index)
  79. {
  80. int i;
  81. for_each_possible_cpu(i) {
  82. if (index == qmap->mq_map[i])
  83. return cpu_to_node(i);
  84. }
  85. return NUMA_NO_NODE;
  86. }
  87. /**
  88. * blk_mq_map_hw_queues - Create CPU to hardware queue mapping
  89. * @qmap: CPU to hardware queue map
  90. * @dev: The device to map queues
  91. * @offset: Queue offset to use for the device
  92. *
  93. * Create a CPU to hardware queue mapping in @qmap. The struct bus_type
  94. * irq_get_affinity callback will be used to retrieve the affinity.
  95. */
  96. void blk_mq_map_hw_queues(struct blk_mq_queue_map *qmap,
  97. struct device *dev, unsigned int offset)
  98. {
  99. const struct cpumask *mask;
  100. unsigned int queue, cpu;
  101. if (!dev->bus->irq_get_affinity)
  102. goto fallback;
  103. for (queue = 0; queue < qmap->nr_queues; queue++) {
  104. mask = dev->bus->irq_get_affinity(dev, queue + offset);
  105. if (!mask)
  106. goto fallback;
  107. for_each_cpu(cpu, mask)
  108. qmap->mq_map[cpu] = qmap->queue_offset + queue;
  109. }
  110. return;
  111. fallback:
  112. blk_mq_map_queues(qmap);
  113. }
  114. EXPORT_SYMBOL_GPL(blk_mq_map_hw_queues);