sclp_sdias.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * SCLP "store data in absolute storage"
  3. *
  4. * Copyright IBM Corp. 2003, 2013
  5. * Author(s): Michael Holzheu
  6. */
  7. #define KMSG_COMPONENT "sclp_sdias"
  8. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  9. #include <linux/completion.h>
  10. #include <linux/sched.h>
  11. #include <asm/sclp.h>
  12. #include <asm/debug.h>
  13. #include <asm/ipl.h>
  14. #include "sclp_sdias.h"
  15. #include "sclp.h"
  16. #include "sclp_rw.h"
  17. #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
  18. #define SDIAS_RETRIES 300
  19. #define SDIAS_SLEEP_TICKS 50
  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(SDIAS_SLEEP_TICKS);
  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. #ifdef CONFIG_64BIT
  158. sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
  159. #else
  160. sccb.evbuf.asa_size = SDIAS_ASA_SIZE_32;
  161. #endif
  162. sccb.evbuf.event_status = 0;
  163. sccb.evbuf.blk_cnt = nr_blks;
  164. sccb.evbuf.asa = (unsigned long)dest;
  165. sccb.evbuf.fbn = start_blk;
  166. sccb.evbuf.lbn = 0;
  167. sccb.evbuf.dbs = 1;
  168. request.sccb = &sccb;
  169. request.command = SCLP_CMDW_WRITE_EVENT_DATA;
  170. request.status = SCLP_REQ_FILLED;
  171. request.callback = sdias_callback;
  172. rc = sdias_sclp_send(&request);
  173. if (rc) {
  174. pr_err("sclp_send failed: %x\n", rc);
  175. goto out;
  176. }
  177. if (sccb.hdr.response_code != 0x0020) {
  178. TRACE("copy failed: %x\n", sccb.hdr.response_code);
  179. rc = -EIO;
  180. goto out;
  181. }
  182. switch (sdias_evbuf.event_status) {
  183. case SDIAS_EVSTATE_ALL_STORED:
  184. TRACE("all stored\n");
  185. break;
  186. case SDIAS_EVSTATE_PART_STORED:
  187. TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
  188. break;
  189. case SDIAS_EVSTATE_NO_DATA:
  190. TRACE("no data\n");
  191. /* fall through */
  192. default:
  193. pr_err("Error from SCLP while copying hsa. Event status = %x\n",
  194. sdias_evbuf.event_status);
  195. rc = -EIO;
  196. }
  197. out:
  198. mutex_unlock(&sdias_mutex);
  199. return rc;
  200. }
  201. static int __init sclp_sdias_register_check(void)
  202. {
  203. int rc;
  204. rc = sclp_register(&sclp_sdias_register);
  205. if (rc)
  206. return rc;
  207. if (sclp_sdias_blk_count() == 0) {
  208. sclp_unregister(&sclp_sdias_register);
  209. return -ENODEV;
  210. }
  211. return 0;
  212. }
  213. static int __init sclp_sdias_init_sync(void)
  214. {
  215. TRACE("Try synchronous mode\n");
  216. sclp_sdias_register.receive_mask = 0;
  217. sclp_sdias_register.receiver_fn = NULL;
  218. return sclp_sdias_register_check();
  219. }
  220. static int __init sclp_sdias_init_async(void)
  221. {
  222. TRACE("Try asynchronous mode\n");
  223. sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
  224. sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
  225. return sclp_sdias_register_check();
  226. }
  227. int __init sclp_sdias_init(void)
  228. {
  229. if (ipl_info.type != IPL_TYPE_FCP_DUMP)
  230. return 0;
  231. sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
  232. debug_register_view(sdias_dbf, &debug_sprintf_view);
  233. debug_set_level(sdias_dbf, 6);
  234. if (sclp_sdias_init_sync() == 0)
  235. goto out;
  236. if (sclp_sdias_init_async() == 0)
  237. goto out;
  238. TRACE("init failed\n");
  239. return -ENODEV;
  240. out:
  241. TRACE("init done\n");
  242. return 0;
  243. }
  244. void __exit sclp_sdias_exit(void)
  245. {
  246. debug_unregister(sdias_dbf);
  247. sclp_unregister(&sclp_sdias_register);
  248. }