stack.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Linux WiMAX
  3. * Initialization, addition and removal of wimax 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. * This implements:
  25. *
  26. * - basic life cycle of 'struct wimax_dev' [wimax_dev_*()]; on
  27. * addition/registration initialize all subfields and allocate
  28. * generic netlink resources for user space communication. On
  29. * removal/unregistration, undo all that.
  30. *
  31. * - device state machine [wimax_state_change()] and support to send
  32. * reports to user space when the state changes
  33. * [wimax_gnl_re_state_change*()].
  34. *
  35. * See include/net/wimax.h for rationales and design.
  36. *
  37. * ROADMAP
  38. *
  39. * [__]wimax_state_change() Called by drivers to update device's state
  40. * wimax_gnl_re_state_change_alloc()
  41. * wimax_gnl_re_state_change_send()
  42. *
  43. * wimax_dev_init() Init a device
  44. * wimax_dev_add() Register
  45. * wimax_rfkill_add()
  46. * wimax_gnl_add() Register all the generic netlink resources.
  47. * wimax_id_table_add()
  48. * wimax_dev_rm() Unregister
  49. * wimax_id_table_rm()
  50. * wimax_gnl_rm()
  51. * wimax_rfkill_rm()
  52. */
  53. #include <linux/device.h>
  54. #include <linux/gfp.h>
  55. #include <net/genetlink.h>
  56. #include <linux/netdevice.h>
  57. #include <linux/wimax.h>
  58. #include <linux/module.h>
  59. #include "wimax-internal.h"
  60. #define D_SUBMODULE stack
  61. #include "debug-levels.h"
  62. static char wimax_debug_params[128];
  63. module_param_string(debug, wimax_debug_params, sizeof(wimax_debug_params),
  64. 0644);
  65. MODULE_PARM_DESC(debug,
  66. "String of space-separated NAME:VALUE pairs, where NAMEs "
  67. "are the different debug submodules and VALUE are the "
  68. "initial debug value to set.");
  69. /*
  70. * Authoritative source for the RE_STATE_CHANGE attribute policy
  71. *
  72. * We don't really use it here, but /me likes to keep the definition
  73. * close to where the data is generated.
  74. */
  75. /*
  76. static const struct nla_policy wimax_gnl_re_status_change[WIMAX_GNL_ATTR_MAX + 1] = {
  77. [WIMAX_GNL_STCH_STATE_OLD] = { .type = NLA_U8 },
  78. [WIMAX_GNL_STCH_STATE_NEW] = { .type = NLA_U8 },
  79. };
  80. */
  81. /*
  82. * Allocate a Report State Change message
  83. *
  84. * @header: save it, you need it for _send()
  85. *
  86. * Creates and fills a basic state change message; different code
  87. * paths can then add more attributes to the message as needed.
  88. *
  89. * Use wimax_gnl_re_state_change_send() to send the returned skb.
  90. *
  91. * Returns: skb with the genl message if ok, IS_ERR() ptr on error
  92. * with an errno code.
  93. */
  94. static
  95. struct sk_buff *wimax_gnl_re_state_change_alloc(
  96. struct wimax_dev *wimax_dev,
  97. enum wimax_st new_state, enum wimax_st old_state,
  98. void **header)
  99. {
  100. int result;
  101. struct device *dev = wimax_dev_to_dev(wimax_dev);
  102. void *data;
  103. struct sk_buff *report_skb;
  104. d_fnstart(3, dev, "(wimax_dev %p new_state %u old_state %u)\n",
  105. wimax_dev, new_state, old_state);
  106. result = -ENOMEM;
  107. report_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  108. if (report_skb == NULL) {
  109. dev_err(dev, "RE_STCH: can't create message\n");
  110. goto error_new;
  111. }
  112. /* FIXME: sending a group ID as the seq is wrong */
  113. data = genlmsg_put(report_skb, 0, wimax_gnl_family.mcgrp_offset,
  114. &wimax_gnl_family, 0, WIMAX_GNL_RE_STATE_CHANGE);
  115. if (data == NULL) {
  116. dev_err(dev, "RE_STCH: can't put data into message\n");
  117. goto error_put;
  118. }
  119. *header = data;
  120. result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_OLD, old_state);
  121. if (result < 0) {
  122. dev_err(dev, "RE_STCH: Error adding OLD attr: %d\n", result);
  123. goto error_put;
  124. }
  125. result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_NEW, new_state);
  126. if (result < 0) {
  127. dev_err(dev, "RE_STCH: Error adding NEW attr: %d\n", result);
  128. goto error_put;
  129. }
  130. result = nla_put_u32(report_skb, WIMAX_GNL_STCH_IFIDX,
  131. wimax_dev->net_dev->ifindex);
  132. if (result < 0) {
  133. dev_err(dev, "RE_STCH: Error adding IFINDEX attribute\n");
  134. goto error_put;
  135. }
  136. d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %p\n",
  137. wimax_dev, new_state, old_state, report_skb);
  138. return report_skb;
  139. error_put:
  140. nlmsg_free(report_skb);
  141. error_new:
  142. d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %d\n",
  143. wimax_dev, new_state, old_state, result);
  144. return ERR_PTR(result);
  145. }
  146. /*
  147. * Send a Report State Change message (as created with _alloc).
  148. *
  149. * @report_skb: as returned by wimax_gnl_re_state_change_alloc()
  150. * @header: as returned by wimax_gnl_re_state_change_alloc()
  151. *
  152. * Returns: 0 if ok, < 0 errno code on error.
  153. *
  154. * If the message is NULL, pretend it didn't happen.
  155. */
  156. static
  157. int wimax_gnl_re_state_change_send(
  158. struct wimax_dev *wimax_dev, struct sk_buff *report_skb,
  159. void *header)
  160. {
  161. int result = 0;
  162. struct device *dev = wimax_dev_to_dev(wimax_dev);
  163. d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n",
  164. wimax_dev, report_skb);
  165. if (report_skb == NULL) {
  166. result = -ENOMEM;
  167. goto out;
  168. }
  169. genlmsg_end(report_skb, header);
  170. genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL);
  171. out:
  172. d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n",
  173. wimax_dev, report_skb, result);
  174. return result;
  175. }
  176. static
  177. void __check_new_state(enum wimax_st old_state, enum wimax_st new_state,
  178. unsigned int allowed_states_bm)
  179. {
  180. if (WARN_ON(((1 << new_state) & allowed_states_bm) == 0)) {
  181. pr_err("SW BUG! Forbidden state change %u -> %u\n",
  182. old_state, new_state);
  183. }
  184. }
  185. /*
  186. * Set the current state of a WiMAX device [unlocking version of
  187. * wimax_state_change().
  188. */
  189. void __wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state)
  190. {
  191. struct device *dev = wimax_dev_to_dev(wimax_dev);
  192. enum wimax_st old_state = wimax_dev->state;
  193. struct sk_buff *stch_skb;
  194. void *header;
  195. d_fnstart(3, dev, "(wimax_dev %p new_state %u [old %u])\n",
  196. wimax_dev, new_state, old_state);
  197. if (WARN_ON(new_state >= __WIMAX_ST_INVALID)) {
  198. dev_err(dev, "SW BUG: requesting invalid state %u\n",
  199. new_state);
  200. goto out;
  201. }
  202. if (old_state == new_state)
  203. goto out;
  204. header = NULL; /* gcc complains? can't grok why */
  205. stch_skb = wimax_gnl_re_state_change_alloc(
  206. wimax_dev, new_state, old_state, &header);
  207. /* Verify the state transition and do exit-from-state actions */
  208. switch (old_state) {
  209. case __WIMAX_ST_NULL:
  210. __check_new_state(old_state, new_state,
  211. 1 << WIMAX_ST_DOWN);
  212. break;
  213. case WIMAX_ST_DOWN:
  214. __check_new_state(old_state, new_state,
  215. 1 << __WIMAX_ST_QUIESCING
  216. | 1 << WIMAX_ST_UNINITIALIZED
  217. | 1 << WIMAX_ST_RADIO_OFF);
  218. break;
  219. case __WIMAX_ST_QUIESCING:
  220. __check_new_state(old_state, new_state, 1 << WIMAX_ST_DOWN);
  221. break;
  222. case WIMAX_ST_UNINITIALIZED:
  223. __check_new_state(old_state, new_state,
  224. 1 << __WIMAX_ST_QUIESCING
  225. | 1 << WIMAX_ST_RADIO_OFF);
  226. break;
  227. case WIMAX_ST_RADIO_OFF:
  228. __check_new_state(old_state, new_state,
  229. 1 << __WIMAX_ST_QUIESCING
  230. | 1 << WIMAX_ST_READY);
  231. break;
  232. case WIMAX_ST_READY:
  233. __check_new_state(old_state, new_state,
  234. 1 << __WIMAX_ST_QUIESCING
  235. | 1 << WIMAX_ST_RADIO_OFF
  236. | 1 << WIMAX_ST_SCANNING
  237. | 1 << WIMAX_ST_CONNECTING
  238. | 1 << WIMAX_ST_CONNECTED);
  239. break;
  240. case WIMAX_ST_SCANNING:
  241. __check_new_state(old_state, new_state,
  242. 1 << __WIMAX_ST_QUIESCING
  243. | 1 << WIMAX_ST_RADIO_OFF
  244. | 1 << WIMAX_ST_READY
  245. | 1 << WIMAX_ST_CONNECTING
  246. | 1 << WIMAX_ST_CONNECTED);
  247. break;
  248. case WIMAX_ST_CONNECTING:
  249. __check_new_state(old_state, new_state,
  250. 1 << __WIMAX_ST_QUIESCING
  251. | 1 << WIMAX_ST_RADIO_OFF
  252. | 1 << WIMAX_ST_READY
  253. | 1 << WIMAX_ST_SCANNING
  254. | 1 << WIMAX_ST_CONNECTED);
  255. break;
  256. case WIMAX_ST_CONNECTED:
  257. __check_new_state(old_state, new_state,
  258. 1 << __WIMAX_ST_QUIESCING
  259. | 1 << WIMAX_ST_RADIO_OFF
  260. | 1 << WIMAX_ST_READY);
  261. netif_tx_disable(wimax_dev->net_dev);
  262. netif_carrier_off(wimax_dev->net_dev);
  263. break;
  264. case __WIMAX_ST_INVALID:
  265. default:
  266. dev_err(dev, "SW BUG: wimax_dev %p is in unknown state %u\n",
  267. wimax_dev, wimax_dev->state);
  268. WARN_ON(1);
  269. goto out;
  270. }
  271. /* Execute the actions of entry to the new state */
  272. switch (new_state) {
  273. case __WIMAX_ST_NULL:
  274. dev_err(dev, "SW BUG: wimax_dev %p entering NULL state "
  275. "from %u\n", wimax_dev, wimax_dev->state);
  276. WARN_ON(1); /* Nobody can enter this state */
  277. break;
  278. case WIMAX_ST_DOWN:
  279. break;
  280. case __WIMAX_ST_QUIESCING:
  281. break;
  282. case WIMAX_ST_UNINITIALIZED:
  283. break;
  284. case WIMAX_ST_RADIO_OFF:
  285. break;
  286. case WIMAX_ST_READY:
  287. break;
  288. case WIMAX_ST_SCANNING:
  289. break;
  290. case WIMAX_ST_CONNECTING:
  291. break;
  292. case WIMAX_ST_CONNECTED:
  293. netif_carrier_on(wimax_dev->net_dev);
  294. netif_wake_queue(wimax_dev->net_dev);
  295. break;
  296. case __WIMAX_ST_INVALID:
  297. default:
  298. BUG();
  299. }
  300. __wimax_state_set(wimax_dev, new_state);
  301. if (!IS_ERR(stch_skb))
  302. wimax_gnl_re_state_change_send(wimax_dev, stch_skb, header);
  303. out:
  304. d_fnend(3, dev, "(wimax_dev %p new_state %u [old %u]) = void\n",
  305. wimax_dev, new_state, old_state);
  306. }
  307. /**
  308. * wimax_state_change - Set the current state of a WiMAX device
  309. *
  310. * @wimax_dev: WiMAX device descriptor (properly referenced)
  311. * @new_state: New state to switch to
  312. *
  313. * This implements the state changes for the wimax devices. It will
  314. *
  315. * - verify that the state transition is legal (for now it'll just
  316. * print a warning if not) according to the table in
  317. * linux/wimax.h's documentation for 'enum wimax_st'.
  318. *
  319. * - perform the actions needed for leaving the current state and
  320. * whichever are needed for entering the new state.
  321. *
  322. * - issue a report to user space indicating the new state (and an
  323. * optional payload with information about the new state).
  324. *
  325. * NOTE: @wimax_dev must be locked
  326. */
  327. void wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state)
  328. {
  329. /*
  330. * A driver cannot take the wimax_dev out of the
  331. * __WIMAX_ST_NULL state unless by calling wimax_dev_add(). If
  332. * the wimax_dev's state is still NULL, we ignore any request
  333. * to change its state because it means it hasn't been yet
  334. * registered.
  335. *
  336. * There is no need to complain about it, as routines that
  337. * call this might be shared from different code paths that
  338. * are called before or after wimax_dev_add() has done its
  339. * job.
  340. */
  341. mutex_lock(&wimax_dev->mutex);
  342. if (wimax_dev->state > __WIMAX_ST_NULL)
  343. __wimax_state_change(wimax_dev, new_state);
  344. mutex_unlock(&wimax_dev->mutex);
  345. }
  346. EXPORT_SYMBOL_GPL(wimax_state_change);
  347. /**
  348. * wimax_state_get() - Return the current state of a WiMAX device
  349. *
  350. * @wimax_dev: WiMAX device descriptor
  351. *
  352. * Returns: Current state of the device according to its driver.
  353. */
  354. enum wimax_st wimax_state_get(struct wimax_dev *wimax_dev)
  355. {
  356. enum wimax_st state;
  357. mutex_lock(&wimax_dev->mutex);
  358. state = wimax_dev->state;
  359. mutex_unlock(&wimax_dev->mutex);
  360. return state;
  361. }
  362. EXPORT_SYMBOL_GPL(wimax_state_get);
  363. /**
  364. * wimax_dev_init - initialize a newly allocated instance
  365. *
  366. * @wimax_dev: WiMAX device descriptor to initialize.
  367. *
  368. * Initializes fields of a freshly allocated @wimax_dev instance. This
  369. * function assumes that after allocation, the memory occupied by
  370. * @wimax_dev was zeroed.
  371. */
  372. void wimax_dev_init(struct wimax_dev *wimax_dev)
  373. {
  374. INIT_LIST_HEAD(&wimax_dev->id_table_node);
  375. __wimax_state_set(wimax_dev, __WIMAX_ST_NULL);
  376. mutex_init(&wimax_dev->mutex);
  377. mutex_init(&wimax_dev->mutex_reset);
  378. }
  379. EXPORT_SYMBOL_GPL(wimax_dev_init);
  380. static const struct nla_policy wimax_gnl_policy[WIMAX_GNL_ATTR_MAX + 1] = {
  381. [WIMAX_GNL_RESET_IFIDX] = { .type = NLA_U32, },
  382. [WIMAX_GNL_RFKILL_IFIDX] = { .type = NLA_U32, },
  383. [WIMAX_GNL_RFKILL_STATE] = {
  384. .type = NLA_U32 /* enum wimax_rf_state */
  385. },
  386. [WIMAX_GNL_STGET_IFIDX] = { .type = NLA_U32, },
  387. [WIMAX_GNL_MSG_IFIDX] = { .type = NLA_U32, },
  388. [WIMAX_GNL_MSG_DATA] = {
  389. .type = NLA_UNSPEC, /* libnl doesn't grok BINARY yet */
  390. },
  391. };
  392. static const struct genl_ops wimax_gnl_ops[] = {
  393. {
  394. .cmd = WIMAX_GNL_OP_MSG_FROM_USER,
  395. .flags = GENL_ADMIN_PERM,
  396. .policy = wimax_gnl_policy,
  397. .doit = wimax_gnl_doit_msg_from_user,
  398. },
  399. {
  400. .cmd = WIMAX_GNL_OP_RESET,
  401. .flags = GENL_ADMIN_PERM,
  402. .policy = wimax_gnl_policy,
  403. .doit = wimax_gnl_doit_reset,
  404. },
  405. {
  406. .cmd = WIMAX_GNL_OP_RFKILL,
  407. .flags = GENL_ADMIN_PERM,
  408. .policy = wimax_gnl_policy,
  409. .doit = wimax_gnl_doit_rfkill,
  410. },
  411. {
  412. .cmd = WIMAX_GNL_OP_STATE_GET,
  413. .flags = GENL_ADMIN_PERM,
  414. .policy = wimax_gnl_policy,
  415. .doit = wimax_gnl_doit_state_get,
  416. },
  417. };
  418. static
  419. size_t wimax_addr_scnprint(char *addr_str, size_t addr_str_size,
  420. unsigned char *addr, size_t addr_len)
  421. {
  422. unsigned int cnt, total;
  423. for (total = cnt = 0; cnt < addr_len; cnt++)
  424. total += scnprintf(addr_str + total, addr_str_size - total,
  425. "%02x%c", addr[cnt],
  426. cnt == addr_len - 1 ? '\0' : ':');
  427. return total;
  428. }
  429. /**
  430. * wimax_dev_add - Register a new WiMAX device
  431. *
  432. * @wimax_dev: WiMAX device descriptor (as embedded in your @net_dev's
  433. * priv data). You must have called wimax_dev_init() on it before.
  434. *
  435. * @net_dev: net device the @wimax_dev is associated with. The
  436. * function expects SET_NETDEV_DEV() and register_netdev() were
  437. * already called on it.
  438. *
  439. * Registers the new WiMAX device, sets up the user-kernel control
  440. * interface (generic netlink) and common WiMAX infrastructure.
  441. *
  442. * Note that the parts that will allow interaction with user space are
  443. * setup at the very end, when the rest is in place, as once that
  444. * happens, the driver might get user space control requests via
  445. * netlink or from debugfs that might translate into calls into
  446. * wimax_dev->op_*().
  447. */
  448. int wimax_dev_add(struct wimax_dev *wimax_dev, struct net_device *net_dev)
  449. {
  450. int result;
  451. struct device *dev = net_dev->dev.parent;
  452. char addr_str[32];
  453. d_fnstart(3, dev, "(wimax_dev %p net_dev %p)\n", wimax_dev, net_dev);
  454. /* Do the RFKILL setup before locking, as RFKILL will call
  455. * into our functions. */
  456. wimax_dev->net_dev = net_dev;
  457. result = wimax_rfkill_add(wimax_dev);
  458. if (result < 0)
  459. goto error_rfkill_add;
  460. /* Set up user-space interaction */
  461. mutex_lock(&wimax_dev->mutex);
  462. wimax_id_table_add(wimax_dev);
  463. result = wimax_debugfs_add(wimax_dev);
  464. if (result < 0) {
  465. dev_err(dev, "cannot initialize debugfs: %d\n",
  466. result);
  467. goto error_debugfs_add;
  468. }
  469. __wimax_state_set(wimax_dev, WIMAX_ST_DOWN);
  470. mutex_unlock(&wimax_dev->mutex);
  471. wimax_addr_scnprint(addr_str, sizeof(addr_str),
  472. net_dev->dev_addr, net_dev->addr_len);
  473. dev_err(dev, "WiMAX interface %s (%s) ready\n",
  474. net_dev->name, addr_str);
  475. d_fnend(3, dev, "(wimax_dev %p net_dev %p) = 0\n", wimax_dev, net_dev);
  476. return 0;
  477. error_debugfs_add:
  478. wimax_id_table_rm(wimax_dev);
  479. mutex_unlock(&wimax_dev->mutex);
  480. wimax_rfkill_rm(wimax_dev);
  481. error_rfkill_add:
  482. d_fnend(3, dev, "(wimax_dev %p net_dev %p) = %d\n",
  483. wimax_dev, net_dev, result);
  484. return result;
  485. }
  486. EXPORT_SYMBOL_GPL(wimax_dev_add);
  487. /**
  488. * wimax_dev_rm - Unregister an existing WiMAX device
  489. *
  490. * @wimax_dev: WiMAX device descriptor
  491. *
  492. * Unregisters a WiMAX device previously registered for use with
  493. * wimax_add_rm().
  494. *
  495. * IMPORTANT! Must call before calling unregister_netdev().
  496. *
  497. * After this function returns, you will not get any more user space
  498. * control requests (via netlink or debugfs) and thus to wimax_dev->ops.
  499. *
  500. * Reentrancy control is ensured by setting the state to
  501. * %__WIMAX_ST_QUIESCING. rfkill operations coming through
  502. * wimax_*rfkill*() will be stopped by the quiescing state; ops coming
  503. * from the rfkill subsystem will be stopped by the support being
  504. * removed by wimax_rfkill_rm().
  505. */
  506. void wimax_dev_rm(struct wimax_dev *wimax_dev)
  507. {
  508. d_fnstart(3, NULL, "(wimax_dev %p)\n", wimax_dev);
  509. mutex_lock(&wimax_dev->mutex);
  510. __wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
  511. wimax_debugfs_rm(wimax_dev);
  512. wimax_id_table_rm(wimax_dev);
  513. __wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
  514. mutex_unlock(&wimax_dev->mutex);
  515. wimax_rfkill_rm(wimax_dev);
  516. d_fnend(3, NULL, "(wimax_dev %p) = void\n", wimax_dev);
  517. }
  518. EXPORT_SYMBOL_GPL(wimax_dev_rm);
  519. /* Debug framework control of debug levels */
  520. struct d_level D_LEVEL[] = {
  521. D_SUBMODULE_DEFINE(debugfs),
  522. D_SUBMODULE_DEFINE(id_table),
  523. D_SUBMODULE_DEFINE(op_msg),
  524. D_SUBMODULE_DEFINE(op_reset),
  525. D_SUBMODULE_DEFINE(op_rfkill),
  526. D_SUBMODULE_DEFINE(op_state_get),
  527. D_SUBMODULE_DEFINE(stack),
  528. };
  529. size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
  530. struct genl_family wimax_gnl_family = {
  531. .id = GENL_ID_GENERATE,
  532. .name = "WiMAX",
  533. .version = WIMAX_GNL_VERSION,
  534. .hdrsize = 0,
  535. .maxattr = WIMAX_GNL_ATTR_MAX,
  536. };
  537. static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
  538. { .name = "msg", },
  539. };
  540. /* Shutdown the wimax stack */
  541. static
  542. int __init wimax_subsys_init(void)
  543. {
  544. int result;
  545. d_fnstart(4, NULL, "()\n");
  546. d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params,
  547. "wimax.debug");
  548. snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
  549. "WiMAX");
  550. result = genl_register_family_with_ops_groups(&wimax_gnl_family,
  551. wimax_gnl_ops,
  552. wimax_gnl_mcgrps);
  553. if (unlikely(result < 0)) {
  554. pr_err("cannot register generic netlink family: %d\n", result);
  555. goto error_register_family;
  556. }
  557. d_fnend(4, NULL, "() = 0\n");
  558. return 0;
  559. error_register_family:
  560. d_fnend(4, NULL, "() = %d\n", result);
  561. return result;
  562. }
  563. module_init(wimax_subsys_init);
  564. /* Shutdown the wimax stack */
  565. static
  566. void __exit wimax_subsys_exit(void)
  567. {
  568. wimax_id_table_release();
  569. genl_unregister_family(&wimax_gnl_family);
  570. }
  571. module_exit(wimax_subsys_exit);
  572. MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
  573. MODULE_DESCRIPTION("Linux WiMAX stack");
  574. MODULE_LICENSE("GPL");