blk-mq-cpumap.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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_queues, const int cpu)
  16. {
  17. return cpu % nr_queues;
  18. }
  19. static int get_first_sibling(unsigned int cpu)
  20. {
  21. unsigned int ret;
  22. ret = cpumask_first(topology_sibling_cpumask(cpu));
  23. if (ret < nr_cpu_ids)
  24. return ret;
  25. return cpu;
  26. }
  27. int blk_mq_map_queues(struct blk_mq_tag_set *set)
  28. {
  29. unsigned int *map = set->mq_map;
  30. unsigned int nr_queues = set->nr_hw_queues;
  31. unsigned int cpu, first_sibling;
  32. for_each_possible_cpu(cpu) {
  33. /*
  34. * First do sequential mapping between CPUs and queues.
  35. * In case we still have CPUs to map, and we have some number of
  36. * threads per cores then map sibling threads to the same queue for
  37. * performace optimizations.
  38. */
  39. if (cpu < nr_queues) {
  40. map[cpu] = cpu_to_queue_index(nr_queues, cpu);
  41. } else {
  42. first_sibling = get_first_sibling(cpu);
  43. if (first_sibling == cpu)
  44. map[cpu] = cpu_to_queue_index(nr_queues, cpu);
  45. else
  46. map[cpu] = map[first_sibling];
  47. }
  48. }
  49. return 0;
  50. }
  51. EXPORT_SYMBOL_GPL(blk_mq_map_queues);
  52. /*
  53. * We have no quick way of doing reverse lookups. This is only used at
  54. * queue init time, so runtime isn't important.
  55. */
  56. int blk_mq_hw_queue_to_node(unsigned int *mq_map, unsigned int index)
  57. {
  58. int i;
  59. for_each_possible_cpu(i) {
  60. if (index == mq_map[i])
  61. return local_memory_node(cpu_to_node(i));
  62. }
  63. return NUMA_NO_NODE;
  64. }