aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-eeprom.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-04-21 18:41:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:15 -0400
commit073d3f5f1b3b6512eb82a3d40c84dedb14dc6f73 (patch)
tree49ef76bf1d863a231b0a672c2c34fb44f63fad9c /drivers/net/wireless/iwlwifi/iwl-eeprom.c
parent5da4b55f78fb2ed40926b775d4f7c791594ecbd7 (diff)
iwlwifi: changing EEPROM layout handling
This patch 1. changes the current EEPROM handling through a single HW struct layout representation, to more general approach, treating the EEPROM image as a flat bytes array, handling this image through ops functions and offsets. 2. Eeprom is dynamically allocated accroding HW type Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-eeprom.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index a07d5dcb7abc..a436f877882b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -193,6 +193,12 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
193} 193}
194EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); 194EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
195 195
196const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
197{
198 BUG_ON(offset >= priv->cfg->eeprom_size);
199 return &priv->eeprom[offset];
200}
201EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
196 202
197/** 203/**
198 * iwl_eeprom_init - read EEPROM contents 204 * iwl_eeprom_init - read EEPROM contents
@@ -203,30 +209,35 @@ EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
203 */ 209 */
204int iwl_eeprom_init(struct iwl_priv *priv) 210int iwl_eeprom_init(struct iwl_priv *priv)
205{ 211{
206 u16 *e = (u16 *)&priv->eeprom; 212 u16 *e;
207 u32 gp = iwl_read32(priv, CSR_EEPROM_GP); 213 u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
208 u32 r; 214 u32 r;
209 int sz = sizeof(priv->eeprom); 215 int sz = priv->cfg->eeprom_size;
210 int ret; 216 int ret;
211 int i; 217 int i;
212 u16 addr; 218 u16 addr;
213 219
214 /* The EEPROM structure has several padding buffers within it 220 /* allocate eeprom */
215 * and when adding new EEPROM maps is subject to programmer errors 221 priv->eeprom = kzalloc(sz, GFP_KERNEL);
216 * which may be very difficult to identify without explicitly 222 if (!priv->eeprom) {
217 * checking the resulting size of the eeprom map. */ 223 ret = -ENOMEM;
218 BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); 224 goto alloc_err;
225 }
226 e = (u16 *)priv->eeprom;
219 227
220 if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { 228 ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
229 if (ret < 0) {
221 IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); 230 IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
222 return -ENOENT; 231 ret = -ENOENT;
232 goto err;
223 } 233 }
224 234
225 /* Make sure driver (instead of uCode) is allowed to read EEPROM */ 235 /* Make sure driver (instead of uCode) is allowed to read EEPROM */
226 ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); 236 ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
227 if (ret < 0) { 237 if (ret < 0) {
228 IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); 238 IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
229 return -ENOENT; 239 ret = -ENOENT;
240 goto err;
230 } 241 }
231 242
232 /* eeprom is an array of 16bit values */ 243 /* eeprom is an array of 16bit values */
@@ -250,61 +261,93 @@ int iwl_eeprom_init(struct iwl_priv *priv)
250 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); 261 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
251 } 262 }
252 ret = 0; 263 ret = 0;
253
254done: 264done:
255 priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); 265 priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
266err:
267 if (ret)
268 kfree(priv->eeprom);
269alloc_err:
256 return ret; 270 return ret;
257} 271}
258EXPORT_SYMBOL(iwl_eeprom_init); 272EXPORT_SYMBOL(iwl_eeprom_init);
259 273
274void iwl_eeprom_free(struct iwl_priv *priv)
275{
276 if(priv->eeprom)
277 kfree(priv->eeprom);
278 priv->eeprom = NULL;
279}
280EXPORT_SYMBOL(iwl_eeprom_free);
281
282
283const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
284{
285 return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
286}
287EXPORT_SYMBOL(iwl_eeprom_query_addr);
288
289u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
290{
291 return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
292}
293EXPORT_SYMBOL(iwl_eeprom_query16);
260 294
261void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) 295void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
262{ 296{
263 memcpy(mac, priv->eeprom.mac_address, 6); 297 const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
298 EEPROM_MAC_ADDRESS);
299 memcpy(mac, addr, ETH_ALEN);
264} 300}
265EXPORT_SYMBOL(iwl_eeprom_get_mac); 301EXPORT_SYMBOL(iwl_eeprom_get_mac);
266 302
267static void iwl_init_band_reference(const struct iwl_priv *priv, 303static void iwl_init_band_reference(const struct iwl_priv *priv,
268 int band, 304 int eep_band, int *eeprom_ch_count,
269 int *eeprom_ch_count, 305 const struct iwl_eeprom_channel **eeprom_ch_info,
270 const struct iwl4965_eeprom_channel 306 const u8 **eeprom_ch_index)
271 **eeprom_ch_info,
272 const u8 **eeprom_ch_index)
273{ 307{
274 switch (band) { 308 u32 offset = priv->cfg->ops->lib->
309 eeprom_ops.regulatory_bands[eep_band - 1];
310 switch (eep_band) {
275 case 1: /* 2.4GHz band */ 311 case 1: /* 2.4GHz band */
276 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); 312 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
277 *eeprom_ch_info = priv->eeprom.band_1_channels; 313 *eeprom_ch_info = (struct iwl_eeprom_channel *)
314 iwl_eeprom_query_addr(priv, offset);
278 *eeprom_ch_index = iwl_eeprom_band_1; 315 *eeprom_ch_index = iwl_eeprom_band_1;
279 break; 316 break;
280 case 2: /* 4.9GHz band */ 317 case 2: /* 4.9GHz band */
281 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); 318 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
282 *eeprom_ch_info = priv->eeprom.band_2_channels; 319 *eeprom_ch_info = (struct iwl_eeprom_channel *)
320 iwl_eeprom_query_addr(priv, offset);
283 *eeprom_ch_index = iwl_eeprom_band_2; 321 *eeprom_ch_index = iwl_eeprom_band_2;
284 break; 322 break;
285 case 3: /* 5.2GHz band */ 323 case 3: /* 5.2GHz band */
286 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); 324 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
287 *eeprom_ch_info = priv->eeprom.band_3_channels; 325 *eeprom_ch_info = (struct iwl_eeprom_channel *)
326 iwl_eeprom_query_addr(priv, offset);
288 *eeprom_ch_index = iwl_eeprom_band_3; 327 *eeprom_ch_index = iwl_eeprom_band_3;
289 break; 328 break;
290 case 4: /* 5.5GHz band */ 329 case 4: /* 5.5GHz band */
291 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); 330 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
292 *eeprom_ch_info = priv->eeprom.band_4_channels; 331 *eeprom_ch_info = (struct iwl_eeprom_channel *)
332 iwl_eeprom_query_addr(priv, offset);
293 *eeprom_ch_index = iwl_eeprom_band_4; 333 *eeprom_ch_index = iwl_eeprom_band_4;
294 break; 334 break;
295 case 5: /* 5.7GHz band */ 335 case 5: /* 5.7GHz band */
296 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); 336 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
297 *eeprom_ch_info = priv->eeprom.band_5_channels; 337 *eeprom_ch_info = (struct iwl_eeprom_channel *)
338 iwl_eeprom_query_addr(priv, offset);
298 *eeprom_ch_index = iwl_eeprom_band_5; 339 *eeprom_ch_index = iwl_eeprom_band_5;
299 break; 340 break;
300 case 6: /* 2.4GHz FAT channels */ 341 case 6: /* 2.4GHz FAT channels */
301 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); 342 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
302 *eeprom_ch_info = priv->eeprom.band_24_channels; 343 *eeprom_ch_info = (struct iwl_eeprom_channel *)
344 iwl_eeprom_query_addr(priv, offset);
303 *eeprom_ch_index = iwl_eeprom_band_6; 345 *eeprom_ch_index = iwl_eeprom_band_6;
304 break; 346 break;
305 case 7: /* 5 GHz FAT channels */ 347 case 7: /* 5 GHz FAT channels */
306 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); 348 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
307 *eeprom_ch_info = priv->eeprom.band_52_channels; 349 *eeprom_ch_info = (struct iwl_eeprom_channel *)
350 iwl_eeprom_query_addr(priv, offset);
308 *eeprom_ch_index = iwl_eeprom_band_7; 351 *eeprom_ch_index = iwl_eeprom_band_7;
309 break; 352 break;
310 default: 353 default:
@@ -323,7 +366,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
323 */ 366 */
324static int iwl4965_set_fat_chan_info(struct iwl_priv *priv, 367static int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
325 enum ieee80211_band band, u16 channel, 368 enum ieee80211_band band, u16 channel,
326 const struct iwl4965_eeprom_channel *eeprom_ch, 369 const struct iwl_eeprom_channel *eeprom_ch,
327 u8 fat_extension_channel) 370 u8 fat_extension_channel)
328{ 371{
329 struct iwl_channel_info *ch_info; 372 struct iwl_channel_info *ch_info;
@@ -372,7 +415,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
372{ 415{
373 int eeprom_ch_count = 0; 416 int eeprom_ch_count = 0;
374 const u8 *eeprom_ch_index = NULL; 417 const u8 *eeprom_ch_index = NULL;
375 const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL; 418 const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
376 int band, ch; 419 int band, ch;
377 struct iwl_channel_info *ch_info; 420 struct iwl_channel_info *ch_info;
378 421
@@ -381,9 +424,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
381 return 0; 424 return 0;
382 } 425 }
383 426
384 if (priv->eeprom.version < 0x2f) { 427 if (iwl_eeprom_query16(priv, EEPROM_VERSION) < 0x2f) {
385 IWL_WARNING("Unsupported EEPROM version: 0x%04X\n", 428 IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
386 priv->eeprom.version); 429 iwl_eeprom_query16(priv, EEPROM_VERSION));
387 return -EINVAL; 430 return -EINVAL;
388 } 431 }
389 432