id-table.c 4.4 KB

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