zfcp_diag.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * zfcp device driver
  4. *
  5. * Functions to handle diagnostics.
  6. *
  7. * Copyright IBM Corp. 2018
  8. */
  9. #include <linux/spinlock.h>
  10. #include <linux/jiffies.h>
  11. #include <linux/string.h>
  12. #include <linux/kernfs.h>
  13. #include <linux/sysfs.h>
  14. #include <linux/errno.h>
  15. #include <linux/slab.h>
  16. #include "zfcp_diag.h"
  17. #include "zfcp_ext.h"
  18. #include "zfcp_def.h"
  19. static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
  20. /**
  21. * zfcp_diag_adapter_setup() - Setup storage for adapter diagnostics.
  22. * @adapter: the adapter to setup diagnostics for.
  23. *
  24. * Creates the data-structures to store the diagnostics for an adapter. This
  25. * overwrites whatever was stored before at &zfcp_adapter->diagnostics!
  26. *
  27. * Return:
  28. * * 0 - Everyting is OK
  29. * * -ENOMEM - Could not allocate all/parts of the data-structures;
  30. * &zfcp_adapter->diagnostics remains unchanged
  31. */
  32. int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
  33. {
  34. struct zfcp_diag_adapter *diag;
  35. struct zfcp_diag_header *hdr;
  36. diag = kzalloc(sizeof(*diag), GFP_KERNEL);
  37. if (diag == NULL)
  38. return -ENOMEM;
  39. diag->max_age = (5 * 1000); /* default value: 5 s */
  40. /* setup header for port_data */
  41. hdr = &diag->port_data.header;
  42. spin_lock_init(&hdr->access_lock);
  43. hdr->buffer = &diag->port_data.data;
  44. hdr->buffer_size = sizeof(diag->port_data.data);
  45. /* set the timestamp so that the first test on age will always fail */
  46. hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
  47. /* setup header for config_data */
  48. hdr = &diag->config_data.header;
  49. spin_lock_init(&hdr->access_lock);
  50. hdr->buffer = &diag->config_data.data;
  51. hdr->buffer_size = sizeof(diag->config_data.data);
  52. /* set the timestamp so that the first test on age will always fail */
  53. hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
  54. adapter->diagnostics = diag;
  55. return 0;
  56. }
  57. /**
  58. * zfcp_diag_adapter_free() - Frees all adapter diagnostics allocations.
  59. * @adapter: the adapter whose diagnostic structures should be freed.
  60. *
  61. * Frees all data-structures in the given adapter that store diagnostics
  62. * information. Can savely be called with partially setup diagnostics.
  63. */
  64. void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter)
  65. {
  66. kfree(adapter->diagnostics);
  67. adapter->diagnostics = NULL;
  68. }
  69. /**
  70. * zfcp_diag_sysfs_setup() - Setup the sysfs-group for adapter-diagnostics.
  71. * @adapter: target adapter to which the group should be added.
  72. *
  73. * Return: 0 on success; Something else otherwise (see sysfs_create_group()).
  74. */
  75. int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter)
  76. {
  77. int rc = sysfs_create_group(&adapter->ccw_device->dev.kobj,
  78. &zfcp_sysfs_diag_attr_group);
  79. if (rc == 0)
  80. adapter->diagnostics->sysfs_established = 1;
  81. return rc;
  82. }
  83. /**
  84. * zfcp_diag_sysfs_destroy() - Remove the sysfs-group for adapter-diagnostics.
  85. * @adapter: target adapter from which the group should be removed.
  86. */
  87. void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter)
  88. {
  89. if (adapter->diagnostics == NULL ||
  90. !adapter->diagnostics->sysfs_established)
  91. return;
  92. /*
  93. * We need this state-handling so we can prevent warnings being printed
  94. * on the kernel-console in case we have to abort a halfway done
  95. * zfcp_adapter_enqueue(), in which the sysfs-group was not yet
  96. * established. sysfs_remove_group() does this checking as well, but
  97. * still prints a warning in case we try to remove a group that has not
  98. * been established before
  99. */
  100. adapter->diagnostics->sysfs_established = 0;
  101. sysfs_remove_group(&adapter->ccw_device->dev.kobj,
  102. &zfcp_sysfs_diag_attr_group);
  103. }
  104. /**
  105. * zfcp_diag_update_xdata() - Update a diagnostics buffer.
  106. * @hdr: the meta data to update.
  107. * @data: data to use for the update.
  108. * @incomplete: flag stating whether the data in @data is incomplete.
  109. */
  110. void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
  111. const void *const data, const bool incomplete)
  112. {
  113. const unsigned long capture_timestamp = jiffies;
  114. unsigned long flags;
  115. spin_lock_irqsave(&hdr->access_lock, flags);
  116. /* make sure we never go into the past with an update */
  117. if (!time_after_eq(capture_timestamp, hdr->timestamp))
  118. goto out;
  119. hdr->timestamp = capture_timestamp;
  120. hdr->incomplete = incomplete;
  121. memcpy(hdr->buffer, data, hdr->buffer_size);
  122. out:
  123. spin_unlock_irqrestore(&hdr->access_lock, flags);
  124. }
  125. /**
  126. * zfcp_diag_update_port_data_buffer() - Implementation of
  127. * &typedef zfcp_diag_update_buffer_func
  128. * to collect and update Port Data.
  129. * @adapter: Adapter to collect Port Data from.
  130. *
  131. * This call is SYNCHRONOUS ! It blocks till the respective command has
  132. * finished completely, or has failed in some way.
  133. *
  134. * Return:
  135. * * 0 - Successfully retrieved new Diagnostics and Updated the buffer;
  136. * this also includes cases where data was retrieved, but
  137. * incomplete; you'll have to check the flag ``incomplete``
  138. * of &struct zfcp_diag_header.
  139. * * see zfcp_fsf_exchange_port_data_sync() for possible error-codes (
  140. * excluding -EAGAIN)
  141. */
  142. int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter)
  143. {
  144. int rc;
  145. rc = zfcp_fsf_exchange_port_data_sync(adapter->qdio, NULL);
  146. if (rc == -EAGAIN)
  147. rc = 0; /* signaling incomplete via struct zfcp_diag_header */
  148. /* buffer-data was updated in zfcp_fsf_exchange_port_data_handler() */
  149. return rc;
  150. }
  151. /**
  152. * zfcp_diag_update_config_data_buffer() - Implementation of
  153. * &typedef zfcp_diag_update_buffer_func
  154. * to collect and update Config Data.
  155. * @adapter: Adapter to collect Config Data from.
  156. *
  157. * This call is SYNCHRONOUS ! It blocks till the respective command has
  158. * finished completely, or has failed in some way.
  159. *
  160. * Return:
  161. * * 0 - Successfully retrieved new Diagnostics and Updated the buffer;
  162. * this also includes cases where data was retrieved, but
  163. * incomplete; you'll have to check the flag ``incomplete``
  164. * of &struct zfcp_diag_header.
  165. * * see zfcp_fsf_exchange_config_data_sync() for possible error-codes (
  166. * excluding -EAGAIN)
  167. */
  168. int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter)
  169. {
  170. int rc;
  171. rc = zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL);
  172. if (rc == -EAGAIN)
  173. rc = 0; /* signaling incomplete via struct zfcp_diag_header */
  174. /* buffer-data was updated in zfcp_fsf_exchange_config_data_handler() */
  175. return rc;
  176. }
  177. static int __zfcp_diag_update_buffer(struct zfcp_adapter *const adapter,
  178. struct zfcp_diag_header *const hdr,
  179. zfcp_diag_update_buffer_func buffer_update,
  180. unsigned long *const flags)
  181. __must_hold(hdr->access_lock)
  182. {
  183. int rc;
  184. if (hdr->updating == 1) {
  185. rc = wait_event_interruptible_lock_irq(__zfcp_diag_publish_wait,
  186. hdr->updating == 0,
  187. hdr->access_lock);
  188. rc = (rc == 0 ? -EAGAIN : -EINTR);
  189. } else {
  190. hdr->updating = 1;
  191. spin_unlock_irqrestore(&hdr->access_lock, *flags);
  192. /* unlocked, because update function sleeps */
  193. rc = buffer_update(adapter);
  194. spin_lock_irqsave(&hdr->access_lock, *flags);
  195. hdr->updating = 0;
  196. /*
  197. * every thread waiting here went via an interruptible wait,
  198. * so its fine to only wake those
  199. */
  200. wake_up_interruptible_all(&__zfcp_diag_publish_wait);
  201. }
  202. return rc;
  203. }
  204. static bool
  205. __zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_adapter *const diag,
  206. const struct zfcp_diag_header *const hdr)
  207. __must_hold(hdr->access_lock)
  208. {
  209. const unsigned long now = jiffies;
  210. /*
  211. * Should not happen (data is from the future).. if it does, still
  212. * signal that it needs refresh
  213. */
  214. if (!time_after_eq(now, hdr->timestamp))
  215. return false;
  216. if (jiffies_to_msecs(now - hdr->timestamp) >= diag->max_age)
  217. return false;
  218. return true;
  219. }
  220. /**
  221. * zfcp_diag_update_buffer_limited() - Collect diagnostics and update a
  222. * diagnostics buffer rate limited.
  223. * @adapter: Adapter to collect the diagnostics from.
  224. * @hdr: buffer-header for which to update with the collected diagnostics.
  225. * @buffer_update: Specific implementation for collecting and updating.
  226. *
  227. * This function will cause an update of the given @hdr by calling the also
  228. * given @buffer_update function. If called by multiple sources at the same
  229. * time, it will synchornize the update by only allowing one source to call
  230. * @buffer_update and the others to wait for that source to complete instead
  231. * (the wait is interruptible).
  232. *
  233. * Additionally this version is rate-limited and will only exit if either the
  234. * buffer is fresh enough (within the limit) - it will do nothing if the buffer
  235. * is fresh enough to begin with -, or if the source/thread that started this
  236. * update is the one that made the update (to prevent endless loops).
  237. *
  238. * Return:
  239. * * 0 - If the update was successfully published and/or the buffer is
  240. * fresh enough
  241. * * -EINTR - If the thread went into the wait-state and was interrupted
  242. * * whatever @buffer_update returns
  243. */
  244. int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
  245. struct zfcp_diag_header *const hdr,
  246. zfcp_diag_update_buffer_func buffer_update)
  247. {
  248. unsigned long flags;
  249. int rc;
  250. spin_lock_irqsave(&hdr->access_lock, flags);
  251. for (rc = 0;
  252. !__zfcp_diag_test_buffer_age_isfresh(adapter->diagnostics, hdr);
  253. rc = 0) {
  254. rc = __zfcp_diag_update_buffer(adapter, hdr, buffer_update,
  255. &flags);
  256. if (rc != -EAGAIN)
  257. break;
  258. }
  259. spin_unlock_irqrestore(&hdr->access_lock, flags);
  260. return rc;
  261. }