sclp_info.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * drivers/s390/char/sclp_info.c
  3. *
  4. * Copyright IBM Corp. 2007
  5. * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  6. */
  7. #include <linux/init.h>
  8. #include <linux/errno.h>
  9. #include <linux/string.h>
  10. #include <asm/sclp.h>
  11. #include "sclp.h"
  12. struct sclp_readinfo_sccb {
  13. struct sccb_header header; /* 0-7 */
  14. u16 rnmax; /* 8-9 */
  15. u8 rnsize; /* 10 */
  16. u8 _reserved0[24 - 11]; /* 11-23 */
  17. u8 loadparm[8]; /* 24-31 */
  18. u8 _reserved1[48 - 32]; /* 32-47 */
  19. u64 facilities; /* 48-55 */
  20. u8 _reserved2[91 - 56]; /* 56-90 */
  21. u8 flags; /* 91 */
  22. u8 _reserved3[100 - 92]; /* 92-99 */
  23. u32 rnsize2; /* 100-103 */
  24. u64 rnmax2; /* 104-111 */
  25. u8 _reserved4[4096 - 112]; /* 112-4095 */
  26. } __attribute__((packed, aligned(4096)));
  27. static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
  28. static int __initdata early_readinfo_sccb_valid;
  29. u64 sclp_facilities;
  30. void __init sclp_readinfo_early(void)
  31. {
  32. int ret;
  33. int i;
  34. struct sclp_readinfo_sccb *sccb;
  35. sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
  36. SCLP_CMDW_READ_SCP_INFO};
  37. /* Enable service signal subclass mask. */
  38. __ctl_set_bit(0, 9);
  39. sccb = &early_readinfo_sccb;
  40. for (i = 0; i < ARRAY_SIZE(commands); i++) {
  41. do {
  42. memset(sccb, 0, sizeof(*sccb));
  43. sccb->header.length = sizeof(*sccb);
  44. sccb->header.control_mask[2] = 0x80;
  45. ret = sclp_service_call(commands[i], sccb);
  46. } while (ret == -EBUSY);
  47. if (ret)
  48. break;
  49. __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
  50. PSW_MASK_WAIT | PSW_DEFAULT_KEY);
  51. local_irq_disable();
  52. /*
  53. * Contents of the sccb might have changed
  54. * therefore a barrier is needed.
  55. */
  56. barrier();
  57. if (sccb->header.response_code == 0x10) {
  58. early_readinfo_sccb_valid = 1;
  59. break;
  60. }
  61. if (sccb->header.response_code != 0x1f0)
  62. break;
  63. }
  64. /* Disable service signal subclass mask again. */
  65. __ctl_clear_bit(0, 9);
  66. }
  67. void __init sclp_facilities_detect(void)
  68. {
  69. if (!early_readinfo_sccb_valid)
  70. return;
  71. sclp_facilities = early_readinfo_sccb.facilities;
  72. }
  73. unsigned long long __init sclp_memory_detect(void)
  74. {
  75. unsigned long long memsize;
  76. struct sclp_readinfo_sccb *sccb;
  77. if (!early_readinfo_sccb_valid)
  78. return 0;
  79. sccb = &early_readinfo_sccb;
  80. if (sccb->rnsize)
  81. memsize = sccb->rnsize << 20;
  82. else
  83. memsize = sccb->rnsize2 << 20;
  84. if (sccb->rnmax)
  85. memsize *= sccb->rnmax;
  86. else
  87. memsize *= sccb->rnmax2;
  88. return memsize;
  89. }
  90. /*
  91. * This function will be called after sclp_memory_detect(), which gets called
  92. * early from early.c code. Therefore the sccb should have valid contents.
  93. */
  94. void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
  95. {
  96. struct sclp_readinfo_sccb *sccb;
  97. if (!early_readinfo_sccb_valid)
  98. return;
  99. sccb = &early_readinfo_sccb;
  100. info->is_valid = 1;
  101. if (sccb->flags & 0x2)
  102. info->has_dump = 1;
  103. memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
  104. }