op-reset.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Linux WiMAX
  3. * Implement and export a method for resetting a WiMAX device
  4. *
  5. *
  6. * Copyright (C) 2008 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 a simple synchronous call to reset a WiMAX device.
  25. *
  26. * Resets aim at being warm, keeping the device handles active;
  27. * however, when that fails, it falls back to a cold reset (that will
  28. * disconnect and reconnect the device).
  29. */
  30. #include <net/wimax.h>
  31. #include <net/genetlink.h>
  32. #include <linux/wimax.h>
  33. #include <linux/security.h>
  34. #include <linux/export.h>
  35. #include "wimax-internal.h"
  36. #define D_SUBMODULE op_reset
  37. #include "debug-levels.h"
  38. /**
  39. * wimax_reset - Reset a WiMAX device
  40. *
  41. * @wimax_dev: WiMAX device descriptor
  42. *
  43. * Returns:
  44. *
  45. * %0 if ok and a warm reset was done (the device still exists in
  46. * the system).
  47. *
  48. * -%ENODEV if a cold/bus reset had to be done (device has
  49. * disconnected and reconnected, so current handle is not valid
  50. * any more).
  51. *
  52. * -%EINVAL if the device is not even registered.
  53. *
  54. * Any other negative error code shall be considered as
  55. * non-recoverable.
  56. *
  57. * Description:
  58. *
  59. * Called when wanting to reset the device for any reason. Device is
  60. * taken back to power on status.
  61. *
  62. * This call blocks; on successful return, the device has completed the
  63. * reset process and is ready to operate.
  64. */
  65. int wimax_reset(struct wimax_dev *wimax_dev)
  66. {
  67. int result = -EINVAL;
  68. struct device *dev = wimax_dev_to_dev(wimax_dev);
  69. enum wimax_st state;
  70. might_sleep();
  71. d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
  72. mutex_lock(&wimax_dev->mutex);
  73. dev_hold(wimax_dev->net_dev);
  74. state = wimax_dev->state;
  75. mutex_unlock(&wimax_dev->mutex);
  76. if (state >= WIMAX_ST_DOWN) {
  77. mutex_lock(&wimax_dev->mutex_reset);
  78. result = wimax_dev->op_reset(wimax_dev);
  79. mutex_unlock(&wimax_dev->mutex_reset);
  80. }
  81. dev_put(wimax_dev->net_dev);
  82. d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
  83. return result;
  84. }
  85. EXPORT_SYMBOL(wimax_reset);
  86. /*
  87. * Exporting to user space over generic netlink
  88. *
  89. * Parse the reset command from user space, return error code.
  90. *
  91. * No attributes.
  92. */
  93. int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info)
  94. {
  95. int result, ifindex;
  96. struct wimax_dev *wimax_dev;
  97. d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
  98. result = -ENODEV;
  99. if (info->attrs[WIMAX_GNL_RESET_IFIDX] == NULL) {
  100. pr_err("WIMAX_GNL_OP_RFKILL: can't find IFIDX attribute\n");
  101. goto error_no_wimax_dev;
  102. }
  103. ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RESET_IFIDX]);
  104. wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
  105. if (wimax_dev == NULL)
  106. goto error_no_wimax_dev;
  107. /* Execute the operation and send the result back to user space */
  108. result = wimax_reset(wimax_dev);
  109. dev_put(wimax_dev->net_dev);
  110. error_no_wimax_dev:
  111. d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
  112. return result;
  113. }