id-table.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Linux WiMAX
  4. * Mappping of generic netlink family IDs to net devices
  5. *
  6. * Copyright (C) 2005-2006 Intel Corporation <linux-wimax@intel.com>
  7. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  8. *
  9. * We assign a single generic netlink family ID to each device (to
  10. * simplify lookup).
  11. *
  12. * We need a way to map family ID to a wimax_dev pointer.
  13. *
  14. * The idea is to use a very simple lookup. Using a netlink attribute
  15. * with (for example) the interface name implies a heavier search over
  16. * all the network devices; seemed kind of a waste given that we know
  17. * we are looking for a WiMAX device and that most systems will have
  18. * just a single WiMAX adapter.
  19. *
  20. * We put all the WiMAX devices in the system in a linked list and
  21. * match the generic link family ID against the list.
  22. *
  23. * By using a linked list, the case of a single adapter in the system
  24. * becomes (almost) no overhead, while still working for many more. If
  25. * it ever goes beyond two, I'll be surprised.
  26. */
  27. #include <linux/device.h>
  28. #include <net/genetlink.h>
  29. #include <linux/netdevice.h>
  30. #include <linux/list.h>
  31. #include <linux/wimax.h>
  32. #include "wimax-internal.h"
  33. #define D_SUBMODULE id_table
  34. #include "debug-levels.h"
  35. static DEFINE_SPINLOCK(wimax_id_table_lock);
  36. static struct list_head wimax_id_table = LIST_HEAD_INIT(wimax_id_table);
  37. /*
  38. * wimax_id_table_add - add a gennetlink familiy ID / wimax_dev mapping
  39. *
  40. * @wimax_dev: WiMAX device descriptor to associate to the Generic
  41. * Netlink family ID.
  42. *
  43. * Look for an empty spot in the ID table; if none found, double the
  44. * table's size and get the first spot.
  45. */
  46. void wimax_id_table_add(struct wimax_dev *wimax_dev)
  47. {
  48. d_fnstart(3, NULL, "(wimax_dev %p)\n", wimax_dev);
  49. spin_lock(&wimax_id_table_lock);
  50. list_add(&wimax_dev->id_table_node, &wimax_id_table);
  51. spin_unlock(&wimax_id_table_lock);
  52. d_fnend(3, NULL, "(wimax_dev %p)\n", wimax_dev);
  53. }
  54. /*
  55. * wimax_get_netdev_by_info - lookup a wimax_dev from the gennetlink info
  56. *
  57. * The generic netlink family ID has been filled out in the
  58. * nlmsghdr->nlmsg_type field, so we pull it from there, look it up in
  59. * the mapping table and reference the wimax_dev.
  60. *
  61. * When done, the reference should be dropped with
  62. * 'dev_put(wimax_dev->net_dev)'.
  63. */
  64. struct wimax_dev *wimax_dev_get_by_genl_info(
  65. struct genl_info *info, int ifindex)
  66. {
  67. struct wimax_dev *wimax_dev = NULL;
  68. d_fnstart(3, NULL, "(info %p ifindex %d)\n", info, ifindex);
  69. spin_lock(&wimax_id_table_lock);
  70. list_for_each_entry(wimax_dev, &wimax_id_table, id_table_node) {
  71. if (wimax_dev->net_dev->ifindex == ifindex) {
  72. dev_hold(wimax_dev->net_dev);
  73. goto found;
  74. }
  75. }
  76. wimax_dev = NULL;
  77. d_printf(1, NULL, "wimax: no devices found with ifindex %d\n",
  78. ifindex);
  79. found:
  80. spin_unlock(&wimax_id_table_lock);
  81. d_fnend(3, NULL, "(info %p ifindex %d) = %p\n",
  82. info, ifindex, wimax_dev);
  83. return wimax_dev;
  84. }
  85. /*
  86. * wimax_id_table_rm - Remove a gennetlink familiy ID / wimax_dev mapping
  87. *
  88. * @id: family ID to remove from the table
  89. */
  90. void wimax_id_table_rm(struct wimax_dev *wimax_dev)
  91. {
  92. spin_lock(&wimax_id_table_lock);
  93. list_del_init(&wimax_dev->id_table_node);
  94. spin_unlock(&wimax_id_table_lock);
  95. }
  96. /*
  97. * Release the gennetlink family id / mapping table
  98. *
  99. * On debug, verify that the table is empty upon removal. We want the
  100. * code always compiled, to ensure it doesn't bit rot. It will be
  101. * compiled out if CONFIG_BUG is disabled.
  102. */
  103. void wimax_id_table_release(void)
  104. {
  105. struct wimax_dev *wimax_dev;
  106. #ifndef CONFIG_BUG
  107. return;
  108. #endif
  109. spin_lock(&wimax_id_table_lock);
  110. list_for_each_entry(wimax_dev, &wimax_id_table, id_table_node) {
  111. pr_err("BUG: %s wimax_dev %p ifindex %d not cleared\n",
  112. __func__, wimax_dev, wimax_dev->net_dev->ifindex);
  113. WARN_ON(1);
  114. }
  115. spin_unlock(&wimax_id_table_lock);
  116. }