diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2008-04-21 18:41:52 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-07 15:02:15 -0400 |
commit | 073d3f5f1b3b6512eb82a3d40c84dedb14dc6f73 (patch) | |
tree | 49ef76bf1d863a231b0a672c2c34fb44f63fad9c /drivers/net/wireless/iwlwifi/iwl-eeprom.c | |
parent | 5da4b55f78fb2ed40926b775d4f7c791594ecbd7 (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.c | 101 |
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 | } |
194 | EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); | 194 | EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); |
195 | 195 | ||
196 | const 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 | } | ||
201 | EXPORT_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 | */ |
204 | int iwl_eeprom_init(struct iwl_priv *priv) | 210 | int 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 | |||
254 | done: | 264 | done: |
255 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); | 265 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); |
266 | err: | ||
267 | if (ret) | ||
268 | kfree(priv->eeprom); | ||
269 | alloc_err: | ||
256 | return ret; | 270 | return ret; |
257 | } | 271 | } |
258 | EXPORT_SYMBOL(iwl_eeprom_init); | 272 | EXPORT_SYMBOL(iwl_eeprom_init); |
259 | 273 | ||
274 | void iwl_eeprom_free(struct iwl_priv *priv) | ||
275 | { | ||
276 | if(priv->eeprom) | ||
277 | kfree(priv->eeprom); | ||
278 | priv->eeprom = NULL; | ||
279 | } | ||
280 | EXPORT_SYMBOL(iwl_eeprom_free); | ||
281 | |||
282 | |||
283 | const 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 | } | ||
287 | EXPORT_SYMBOL(iwl_eeprom_query_addr); | ||
288 | |||
289 | u16 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 | } | ||
293 | EXPORT_SYMBOL(iwl_eeprom_query16); | ||
260 | 294 | ||
261 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | 295 | void 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 | } |
265 | EXPORT_SYMBOL(iwl_eeprom_get_mac); | 301 | EXPORT_SYMBOL(iwl_eeprom_get_mac); |
266 | 302 | ||
267 | static void iwl_init_band_reference(const struct iwl_priv *priv, | 303 | static 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 | */ |
324 | static int iwl4965_set_fat_chan_info(struct iwl_priv *priv, | 367 | static 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 | ||