diff options
Diffstat (limited to 'drivers/net/wireless/p54/eeprom.c')
-rw-r--r-- | drivers/net/wireless/p54/eeprom.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 78347041ec40..35b09aa0529b 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | 24 | ||
25 | #include <net/mac80211.h> | 25 | #include <net/mac80211.h> |
26 | #include <linux/crc-ccitt.h> | ||
26 | 27 | ||
27 | #include "p54.h" | 28 | #include "p54.h" |
28 | #include "eeprom.h" | 29 | #include "eeprom.h" |
@@ -260,8 +261,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) | |||
260 | list->max_entries = max_channel_num; | 261 | list->max_entries = max_channel_num; |
261 | list->channels = kzalloc(sizeof(struct p54_channel_entry) * | 262 | list->channels = kzalloc(sizeof(struct p54_channel_entry) * |
262 | max_channel_num, GFP_KERNEL); | 263 | max_channel_num, GFP_KERNEL); |
263 | if (!list->channels) | 264 | if (!list->channels) { |
265 | ret = -ENOMEM; | ||
264 | goto free; | 266 | goto free; |
267 | } | ||
265 | 268 | ||
266 | for (i = 0; i < max_channel_num; i++) { | 269 | for (i = 0; i < max_channel_num; i++) { |
267 | if (i < priv->iq_autocal_len) { | 270 | if (i < priv->iq_autocal_len) { |
@@ -540,6 +543,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
540 | int err; | 543 | int err; |
541 | u8 *end = (u8 *)eeprom + len; | 544 | u8 *end = (u8 *)eeprom + len; |
542 | u16 synth = 0; | 545 | u16 synth = 0; |
546 | u16 crc16 = ~0; | ||
543 | 547 | ||
544 | wrap = (struct eeprom_pda_wrap *) eeprom; | 548 | wrap = (struct eeprom_pda_wrap *) eeprom; |
545 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); | 549 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); |
@@ -655,16 +659,29 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
655 | } | 659 | } |
656 | break; | 660 | break; |
657 | case PDR_END: | 661 | case PDR_END: |
658 | /* make it overrun */ | 662 | crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry)); |
659 | entry_len = len; | 663 | if (crc16 != le16_to_cpup((__le16 *)entry->data)) { |
664 | wiphy_err(dev->wiphy, "eeprom failed checksum " | ||
665 | "test!\n"); | ||
666 | err = -ENOMSG; | ||
667 | goto err; | ||
668 | } else { | ||
669 | goto good_eeprom; | ||
670 | } | ||
660 | break; | 671 | break; |
661 | default: | 672 | default: |
662 | break; | 673 | break; |
663 | } | 674 | } |
664 | 675 | ||
665 | entry = (void *)entry + (entry_len + 1)*2; | 676 | crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2); |
677 | entry = (void *)entry + (entry_len + 1) * 2; | ||
666 | } | 678 | } |
667 | 679 | ||
680 | wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n"); | ||
681 | err = -ENODATA; | ||
682 | goto err; | ||
683 | |||
684 | good_eeprom: | ||
668 | if (!synth || !priv->iq_autocal || !priv->output_limit || | 685 | if (!synth || !priv->iq_autocal || !priv->output_limit || |
669 | !priv->curve_data) { | 686 | !priv->curve_data) { |
670 | wiphy_err(dev->wiphy, | 687 | wiphy_err(dev->wiphy, |