op-reset.c 2.9 KB

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