2 * EEPROM parser code for mac80211 Prism54 drivers
4 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
5 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
9 * - the islsm (softmac prism54) driver, which is:
10 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
12 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
19 #include <linux/init.h>
20 #include <linux/firmware.h>
21 #include <linux/etherdevice.h>
22 #include <linux/sort.h>
23 #include <linux/slab.h>
25 #include <net/mac80211.h>
31 static struct ieee80211_rate p54_bgrates
[] = {
32 { .bitrate
= 10, .hw_value
= 0, },
33 { .bitrate
= 20, .hw_value
= 1, .flags
= IEEE80211_RATE_SHORT_PREAMBLE
},
34 { .bitrate
= 55, .hw_value
= 2, .flags
= IEEE80211_RATE_SHORT_PREAMBLE
},
35 { .bitrate
= 110, .hw_value
= 3, .flags
= IEEE80211_RATE_SHORT_PREAMBLE
},
36 { .bitrate
= 60, .hw_value
= 4, },
37 { .bitrate
= 90, .hw_value
= 5, },
38 { .bitrate
= 120, .hw_value
= 6, },
39 { .bitrate
= 180, .hw_value
= 7, },
40 { .bitrate
= 240, .hw_value
= 8, },
41 { .bitrate
= 360, .hw_value
= 9, },
42 { .bitrate
= 480, .hw_value
= 10, },
43 { .bitrate
= 540, .hw_value
= 11, },
46 static struct ieee80211_rate p54_arates
[] = {
47 { .bitrate
= 60, .hw_value
= 4, },
48 { .bitrate
= 90, .hw_value
= 5, },
49 { .bitrate
= 120, .hw_value
= 6, },
50 { .bitrate
= 180, .hw_value
= 7, },
51 { .bitrate
= 240, .hw_value
= 8, },
52 { .bitrate
= 360, .hw_value
= 9, },
53 { .bitrate
= 480, .hw_value
= 10, },
54 { .bitrate
= 540, .hw_value
= 11, },
57 #define CHAN_HAS_CAL BIT(0)
58 #define CHAN_HAS_LIMIT BIT(1)
59 #define CHAN_HAS_CURVE BIT(2)
60 #define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE)
62 struct p54_channel_entry
{
66 enum ieee80211_band band
;
69 struct p54_channel_list
{
70 struct p54_channel_entry
*channels
;
73 size_t band_channel_num
[IEEE80211_NUM_BANDS
];
76 static int p54_get_band_from_freq(u16 freq
)
78 /* FIXME: sync these values with the 802.11 spec */
80 if ((freq
>= 2412) && (freq
<= 2484))
81 return IEEE80211_BAND_2GHZ
;
83 if ((freq
>= 4920) && (freq
<= 5825))
84 return IEEE80211_BAND_5GHZ
;
89 static int p54_compare_channels(const void *_a
,
92 const struct p54_channel_entry
*a
= _a
;
93 const struct p54_channel_entry
*b
= _b
;
95 return a
->index
- b
->index
;
98 static int p54_fill_band_bitrates(struct ieee80211_hw
*dev
,
99 struct ieee80211_supported_band
*band_entry
,
100 enum ieee80211_band band
)
102 /* TODO: generate rate array dynamically */
105 case IEEE80211_BAND_2GHZ
:
106 band_entry
->bitrates
= p54_bgrates
;
107 band_entry
->n_bitrates
= ARRAY_SIZE(p54_bgrates
);
109 case IEEE80211_BAND_5GHZ
:
110 band_entry
->bitrates
= p54_arates
;
111 band_entry
->n_bitrates
= ARRAY_SIZE(p54_arates
);
120 static int p54_generate_band(struct ieee80211_hw
*dev
,
121 struct p54_channel_list
*list
,
122 enum ieee80211_band band
)
124 struct p54_common
*priv
= dev
->priv
;
125 struct ieee80211_supported_band
*tmp
, *old
;
129 if ((!list
->entries
) || (!list
->band_channel_num
[band
]))
132 tmp
= kzalloc(sizeof(*tmp
), GFP_KERNEL
);
136 tmp
->channels
= kzalloc(sizeof(struct ieee80211_channel
) *
137 list
->band_channel_num
[band
], GFP_KERNEL
);
141 ret
= p54_fill_band_bitrates(dev
, tmp
, band
);
145 for (i
= 0, j
= 0; (j
< list
->band_channel_num
[band
]) &&
146 (i
< list
->entries
); i
++) {
148 if (list
->channels
[i
].band
!= band
)
151 if (list
->channels
[i
].data
!= CHAN_HAS_ALL
) {
152 printk(KERN_ERR
"%s:%s%s%s is/are missing for "
153 "channel:%d [%d MHz].\n",
154 wiphy_name(dev
->wiphy
),
155 (list
->channels
[i
].data
& CHAN_HAS_CAL
? "" :
156 " [iqauto calibration data]"),
157 (list
->channels
[i
].data
& CHAN_HAS_LIMIT
? "" :
158 " [output power limits]"),
159 (list
->channels
[i
].data
& CHAN_HAS_CURVE
? "" :
161 list
->channels
[i
].index
, list
->channels
[i
].freq
);
165 tmp
->channels
[j
].band
= list
->channels
[i
].band
;
166 tmp
->channels
[j
].center_freq
= list
->channels
[i
].freq
;
171 printk(KERN_ERR
"%s: Disabling totally damaged %s band.\n",
172 wiphy_name(dev
->wiphy
), (band
== IEEE80211_BAND_2GHZ
) ?
180 old
= priv
->band_table
[band
];
181 priv
->band_table
[band
] = tmp
;
183 kfree(old
->channels
);
191 kfree(tmp
->channels
);
198 static void p54_update_channel_param(struct p54_channel_list
*list
,
204 * usually all lists in the eeprom are mostly sorted.
205 * so it's very likely that the entry we are looking for
206 * is right at the end of the list
208 for (i
= list
->entries
; i
>= 0; i
--) {
209 if (freq
== list
->channels
[i
].freq
) {
210 list
->channels
[i
].data
|= data
;
215 if ((i
< 0) && (list
->entries
< list
->max_entries
)) {
216 /* entry does not exist yet. Initialize a new one. */
217 band
= p54_get_band_from_freq(freq
);
220 * filter out frequencies which don't belong into
221 * any supported band.
227 list
->band_channel_num
[band
]++;
229 list
->channels
[i
].freq
= freq
;
230 list
->channels
[i
].data
= data
;
231 list
->channels
[i
].band
= band
;
232 list
->channels
[i
].index
= ieee80211_frequency_to_channel(freq
);
233 /* TODO: parse output_limit and fill max_power */
237 static int p54_generate_channel_lists(struct ieee80211_hw
*dev
)
239 struct p54_common
*priv
= dev
->priv
;
240 struct p54_channel_list
*list
;
241 unsigned int i
, j
, max_channel_num
;
245 if ((priv
->iq_autocal_len
!= priv
->curve_data
->entries
) ||
246 (priv
->iq_autocal_len
!= priv
->output_limit
->entries
))
247 printk(KERN_ERR
"%s: Unsupported or damaged EEPROM detected. "
248 "You may not be able to use all channels.\n",
249 wiphy_name(dev
->wiphy
));
251 max_channel_num
= max_t(unsigned int, priv
->output_limit
->entries
,
252 priv
->iq_autocal_len
);
253 max_channel_num
= max_t(unsigned int, max_channel_num
,
254 priv
->curve_data
->entries
);
256 list
= kzalloc(sizeof(*list
), GFP_KERNEL
);
262 list
->max_entries
= max_channel_num
;
263 list
->channels
= kzalloc(sizeof(struct p54_channel_entry
) *
264 max_channel_num
, GFP_KERNEL
);
265 if (!list
->channels
) {
270 for (i
= 0; i
< max_channel_num
; i
++) {
271 if (i
< priv
->iq_autocal_len
) {
272 freq
= le16_to_cpu(priv
->iq_autocal
[i
].freq
);
273 p54_update_channel_param(list
, freq
, CHAN_HAS_CAL
);
276 if (i
< priv
->output_limit
->entries
) {
277 freq
= le16_to_cpup((__le16
*) (i
*
278 priv
->output_limit
->entry_size
+
279 priv
->output_limit
->offset
+
280 priv
->output_limit
->data
));
282 p54_update_channel_param(list
, freq
, CHAN_HAS_LIMIT
);
285 if (i
< priv
->curve_data
->entries
) {
286 freq
= le16_to_cpup((__le16
*) (i
*
287 priv
->curve_data
->entry_size
+
288 priv
->curve_data
->offset
+
289 priv
->curve_data
->data
));
291 p54_update_channel_param(list
, freq
, CHAN_HAS_CURVE
);
295 /* sort the list by the channel index */
296 sort(list
->channels
, list
->entries
, sizeof(struct p54_channel_entry
),
297 p54_compare_channels
, NULL
);
299 for (i
= 0, j
= 0; i
< IEEE80211_NUM_BANDS
; i
++) {
300 if (p54_generate_band(dev
, list
, i
) == 0)
304 /* no useable band available. */
310 kfree(list
->channels
);
317 static int p54_convert_rev0(struct ieee80211_hw
*dev
,
318 struct pda_pa_curve_data
*curve_data
)
320 struct p54_common
*priv
= dev
->priv
;
321 struct p54_pa_curve_data_sample
*dst
;
322 struct pda_pa_curve_data_sample_rev0
*src
;
323 size_t cd_len
= sizeof(*curve_data
) +
324 (curve_data
->points_per_channel
*sizeof(*dst
) + 2) *
325 curve_data
->channels
;
327 void *source
, *target
;
329 priv
->curve_data
= kmalloc(sizeof(*priv
->curve_data
) + cd_len
,
331 if (!priv
->curve_data
)
334 priv
->curve_data
->entries
= curve_data
->channels
;
335 priv
->curve_data
->entry_size
= sizeof(__le16
) +
336 sizeof(*dst
) * curve_data
->points_per_channel
;
337 priv
->curve_data
->offset
= offsetof(struct pda_pa_curve_data
, data
);
338 priv
->curve_data
->len
= cd_len
;
339 memcpy(priv
->curve_data
->data
, curve_data
, sizeof(*curve_data
));
340 source
= curve_data
->data
;
341 target
= ((struct pda_pa_curve_data
*) priv
->curve_data
->data
)->data
;
342 for (i
= 0; i
< curve_data
->channels
; i
++) {
343 __le16
*freq
= source
;
344 source
+= sizeof(__le16
);
345 *((__le16
*)target
) = *freq
;
346 target
+= sizeof(__le16
);
347 for (j
= 0; j
< curve_data
->points_per_channel
; j
++) {
351 dst
->rf_power
= src
->rf_power
;
352 dst
->pa_detector
= src
->pa_detector
;
353 dst
->data_64qam
= src
->pcv
;
354 /* "invent" the points for the other modulations */
355 #define SUB(x, y) (u8)(((x) - (y)) > (x) ? 0 : (x) - (y))
356 dst
->data_16qam
= SUB(src
->pcv
, 12);
357 dst
->data_qpsk
= SUB(dst
->data_16qam
, 12);
358 dst
->data_bpsk
= SUB(dst
->data_qpsk
, 12);
359 dst
->data_barker
= SUB(dst
->data_bpsk
, 14);
361 target
+= sizeof(*dst
);
362 source
+= sizeof(*src
);
369 static int p54_convert_rev1(struct ieee80211_hw
*dev
,
370 struct pda_pa_curve_data
*curve_data
)
372 struct p54_common
*priv
= dev
->priv
;
373 struct p54_pa_curve_data_sample
*dst
;
374 struct pda_pa_curve_data_sample_rev1
*src
;
375 size_t cd_len
= sizeof(*curve_data
) +
376 (curve_data
->points_per_channel
*sizeof(*dst
) + 2) *
377 curve_data
->channels
;
379 void *source
, *target
;
381 priv
->curve_data
= kzalloc(cd_len
+ sizeof(*priv
->curve_data
),
383 if (!priv
->curve_data
)
386 priv
->curve_data
->entries
= curve_data
->channels
;
387 priv
->curve_data
->entry_size
= sizeof(__le16
) +
388 sizeof(*dst
) * curve_data
->points_per_channel
;
389 priv
->curve_data
->offset
= offsetof(struct pda_pa_curve_data
, data
);
390 priv
->curve_data
->len
= cd_len
;
391 memcpy(priv
->curve_data
->data
, curve_data
, sizeof(*curve_data
));
392 source
= curve_data
->data
;
393 target
= ((struct pda_pa_curve_data
*) priv
->curve_data
->data
)->data
;
394 for (i
= 0; i
< curve_data
->channels
; i
++) {
395 __le16
*freq
= source
;
396 source
+= sizeof(__le16
);
397 *((__le16
*)target
) = *freq
;
398 target
+= sizeof(__le16
);
399 for (j
= 0; j
< curve_data
->points_per_channel
; j
++) {
400 memcpy(target
, source
, sizeof(*src
));
402 target
+= sizeof(*dst
);
403 source
+= sizeof(*src
);
411 static const char *p54_rf_chips
[] = { "INVALID-0", "Duette3", "Duette2",
412 "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
414 static void p54_parse_rssical(struct ieee80211_hw
*dev
, void *data
, int len
,
417 struct p54_common
*priv
= dev
->priv
;
418 int offset
= (type
== PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED
) ? 2 : 0;
419 int entry_size
= sizeof(struct pda_rssi_cal_entry
) + offset
;
420 int num_entries
= (type
== PDR_RSSI_LINEAR_APPROXIMATION
) ? 1 : 2;
423 if (len
!= (entry_size
* num_entries
)) {
424 printk(KERN_ERR
"%s: unknown rssi calibration data packing "
425 " type:(%x) len:%d.\n",
426 wiphy_name(dev
->wiphy
), type
, len
);
428 print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE
,
431 printk(KERN_ERR
"%s: please report this issue.\n",
432 wiphy_name(dev
->wiphy
));
436 for (i
= 0; i
< num_entries
; i
++) {
437 struct pda_rssi_cal_entry
*cal
= data
+
438 (offset
+ i
* entry_size
);
439 priv
->rssical_db
[i
].mul
= (s16
) le16_to_cpu(cal
->mul
);
440 priv
->rssical_db
[i
].add
= (s16
) le16_to_cpu(cal
->add
);
444 static void p54_parse_default_country(struct ieee80211_hw
*dev
,
447 struct pda_country
*country
;
449 if (len
!= sizeof(*country
)) {
450 printk(KERN_ERR
"%s: found possible invalid default country "
451 "eeprom entry. (entry size: %d)\n",
452 wiphy_name(dev
->wiphy
), len
);
454 print_hex_dump_bytes("country:", DUMP_PREFIX_NONE
,
457 printk(KERN_ERR
"%s: please report this issue.\n",
458 wiphy_name(dev
->wiphy
));
462 country
= (struct pda_country
*) data
;
463 if (country
->flags
== PDR_COUNTRY_CERT_CODE_PSEUDO
)
464 regulatory_hint(dev
->wiphy
, country
->alpha2
);
467 * write a shared/common function that converts
468 * "Regulatory domain codes" (802.11-2007 14.8.2.2)
469 * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
474 static int p54_convert_output_limits(struct ieee80211_hw
*dev
,
475 u8
*data
, size_t len
)
477 struct p54_common
*priv
= dev
->priv
;
483 printk(KERN_ERR
"%s: unknown output power db revision:%x\n",
484 wiphy_name(dev
->wiphy
), data
[0]);
488 if (2 + data
[1] * sizeof(struct pda_channel_output_limit
) > len
)
491 priv
->output_limit
= kmalloc(data
[1] *
492 sizeof(struct pda_channel_output_limit
) +
493 sizeof(*priv
->output_limit
), GFP_KERNEL
);
495 if (!priv
->output_limit
)
498 priv
->output_limit
->offset
= 0;
499 priv
->output_limit
->entries
= data
[1];
500 priv
->output_limit
->entry_size
=
501 sizeof(struct pda_channel_output_limit
);
502 priv
->output_limit
->len
= priv
->output_limit
->entry_size
*
503 priv
->output_limit
->entries
+
504 priv
->output_limit
->offset
;
506 memcpy(priv
->output_limit
->data
, &data
[2],
507 data
[1] * sizeof(struct pda_channel_output_limit
));
512 static struct p54_cal_database
*p54_convert_db(struct pda_custom_wrapper
*src
,
515 struct p54_cal_database
*dst
;
516 size_t payload_len
, entries
, entry_size
, offset
;
518 payload_len
= le16_to_cpu(src
->len
);
519 entries
= le16_to_cpu(src
->entries
);
520 entry_size
= le16_to_cpu(src
->entry_size
);
521 offset
= le16_to_cpu(src
->offset
);
522 if (((entries
* entry_size
+ offset
) != payload_len
) ||
523 (payload_len
+ sizeof(*src
) != total_len
))
526 dst
= kmalloc(sizeof(*dst
) + payload_len
, GFP_KERNEL
);
530 dst
->entries
= entries
;
531 dst
->entry_size
= entry_size
;
532 dst
->offset
= offset
;
533 dst
->len
= payload_len
;
535 memcpy(dst
->data
, src
->data
, payload_len
);
539 int p54_parse_eeprom(struct ieee80211_hw
*dev
, void *eeprom
, int len
)
541 struct p54_common
*priv
= dev
->priv
;
542 struct eeprom_pda_wrap
*wrap
;
543 struct pda_entry
*entry
;
544 unsigned int data_len
, entry_len
;
547 u8
*end
= (u8
*)eeprom
+ len
;
550 wrap
= (struct eeprom_pda_wrap
*) eeprom
;
551 entry
= (void *)wrap
->data
+ le16_to_cpu(wrap
->len
);
553 /* verify that at least the entry length/code fits */
554 while ((u8
*)entry
<= end
- sizeof(*entry
)) {
555 entry_len
= le16_to_cpu(entry
->len
);
556 data_len
= ((entry_len
- 1) << 1);
558 /* abort if entry exceeds whole structure */
559 if ((u8
*)entry
+ sizeof(*entry
) + data_len
> end
)
562 switch (le16_to_cpu(entry
->code
)) {
563 case PDR_MAC_ADDRESS
:
564 if (data_len
!= ETH_ALEN
)
566 SET_IEEE80211_PERM_ADDR(dev
, entry
->data
);
568 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS
:
569 if (priv
->output_limit
)
571 err
= p54_convert_output_limits(dev
, entry
->data
,
576 case PDR_PRISM_PA_CAL_CURVE_DATA
: {
577 struct pda_pa_curve_data
*curve_data
=
578 (struct pda_pa_curve_data
*)entry
->data
;
579 if (data_len
< sizeof(*curve_data
)) {
584 switch (curve_data
->cal_method_rev
) {
586 err
= p54_convert_rev0(dev
, curve_data
);
589 err
= p54_convert_rev1(dev
, curve_data
);
592 printk(KERN_ERR
"%s: unknown curve data "
594 wiphy_name(dev
->wiphy
),
595 curve_data
->cal_method_rev
);
603 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION
:
604 priv
->iq_autocal
= kmalloc(data_len
, GFP_KERNEL
);
605 if (!priv
->iq_autocal
) {
610 memcpy(priv
->iq_autocal
, entry
->data
, data_len
);
611 priv
->iq_autocal_len
= data_len
/ sizeof(struct pda_iq_autocal_entry
);
613 case PDR_DEFAULT_COUNTRY
:
614 p54_parse_default_country(dev
, entry
->data
, data_len
);
616 case PDR_INTERFACE_LIST
:
618 while ((u8
*)tmp
< entry
->data
+ data_len
) {
619 struct exp_if
*exp_if
= tmp
;
620 if (exp_if
->if_id
== cpu_to_le16(IF_ID_ISL39000
))
621 synth
= le16_to_cpu(exp_if
->variant
);
622 tmp
+= sizeof(*exp_if
);
625 case PDR_HARDWARE_PLATFORM_COMPONENT_ID
:
628 priv
->version
= *(u8
*)(entry
->data
+ 1);
630 case PDR_RSSI_LINEAR_APPROXIMATION
:
631 case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND
:
632 case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED
:
633 p54_parse_rssical(dev
, entry
->data
, data_len
,
634 le16_to_cpu(entry
->code
));
636 case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM
: {
637 __le16
*src
= (void *) entry
->data
;
638 s16
*dst
= (void *) &priv
->rssical_db
;
641 if (data_len
!= sizeof(priv
->rssical_db
)) {
645 for (i
= 0; i
< sizeof(priv
->rssical_db
) /
647 *(dst
++) = (s16
) le16_to_cpu(*(src
++));
650 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM
: {
651 struct pda_custom_wrapper
*pda
= (void *) entry
->data
;
652 if (priv
->output_limit
|| data_len
< sizeof(*pda
))
654 priv
->output_limit
= p54_convert_db(pda
, data_len
);
657 case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM
: {
658 struct pda_custom_wrapper
*pda
= (void *) entry
->data
;
659 if (priv
->curve_data
|| data_len
< sizeof(*pda
))
661 priv
->curve_data
= p54_convert_db(pda
, data_len
);
665 /* make it overrun */
672 entry
= (void *)entry
+ (entry_len
+ 1)*2;
675 if (!synth
|| !priv
->iq_autocal
|| !priv
->output_limit
||
677 printk(KERN_ERR
"%s: not all required entries found in eeprom!\n",
678 wiphy_name(dev
->wiphy
));
683 err
= p54_generate_channel_lists(dev
);
687 priv
->rxhw
= synth
& PDR_SYNTH_FRONTEND_MASK
;
688 if (priv
->rxhw
== PDR_SYNTH_FRONTEND_XBOW
)
689 p54_init_xbow_synth(priv
);
690 if (!(synth
& PDR_SYNTH_24_GHZ_DISABLED
))
691 dev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] =
692 priv
->band_table
[IEEE80211_BAND_2GHZ
];
693 if (!(synth
& PDR_SYNTH_5_GHZ_DISABLED
))
694 dev
->wiphy
->bands
[IEEE80211_BAND_5GHZ
] =
695 priv
->band_table
[IEEE80211_BAND_5GHZ
];
696 if ((synth
& PDR_SYNTH_RX_DIV_MASK
) == PDR_SYNTH_RX_DIV_SUPPORTED
)
697 priv
->rx_diversity_mask
= 3;
698 if ((synth
& PDR_SYNTH_TX_DIV_MASK
) == PDR_SYNTH_TX_DIV_SUPPORTED
)
699 priv
->tx_diversity_mask
= 3;
701 if (!is_valid_ether_addr(dev
->wiphy
->perm_addr
)) {
702 u8 perm_addr
[ETH_ALEN
];
704 printk(KERN_WARNING
"%s: Invalid hwaddr! Using randomly generated MAC addr\n",
705 wiphy_name(dev
->wiphy
));
706 random_ether_addr(perm_addr
);
707 SET_IEEE80211_PERM_ADDR(dev
, perm_addr
);
710 printk(KERN_INFO
"%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
711 wiphy_name(dev
->wiphy
), dev
->wiphy
->perm_addr
, priv
->version
,
712 p54_rf_chips
[priv
->rxhw
]);
717 kfree(priv
->iq_autocal
);
718 kfree(priv
->output_limit
);
719 kfree(priv
->curve_data
);
720 priv
->iq_autocal
= NULL
;
721 priv
->output_limit
= NULL
;
722 priv
->curve_data
= NULL
;
724 printk(KERN_ERR
"%s: eeprom parse failed!\n",
725 wiphy_name(dev
->wiphy
));
728 EXPORT_SYMBOL_GPL(p54_parse_eeprom
);
730 int p54_read_eeprom(struct ieee80211_hw
*dev
)
732 struct p54_common
*priv
= dev
->priv
;
733 size_t eeprom_size
= 0x2020, offset
= 0, blocksize
, maxblocksize
;
737 maxblocksize
= EEPROM_READBACK_LEN
;
738 if (priv
->fw_var
>= 0x509)
743 eeprom
= kzalloc(eeprom_size
, GFP_KERNEL
);
744 if (unlikely(!eeprom
))
747 while (eeprom_size
) {
748 blocksize
= min(eeprom_size
, maxblocksize
);
749 ret
= p54_download_eeprom(priv
, (void *) (eeprom
+ offset
),
755 eeprom_size
-= blocksize
;
758 ret
= p54_parse_eeprom(dev
, eeprom
, offset
);
763 EXPORT_SYMBOL_GPL(p54_read_eeprom
);