1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/types.h>
26#include <linux/crc32.h>
27#include <linux/swab.h>
28
29#include "rsxx_priv.h"
30#include "rsxx_cfg.h"
31
32static void initialize_config(struct rsxx_card_cfg *cfg)
33{
34 cfg->hdr.version = RSXX_CFG_VERSION;
35
36 cfg->data.block_size = RSXX_HW_BLK_SIZE;
37 cfg->data.stripe_size = RSXX_HW_BLK_SIZE;
38 cfg->data.vendor_id = RSXX_VENDOR_ID_IBM;
39 cfg->data.cache_order = (-1);
40 cfg->data.intr_coal.mode = RSXX_INTR_COAL_DISABLED;
41 cfg->data.intr_coal.count = 0;
42 cfg->data.intr_coal.latency = 0;
43}
44
45static u32 config_data_crc32(struct rsxx_card_cfg *cfg)
46{
47
48
49
50
51
52 return ~crc32(~0, &cfg->data, sizeof(cfg->data));
53}
54
55
56
57static void config_hdr_be_to_cpu(struct card_cfg_hdr *hdr)
58{
59 hdr->version = be32_to_cpu((__force __be32) hdr->version);
60 hdr->crc = be32_to_cpu((__force __be32) hdr->crc);
61}
62
63static void config_hdr_cpu_to_be(struct card_cfg_hdr *hdr)
64{
65 hdr->version = (__force u32) cpu_to_be32(hdr->version);
66 hdr->crc = (__force u32) cpu_to_be32(hdr->crc);
67}
68
69static void config_data_swab(struct rsxx_card_cfg *cfg)
70{
71 u32 *data = (u32 *) &cfg->data;
72 int i;
73
74 for (i = 0; i < (sizeof(cfg->data) / 4); i++)
75 data[i] = swab32(data[i]);
76}
77
78static void config_data_le_to_cpu(struct rsxx_card_cfg *cfg)
79{
80 u32 *data = (u32 *) &cfg->data;
81 int i;
82
83 for (i = 0; i < (sizeof(cfg->data) / 4); i++)
84 data[i] = le32_to_cpu((__force __le32) data[i]);
85}
86
87static void config_data_cpu_to_le(struct rsxx_card_cfg *cfg)
88{
89 u32 *data = (u32 *) &cfg->data;
90 int i;
91
92 for (i = 0; i < (sizeof(cfg->data) / 4); i++)
93 data[i] = (__force u32) cpu_to_le32(data[i]);
94}
95
96
97
98static int rsxx_save_config(struct rsxx_cardinfo *card)
99{
100 struct rsxx_card_cfg cfg;
101 int st;
102
103 memcpy(&cfg, &card->config, sizeof(cfg));
104
105 if (unlikely(cfg.hdr.version != RSXX_CFG_VERSION)) {
106 dev_err(CARD_TO_DEV(card),
107 "Cannot save config with invalid version %d\n",
108 cfg.hdr.version);
109 return -EINVAL;
110 }
111
112
113 config_data_cpu_to_le(&cfg);
114
115 cfg.hdr.crc = config_data_crc32(&cfg);
116
117
118
119
120
121 config_data_swab(&cfg);
122 config_hdr_cpu_to_be(&cfg.hdr);
123
124 st = rsxx_creg_write(card, CREG_ADD_CONFIG, sizeof(cfg), &cfg, 1);
125 if (st)
126 return st;
127
128 return 0;
129}
130
131int rsxx_load_config(struct rsxx_cardinfo *card)
132{
133 int st;
134 u32 crc;
135
136 st = rsxx_creg_read(card, CREG_ADD_CONFIG, sizeof(card->config),
137 &card->config, 1);
138 if (st) {
139 dev_err(CARD_TO_DEV(card),
140 "Failed reading card config.\n");
141 return st;
142 }
143
144 config_hdr_be_to_cpu(&card->config.hdr);
145
146 if (card->config.hdr.version == RSXX_CFG_VERSION) {
147
148
149
150
151
152
153
154 config_data_swab(&card->config);
155
156
157 crc = config_data_crc32(&card->config);
158 if (crc != card->config.hdr.crc) {
159 dev_err(CARD_TO_DEV(card),
160 "Config corruption detected!\n");
161 dev_info(CARD_TO_DEV(card),
162 "CRC (sb x%08x is x%08x)\n",
163 card->config.hdr.crc, crc);
164 return -EIO;
165 }
166
167
168 config_data_le_to_cpu(&card->config);
169
170 } else if (card->config.hdr.version != 0) {
171 dev_err(CARD_TO_DEV(card),
172 "Invalid config version %d.\n",
173 card->config.hdr.version);
174
175
176
177
178 return -EINVAL;
179 } else {
180 dev_info(CARD_TO_DEV(card),
181 "Initializing card configuration.\n");
182 initialize_config(&card->config);
183 st = rsxx_save_config(card);
184 if (st)
185 return st;
186 }
187
188 card->config_valid = 1;
189
190 dev_dbg(CARD_TO_DEV(card), "version: x%08x\n",
191 card->config.hdr.version);
192 dev_dbg(CARD_TO_DEV(card), "crc: x%08x\n",
193 card->config.hdr.crc);
194 dev_dbg(CARD_TO_DEV(card), "block_size: x%08x\n",
195 card->config.data.block_size);
196 dev_dbg(CARD_TO_DEV(card), "stripe_size: x%08x\n",
197 card->config.data.stripe_size);
198 dev_dbg(CARD_TO_DEV(card), "vendor_id: x%08x\n",
199 card->config.data.vendor_id);
200 dev_dbg(CARD_TO_DEV(card), "cache_order: x%08x\n",
201 card->config.data.cache_order);
202 dev_dbg(CARD_TO_DEV(card), "mode: x%08x\n",
203 card->config.data.intr_coal.mode);
204 dev_dbg(CARD_TO_DEV(card), "count: x%08x\n",
205 card->config.data.intr_coal.count);
206 dev_dbg(CARD_TO_DEV(card), "latency: x%08x\n",
207 card->config.data.intr_coal.latency);
208
209 return 0;
210}
211
212