config.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Filename: config.c
  3. *
  4. *
  5. * Authors: Joshua Morris <josh.h.morris@us.ibm.com>
  6. * Philip Kelleher <pjk1939@linux.vnet.ibm.com>
  7. *
  8. * (C) Copyright 2013 IBM Corporation
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software Foundation,
  22. * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #include <linux/types.h>
  25. #include <linux/crc32.h>
  26. #include <linux/swab.h>
  27. #include "rsxx_priv.h"
  28. #include "rsxx_cfg.h"
  29. static void initialize_config(void *config)
  30. {
  31. struct rsxx_card_cfg *cfg = config;
  32. cfg->hdr.version = RSXX_CFG_VERSION;
  33. cfg->data.block_size = RSXX_HW_BLK_SIZE;
  34. cfg->data.stripe_size = RSXX_HW_BLK_SIZE;
  35. cfg->data.vendor_id = RSXX_VENDOR_ID_TMS_IBM;
  36. cfg->data.cache_order = (-1);
  37. cfg->data.intr_coal.mode = RSXX_INTR_COAL_DISABLED;
  38. cfg->data.intr_coal.count = 0;
  39. cfg->data.intr_coal.latency = 0;
  40. }
  41. static u32 config_data_crc32(struct rsxx_card_cfg *cfg)
  42. {
  43. /*
  44. * Return the compliment of the CRC to ensure compatibility
  45. * (i.e. this is how early rsxx drivers did it.)
  46. */
  47. return ~crc32(~0, &cfg->data, sizeof(cfg->data));
  48. }
  49. /*----------------- Config Byte Swap Functions -------------------*/
  50. static void config_hdr_be_to_cpu(struct card_cfg_hdr *hdr)
  51. {
  52. hdr->version = be32_to_cpu((__force __be32) hdr->version);
  53. hdr->crc = be32_to_cpu((__force __be32) hdr->crc);
  54. }
  55. static void config_hdr_cpu_to_be(struct card_cfg_hdr *hdr)
  56. {
  57. hdr->version = (__force u32) cpu_to_be32(hdr->version);
  58. hdr->crc = (__force u32) cpu_to_be32(hdr->crc);
  59. }
  60. static void config_data_swab(struct rsxx_card_cfg *cfg)
  61. {
  62. u32 *data = (u32 *) &cfg->data;
  63. int i;
  64. for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  65. data[i] = swab32(data[i]);
  66. }
  67. static void config_data_le_to_cpu(struct rsxx_card_cfg *cfg)
  68. {
  69. u32 *data = (u32 *) &cfg->data;
  70. int i;
  71. for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  72. data[i] = le32_to_cpu((__force __le32) data[i]);
  73. }
  74. static void config_data_cpu_to_le(struct rsxx_card_cfg *cfg)
  75. {
  76. u32 *data = (u32 *) &cfg->data;
  77. int i;
  78. for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  79. data[i] = (__force u32) cpu_to_le32(data[i]);
  80. }
  81. /*----------------- Config Operations ------------------*/
  82. static int rsxx_save_config(struct rsxx_cardinfo *card)
  83. {
  84. struct rsxx_card_cfg cfg;
  85. int st;
  86. memcpy(&cfg, &card->config, sizeof(cfg));
  87. if (unlikely(cfg.hdr.version != RSXX_CFG_VERSION)) {
  88. dev_err(CARD_TO_DEV(card),
  89. "Cannot save config with invalid version %d\n",
  90. cfg.hdr.version);
  91. return -EINVAL;
  92. }
  93. /* Convert data to little endian for the CRC calculation. */
  94. config_data_cpu_to_le(&cfg);
  95. cfg.hdr.crc = config_data_crc32(&cfg);
  96. /*
  97. * Swap the data from little endian to big endian so it can be
  98. * stored.
  99. */
  100. config_data_swab(&cfg);
  101. config_hdr_cpu_to_be(&cfg.hdr);
  102. st = rsxx_creg_write(card, CREG_ADD_CONFIG, sizeof(cfg), &cfg, 1);
  103. if (st)
  104. return st;
  105. return 0;
  106. }
  107. int rsxx_load_config(struct rsxx_cardinfo *card)
  108. {
  109. int st;
  110. u32 crc;
  111. st = rsxx_creg_read(card, CREG_ADD_CONFIG, sizeof(card->config),
  112. &card->config, 1);
  113. if (st) {
  114. dev_err(CARD_TO_DEV(card),
  115. "Failed reading card config.\n");
  116. return st;
  117. }
  118. config_hdr_be_to_cpu(&card->config.hdr);
  119. if (card->config.hdr.version == RSXX_CFG_VERSION) {
  120. /*
  121. * We calculate the CRC with the data in little endian, because
  122. * early drivers did not take big endian CPUs into account.
  123. * The data is always stored in big endian, so we need to byte
  124. * swap it before calculating the CRC.
  125. */
  126. config_data_swab(&card->config);
  127. /* Check the CRC */
  128. crc = config_data_crc32(&card->config);
  129. if (crc != card->config.hdr.crc) {
  130. dev_err(CARD_TO_DEV(card),
  131. "Config corruption detected!\n");
  132. dev_info(CARD_TO_DEV(card),
  133. "CRC (sb x%08x is x%08x)\n",
  134. card->config.hdr.crc, crc);
  135. return -EIO;
  136. }
  137. /* Convert the data to CPU byteorder */
  138. config_data_le_to_cpu(&card->config);
  139. } else if (card->config.hdr.version != 0) {
  140. dev_err(CARD_TO_DEV(card),
  141. "Invalid config version %d.\n",
  142. card->config.hdr.version);
  143. /*
  144. * Config version changes require special handling from the
  145. * user
  146. */
  147. return -EINVAL;
  148. } else {
  149. dev_info(CARD_TO_DEV(card),
  150. "Initializing card configuration.\n");
  151. initialize_config(card);
  152. st = rsxx_save_config(card);
  153. if (st)
  154. return st;
  155. }
  156. card->config_valid = 1;
  157. dev_dbg(CARD_TO_DEV(card), "version: x%08x\n",
  158. card->config.hdr.version);
  159. dev_dbg(CARD_TO_DEV(card), "crc: x%08x\n",
  160. card->config.hdr.crc);
  161. dev_dbg(CARD_TO_DEV(card), "block_size: x%08x\n",
  162. card->config.data.block_size);
  163. dev_dbg(CARD_TO_DEV(card), "stripe_size: x%08x\n",
  164. card->config.data.stripe_size);
  165. dev_dbg(CARD_TO_DEV(card), "vendor_id: x%08x\n",
  166. card->config.data.vendor_id);
  167. dev_dbg(CARD_TO_DEV(card), "cache_order: x%08x\n",
  168. card->config.data.cache_order);
  169. dev_dbg(CARD_TO_DEV(card), "mode: x%08x\n",
  170. card->config.data.intr_coal.mode);
  171. dev_dbg(CARD_TO_DEV(card), "count: x%08x\n",
  172. card->config.data.intr_coal.count);
  173. dev_dbg(CARD_TO_DEV(card), "latency: x%08x\n",
  174. card->config.data.intr_coal.latency);
  175. return 0;
  176. }