sclp_sdias.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SCLP "store data in absolute storage"
  4. *
  5. * Copyright IBM Corp. 2003, 2013
  6. * Author(s): Michael Holzheu
  7. */
  8. #define KMSG_COMPONENT "sclp_sdias"
  9. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  10. #include <linux/completion.h>
  11. #include <linux/sched.h>
  12. #include <asm/sclp.h>
  13. #include <asm/debug.h>
  14. #include <asm/ipl.h>
  15. #include "sclp_sdias.h"
  16. #include "sclp.h"
  17. #include "sclp_rw.h"
  18. #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
  19. #define SDIAS_RETRIES 300
  20. static struct debug_info *sdias_dbf;
  21. static struct sclp_register sclp_sdias_register = {
  22. .send_mask = EVTYP_SDIAS_MASK,
  23. };
  24. static struct sdias_sccb sccb __attribute__((aligned(4096)));
  25. static struct sdias_evbuf sdias_evbuf;
  26. static DECLARE_COMPLETION(evbuf_accepted);
  27. static DECLARE_COMPLETION(evbuf_done);
  28. static DEFINE_MUTEX(sdias_mutex);
  29. /*
  30. * Called by SCLP base when read event data has been completed (async mode only)
  31. */
  32. static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
  33. {
  34. memcpy(&sdias_evbuf, evbuf,
  35. min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
  36. complete(&evbuf_done);
  37. TRACE("sclp_sdias_receiver_fn done\n");
  38. }
  39. /*
  40. * Called by SCLP base when sdias event has been accepted
  41. */
  42. static void sdias_callback(struct sclp_req *request, void *data)
  43. {
  44. complete(&evbuf_accepted);
  45. TRACE("callback done\n");
  46. }
  47. static int sdias_sclp_send(struct sclp_req *req)
  48. {
  49. int retries;
  50. int rc;
  51. for (retries = SDIAS_RETRIES; retries; retries--) {
  52. TRACE("add request\n");
  53. rc = sclp_add_request(req);
  54. if (rc) {
  55. /* not initiated, wait some time and retry */
  56. set_current_state(TASK_INTERRUPTIBLE);
  57. TRACE("add request failed: rc = %i\n",rc);
  58. schedule_timeout(msecs_to_jiffies(500));
  59. continue;
  60. }
  61. /* initiated, wait for completion of service call */
  62. wait_for_completion(&evbuf_accepted);
  63. if (req->status == SCLP_REQ_FAILED) {
  64. TRACE("sclp request failed\n");
  65. continue;
  66. }
  67. /* if not accepted, retry */
  68. if (!(sccb.evbuf.hdr.flags & 0x80)) {
  69. TRACE("sclp request failed: flags=%x\n",
  70. sccb.evbuf.hdr.flags);
  71. continue;
  72. }
  73. /*
  74. * for the sync interface the response is in the initial sccb
  75. */
  76. if (!sclp_sdias_register.receiver_fn) {
  77. memcpy(&sdias_evbuf, &sccb.evbuf, sizeof(sdias_evbuf));
  78. TRACE("sync request done\n");
  79. return 0;
  80. }
  81. /* otherwise we wait for completion */
  82. wait_for_completion(&evbuf_done);
  83. TRACE("request done\n");
  84. return 0;
  85. }
  86. return -EIO;
  87. }
  88. /*
  89. * Get number of blocks (4K) available in the HSA
  90. */
  91. int sclp_sdias_blk_count(void)
  92. {
  93. struct sclp_req request;
  94. int rc;
  95. mutex_lock(&sdias_mutex);
  96. memset(&sccb, 0, sizeof(sccb));
  97. memset(&request, 0, sizeof(request));
  98. sccb.hdr.length = sizeof(sccb);
  99. sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
  100. sccb.evbuf.hdr.type = EVTYP_SDIAS;
  101. sccb.evbuf.event_qual = SDIAS_EQ_SIZE;
  102. sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
  103. sccb.evbuf.event_id = 4712;
  104. sccb.evbuf.dbs = 1;
  105. request.sccb = &sccb;
  106. request.command = SCLP_CMDW_WRITE_EVENT_DATA;
  107. request.status = SCLP_REQ_FILLED;
  108. request.callback = sdias_callback;
  109. rc = sdias_sclp_send(&request);
  110. if (rc) {
  111. pr_err("sclp_send failed for get_nr_blocks\n");
  112. goto out;
  113. }
  114. if (sccb.hdr.response_code != 0x0020) {
  115. TRACE("send failed: %x\n", sccb.hdr.response_code);
  116. rc = -EIO;
  117. goto out;
  118. }
  119. switch (sdias_evbuf.event_status) {
  120. case 0:
  121. rc = sdias_evbuf.blk_cnt;
  122. break;
  123. default:
  124. pr_err("SCLP error: %x\n", sdias_evbuf.event_status);
  125. rc = -EIO;
  126. goto out;
  127. }
  128. TRACE("%i blocks\n", rc);
  129. out:
  130. mutex_unlock(&sdias_mutex);
  131. return rc;
  132. }
  133. /*
  134. * Copy from HSA to absolute storage (not reentrant):
  135. *
  136. * @dest : Address of buffer where data should be copied
  137. * @start_blk: Start Block (beginning with 1)
  138. * @nr_blks : Number of 4K blocks to copy
  139. *
  140. * Return Value: 0 : Requested 'number' of blocks of data copied
  141. * <0: ERROR - negative event status
  142. */
  143. int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
  144. {
  145. struct sclp_req request;
  146. int rc;
  147. mutex_lock(&sdias_mutex);
  148. memset(&sccb, 0, sizeof(sccb));
  149. memset(&request, 0, sizeof(request));
  150. sccb.hdr.length = sizeof(sccb);
  151. sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
  152. sccb.evbuf.hdr.type = EVTYP_SDIAS;
  153. sccb.evbuf.hdr.flags = 0;
  154. sccb.evbuf.event_qual = SDIAS_EQ_STORE_DATA;
  155. sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
  156. sccb.evbuf.event_id = 4712;
  157. sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
  158. sccb.evbuf.event_status = 0;
  159. sccb.evbuf.blk_cnt = nr_blks;
  160. sccb.evbuf.asa = (unsigned long)dest;
  161. sccb.evbuf.fbn = start_blk;
  162. sccb.evbuf.lbn = 0;
  163. sccb.evbuf.dbs = 1;
  164. request.sccb = &sccb;
  165. request.command = SCLP_CMDW_WRITE_EVENT_DATA;
  166. request.status = SCLP_REQ_FILLED;
  167. request.callback = sdias_callback;
  168. rc = sdias_sclp_send(&request);
  169. if (rc) {
  170. pr_err("sclp_send failed: %x\n", rc);
  171. goto out;
  172. }
  173. if (sccb.hdr.response_code != 0x0020) {
  174. TRACE("copy failed: %x\n", sccb.hdr.response_code);
  175. rc = -EIO;
  176. goto out;
  177. }
  178. switch (sdias_evbuf.event_status) {
  179. case SDIAS_EVSTATE_ALL_STORED:
  180. TRACE("all stored\n");
  181. break;
  182. case SDIAS_EVSTATE_PART_STORED:
  183. TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
  184. break;
  185. case SDIAS_EVSTATE_NO_DATA:
  186. TRACE("no data\n");
  187. /* fall through */
  188. default:
  189. pr_err("Error from SCLP while copying hsa. Event status = %x\n",
  190. sdias_evbuf.event_status);
  191. rc = -EIO;
  192. }
  193. out:
  194. mutex_unlock(&sdias_mutex);
  195. return rc;
  196. }
  197. static int __init sclp_sdias_register_check(void)
  198. {
  199. int rc;
  200. rc = sclp_register(&sclp_sdias_register);
  201. if (rc)
  202. return rc;
  203. if (sclp_sdias_blk_count() == 0) {
  204. sclp_unregister(&sclp_sdias_register);
  205. return -ENODEV;
  206. }
  207. return 0;
  208. }
  209. static int __init sclp_sdias_init_sync(void)
  210. {
  211. TRACE("Try synchronous mode\n");
  212. sclp_sdias_register.receive_mask = 0;
  213. sclp_sdias_register.receiver_fn = NULL;
  214. return sclp_sdias_register_check();
  215. }
  216. static int __init sclp_sdias_init_async(void)
  217. {
  218. TRACE("Try asynchronous mode\n");
  219. sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
  220. sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
  221. return sclp_sdias_register_check();
  222. }
  223. int __init sclp_sdias_init(void)
  224. {
  225. if (ipl_info.type != IPL_TYPE_FCP_DUMP)
  226. return 0;
  227. sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
  228. debug_register_view(sdias_dbf, &debug_sprintf_view);
  229. debug_set_level(sdias_dbf, 6);
  230. if (sclp_sdias_init_sync() == 0)
  231. goto out;
  232. if (sclp_sdias_init_async() == 0)
  233. goto out;
  234. TRACE("init failed\n");
  235. return -ENODEV;
  236. out:
  237. TRACE("init done\n");
  238. return 0;
  239. }
  240. void __exit sclp_sdias_exit(void)
  241. {
  242. debug_unregister(sdias_dbf);
  243. sclp_unregister(&sclp_sdias_register);
  244. }