sclp_chp.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * drivers/s390/char/sclp_chp.c
  3. *
  4. * Copyright IBM Corp. 2007
  5. * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  6. */
  7. #include <linux/types.h>
  8. #include <linux/gfp.h>
  9. #include <linux/errno.h>
  10. #include <linux/completion.h>
  11. #include <asm/sclp.h>
  12. #include <asm/chpid.h>
  13. #include "sclp.h"
  14. #define TAG "sclp_chp: "
  15. #define SCLP_CMDW_CONFIGURE_CHANNEL_PATH 0x000f0001
  16. #define SCLP_CMDW_DECONFIGURE_CHANNEL_PATH 0x000e0001
  17. #define SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION 0x00030001
  18. static inline sclp_cmdw_t get_configure_cmdw(struct chp_id chpid)
  19. {
  20. return SCLP_CMDW_CONFIGURE_CHANNEL_PATH | chpid.id << 8;
  21. }
  22. static inline sclp_cmdw_t get_deconfigure_cmdw(struct chp_id chpid)
  23. {
  24. return SCLP_CMDW_DECONFIGURE_CHANNEL_PATH | chpid.id << 8;
  25. }
  26. static void chp_callback(struct sclp_req *req, void *data)
  27. {
  28. struct completion *completion = data;
  29. complete(completion);
  30. }
  31. struct chp_cfg_sccb {
  32. struct sccb_header header;
  33. u8 ccm;
  34. u8 reserved[6];
  35. u8 cssid;
  36. } __attribute__((packed));
  37. struct chp_cfg_data {
  38. struct chp_cfg_sccb sccb;
  39. struct sclp_req req;
  40. struct completion completion;
  41. } __attribute__((packed));
  42. static int do_configure(sclp_cmdw_t cmd)
  43. {
  44. struct chp_cfg_data *data;
  45. int rc;
  46. /* Prepare sccb. */
  47. data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
  48. if (!data)
  49. return -ENOMEM;
  50. data->sccb.header.length = sizeof(struct chp_cfg_sccb);
  51. data->req.command = cmd;
  52. data->req.sccb = &(data->sccb);
  53. data->req.status = SCLP_REQ_FILLED;
  54. data->req.callback = chp_callback;
  55. data->req.callback_data = &(data->completion);
  56. init_completion(&data->completion);
  57. /* Perform sclp request. */
  58. rc = sclp_add_request(&(data->req));
  59. if (rc)
  60. goto out;
  61. wait_for_completion(&data->completion);
  62. /* Check response .*/
  63. if (data->req.status != SCLP_REQ_DONE) {
  64. printk(KERN_WARNING TAG "configure channel-path request failed "
  65. "(status=0x%02x)\n", data->req.status);
  66. rc = -EIO;
  67. goto out;
  68. }
  69. switch (data->sccb.header.response_code) {
  70. case 0x0020:
  71. case 0x0120:
  72. case 0x0440:
  73. case 0x0450:
  74. break;
  75. default:
  76. printk(KERN_WARNING TAG "configure channel-path failed "
  77. "(cmd=0x%08x, response=0x%04x)\n", cmd,
  78. data->sccb.header.response_code);
  79. rc = -EIO;
  80. break;
  81. }
  82. out:
  83. free_page((unsigned long) data);
  84. return rc;
  85. }
  86. /**
  87. * sclp_chp_configure - perform configure channel-path sclp command
  88. * @chpid: channel-path ID
  89. *
  90. * Perform configure channel-path command sclp command for specified chpid.
  91. * Return 0 after command successfully finished, non-zero otherwise.
  92. */
  93. int sclp_chp_configure(struct chp_id chpid)
  94. {
  95. return do_configure(get_configure_cmdw(chpid));
  96. }
  97. /**
  98. * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
  99. * @chpid: channel-path ID
  100. *
  101. * Perform deconfigure channel-path command sclp command for specified chpid
  102. * and wait for completion. On success return 0. Return non-zero otherwise.
  103. */
  104. int sclp_chp_deconfigure(struct chp_id chpid)
  105. {
  106. return do_configure(get_deconfigure_cmdw(chpid));
  107. }
  108. struct chp_info_sccb {
  109. struct sccb_header header;
  110. u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
  111. u8 standby[SCLP_CHP_INFO_MASK_SIZE];
  112. u8 configured[SCLP_CHP_INFO_MASK_SIZE];
  113. u8 ccm;
  114. u8 reserved[6];
  115. u8 cssid;
  116. } __attribute__((packed));
  117. struct chp_info_data {
  118. struct chp_info_sccb sccb;
  119. struct sclp_req req;
  120. struct completion completion;
  121. } __attribute__((packed));
  122. /**
  123. * sclp_chp_read_info - perform read channel-path information sclp command
  124. * @info: resulting channel-path information data
  125. *
  126. * Perform read channel-path information sclp command and wait for completion.
  127. * On success, store channel-path information in @info and return 0. Return
  128. * non-zero otherwise.
  129. */
  130. int sclp_chp_read_info(struct sclp_chp_info *info)
  131. {
  132. struct chp_info_data *data;
  133. int rc;
  134. /* Prepare sccb. */
  135. data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
  136. if (!data)
  137. return -ENOMEM;
  138. data->sccb.header.length = sizeof(struct chp_info_sccb);
  139. data->req.command = SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION;
  140. data->req.sccb = &(data->sccb);
  141. data->req.status = SCLP_REQ_FILLED;
  142. data->req.callback = chp_callback;
  143. data->req.callback_data = &(data->completion);
  144. init_completion(&data->completion);
  145. /* Perform sclp request. */
  146. rc = sclp_add_request(&(data->req));
  147. if (rc)
  148. goto out;
  149. wait_for_completion(&data->completion);
  150. /* Check response .*/
  151. if (data->req.status != SCLP_REQ_DONE) {
  152. printk(KERN_WARNING TAG "read channel-path info request failed "
  153. "(status=0x%02x)\n", data->req.status);
  154. rc = -EIO;
  155. goto out;
  156. }
  157. if (data->sccb.header.response_code != 0x0010) {
  158. printk(KERN_WARNING TAG "read channel-path info failed "
  159. "(response=0x%04x)\n", data->sccb.header.response_code);
  160. rc = -EIO;
  161. goto out;
  162. }
  163. memcpy(info->recognized, data->sccb.recognized,
  164. SCLP_CHP_INFO_MASK_SIZE);
  165. memcpy(info->standby, data->sccb.standby,
  166. SCLP_CHP_INFO_MASK_SIZE);
  167. memcpy(info->configured, data->sccb.configured,
  168. SCLP_CHP_INFO_MASK_SIZE);
  169. out:
  170. free_page((unsigned long) data);
  171. return rc;
  172. }