5 * Authors: Joshua Morris <josh.h.morris@us.ibm.com>
6 * Philip Kelleher <pjk1939@linux.vnet.ibm.com>
8 * (C) Copyright 2013 IBM Corporation
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.
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.
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
25 #include <linux/types.h>
26 #include <linux/crc32.h>
27 #include <linux/swab.h>
29 #include "rsxx_priv.h"
32 static void initialize_config(struct rsxx_card_cfg
*cfg
)
34 cfg
->hdr
.version
= RSXX_CFG_VERSION
;
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;
45 static u32
config_data_crc32(struct rsxx_card_cfg
*cfg
)
48 * Return the compliment of the CRC to ensure compatibility
49 * (i.e. this is how early rsxx drivers did it.)
52 return ~crc32(~0, &cfg
->data
, sizeof(cfg
->data
));
56 /*----------------- Config Byte Swap Functions -------------------*/
57 static void config_hdr_be_to_cpu(struct card_cfg_hdr
*hdr
)
59 hdr
->version
= be32_to_cpu((__force __be32
) hdr
->version
);
60 hdr
->crc
= be32_to_cpu((__force __be32
) hdr
->crc
);
63 static void config_hdr_cpu_to_be(struct card_cfg_hdr
*hdr
)
65 hdr
->version
= (__force u32
) cpu_to_be32(hdr
->version
);
66 hdr
->crc
= (__force u32
) cpu_to_be32(hdr
->crc
);
69 static void config_data_swab(struct rsxx_card_cfg
*cfg
)
71 u32
*data
= (u32
*) &cfg
->data
;
74 for (i
= 0; i
< (sizeof(cfg
->data
) / 4); i
++)
75 data
[i
] = swab32(data
[i
]);
78 static void config_data_le_to_cpu(struct rsxx_card_cfg
*cfg
)
80 u32
*data
= (u32
*) &cfg
->data
;
83 for (i
= 0; i
< (sizeof(cfg
->data
) / 4); i
++)
84 data
[i
] = le32_to_cpu((__force __le32
) data
[i
]);
87 static void config_data_cpu_to_le(struct rsxx_card_cfg
*cfg
)
89 u32
*data
= (u32
*) &cfg
->data
;
92 for (i
= 0; i
< (sizeof(cfg
->data
) / 4); i
++)
93 data
[i
] = (__force u32
) cpu_to_le32(data
[i
]);
97 /*----------------- Config Operations ------------------*/
98 static int rsxx_save_config(struct rsxx_cardinfo
*card
)
100 struct rsxx_card_cfg cfg
;
103 memcpy(&cfg
, &card
->config
, sizeof(cfg
));
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",
112 /* Convert data to little endian for the CRC calculation. */
113 config_data_cpu_to_le(&cfg
);
115 cfg
.hdr
.crc
= config_data_crc32(&cfg
);
118 * Swap the data from little endian to big endian so it can be
121 config_data_swab(&cfg
);
122 config_hdr_cpu_to_be(&cfg
.hdr
);
124 st
= rsxx_creg_write(card
, CREG_ADD_CONFIG
, sizeof(cfg
), &cfg
, 1);
131 int rsxx_load_config(struct rsxx_cardinfo
*card
)
136 st
= rsxx_creg_read(card
, CREG_ADD_CONFIG
, sizeof(card
->config
),
139 dev_err(CARD_TO_DEV(card
),
140 "Failed reading card config.\n");
144 config_hdr_be_to_cpu(&card
->config
.hdr
);
146 if (card
->config
.hdr
.version
== RSXX_CFG_VERSION
) {
148 * We calculate the CRC with the data in little endian, because
149 * early drivers did not take big endian CPUs into account.
150 * The data is always stored in big endian, so we need to byte
151 * swap it before calculating the CRC.
154 config_data_swab(&card
->config
);
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
);
167 /* Convert the data to CPU byteorder */
168 config_data_le_to_cpu(&card
->config
);
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
);
175 * Config version changes require special handling from the
180 dev_info(CARD_TO_DEV(card
),
181 "Initializing card configuration.\n");
182 initialize_config(&card
->config
);
183 st
= rsxx_save_config(card
);
188 card
->config_valid
= 1;
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
);