diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/eeprom.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 158 |
1 files changed, 70 insertions, 88 deletions
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index efb672cb31e4..1fef84f87c78 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) | |||
660 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; | 660 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int | ||
664 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
665 | { | ||
666 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
667 | struct ath5k_chan_pcal_info *chinfo; | ||
668 | u8 pier, pdg; | ||
669 | |||
670 | switch (mode) { | ||
671 | case AR5K_EEPROM_MODE_11A: | ||
672 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
673 | return 0; | ||
674 | chinfo = ee->ee_pwr_cal_a; | ||
675 | break; | ||
676 | case AR5K_EEPROM_MODE_11B: | ||
677 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
678 | return 0; | ||
679 | chinfo = ee->ee_pwr_cal_b; | ||
680 | break; | ||
681 | case AR5K_EEPROM_MODE_11G: | ||
682 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
683 | return 0; | ||
684 | chinfo = ee->ee_pwr_cal_g; | ||
685 | break; | ||
686 | default: | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
690 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
691 | if (!chinfo[pier].pd_curves) | ||
692 | continue; | ||
693 | |||
694 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | ||
695 | struct ath5k_pdgain_info *pd = | ||
696 | &chinfo[pier].pd_curves[pdg]; | ||
697 | |||
698 | if (pd != NULL) { | ||
699 | kfree(pd->pd_step); | ||
700 | kfree(pd->pd_pwr); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | kfree(chinfo[pier].pd_curves); | ||
705 | } | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
663 | /* Convert RF5111 specific data to generic raw data | 710 | /* Convert RF5111 specific data to generic raw data |
664 | * used by interpolation code */ | 711 | * used by interpolation code */ |
665 | static int | 712 | static int |
@@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
684 | GFP_KERNEL); | 731 | GFP_KERNEL); |
685 | 732 | ||
686 | if (!chinfo[pier].pd_curves) | 733 | if (!chinfo[pier].pd_curves) |
687 | return -ENOMEM; | 734 | goto err_out; |
688 | 735 | ||
689 | /* Only one curve for RF5111 | 736 | /* Only one curve for RF5111 |
690 | * find out which one and place | 737 | * find out which one and place |
@@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
708 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 755 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
709 | sizeof(u8), GFP_KERNEL); | 756 | sizeof(u8), GFP_KERNEL); |
710 | if (!pd->pd_step) | 757 | if (!pd->pd_step) |
711 | return -ENOMEM; | 758 | goto err_out; |
712 | 759 | ||
713 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 760 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
714 | sizeof(s16), GFP_KERNEL); | 761 | sizeof(s16), GFP_KERNEL); |
715 | if (!pd->pd_pwr) | 762 | if (!pd->pd_pwr) |
716 | return -ENOMEM; | 763 | goto err_out; |
717 | 764 | ||
718 | /* Fill raw dataset | 765 | /* Fill raw dataset |
719 | * (convert power to 0.25dB units | 766 | * (convert power to 0.25dB units |
@@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
734 | } | 781 | } |
735 | 782 | ||
736 | return 0; | 783 | return 0; |
784 | |||
785 | err_out: | ||
786 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
787 | return -ENOMEM; | ||
737 | } | 788 | } |
738 | 789 | ||
739 | /* Parse EEPROM data */ | 790 | /* Parse EEPROM data */ |
@@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
867 | GFP_KERNEL); | 918 | GFP_KERNEL); |
868 | 919 | ||
869 | if (!chinfo[pier].pd_curves) | 920 | if (!chinfo[pier].pd_curves) |
870 | return -ENOMEM; | 921 | goto err_out; |
871 | 922 | ||
872 | /* Fill pd_curves */ | 923 | /* Fill pd_curves */ |
873 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 924 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
886 | sizeof(u8), GFP_KERNEL); | 937 | sizeof(u8), GFP_KERNEL); |
887 | 938 | ||
888 | if (!pd->pd_step) | 939 | if (!pd->pd_step) |
889 | return -ENOMEM; | 940 | goto err_out; |
890 | 941 | ||
891 | pd->pd_pwr = kcalloc(pd->pd_points, | 942 | pd->pd_pwr = kcalloc(pd->pd_points, |
892 | sizeof(s16), GFP_KERNEL); | 943 | sizeof(s16), GFP_KERNEL); |
893 | 944 | ||
894 | if (!pd->pd_pwr) | 945 | if (!pd->pd_pwr) |
895 | return -ENOMEM; | 946 | goto err_out; |
896 | |||
897 | 947 | ||
898 | /* Fill raw dataset | 948 | /* Fill raw dataset |
899 | * (all power levels are in 0.25dB units) */ | 949 | * (all power levels are in 0.25dB units) */ |
@@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
925 | sizeof(u8), GFP_KERNEL); | 975 | sizeof(u8), GFP_KERNEL); |
926 | 976 | ||
927 | if (!pd->pd_step) | 977 | if (!pd->pd_step) |
928 | return -ENOMEM; | 978 | goto err_out; |
929 | 979 | ||
930 | pd->pd_pwr = kcalloc(pd->pd_points, | 980 | pd->pd_pwr = kcalloc(pd->pd_points, |
931 | sizeof(s16), GFP_KERNEL); | 981 | sizeof(s16), GFP_KERNEL); |
932 | 982 | ||
933 | if (!pd->pd_pwr) | 983 | if (!pd->pd_pwr) |
934 | return -ENOMEM; | 984 | goto err_out; |
935 | 985 | ||
936 | /* Fill raw dataset | 986 | /* Fill raw dataset |
937 | * (all power levels are in 0.25dB units) */ | 987 | * (all power levels are in 0.25dB units) */ |
@@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
954 | } | 1004 | } |
955 | 1005 | ||
956 | return 0; | 1006 | return 0; |
1007 | |||
1008 | err_out: | ||
1009 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1010 | return -ENOMEM; | ||
957 | } | 1011 | } |
958 | 1012 | ||
959 | /* Parse EEPROM data */ | 1013 | /* Parse EEPROM data */ |
@@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1156 | GFP_KERNEL); | 1210 | GFP_KERNEL); |
1157 | 1211 | ||
1158 | if (!chinfo[pier].pd_curves) | 1212 | if (!chinfo[pier].pd_curves) |
1159 | return -ENOMEM; | 1213 | goto err_out; |
1160 | 1214 | ||
1161 | /* Fill pd_curves */ | 1215 | /* Fill pd_curves */ |
1162 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 1216 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1177 | sizeof(u8), GFP_KERNEL); | 1231 | sizeof(u8), GFP_KERNEL); |
1178 | 1232 | ||
1179 | if (!pd->pd_step) | 1233 | if (!pd->pd_step) |
1180 | return -ENOMEM; | 1234 | goto err_out; |
1181 | 1235 | ||
1182 | pd->pd_pwr = kcalloc(pd->pd_points, | 1236 | pd->pd_pwr = kcalloc(pd->pd_points, |
1183 | sizeof(s16), GFP_KERNEL); | 1237 | sizeof(s16), GFP_KERNEL); |
1184 | 1238 | ||
1185 | if (!pd->pd_pwr) | 1239 | if (!pd->pd_pwr) |
1186 | return -ENOMEM; | 1240 | goto err_out; |
1187 | 1241 | ||
1188 | /* Fill raw dataset | 1242 | /* Fill raw dataset |
1189 | * convert all pwr levels to | 1243 | * convert all pwr levels to |
@@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1213 | } | 1267 | } |
1214 | 1268 | ||
1215 | return 0; | 1269 | return 0; |
1270 | |||
1271 | err_out: | ||
1272 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1273 | return -ENOMEM; | ||
1216 | } | 1274 | } |
1217 | 1275 | ||
1218 | /* Parse EEPROM data */ | 1276 | /* Parse EEPROM data */ |
@@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | |||
1534 | return 0; | 1592 | return 0; |
1535 | } | 1593 | } |
1536 | 1594 | ||
1537 | static int | ||
1538 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
1539 | { | ||
1540 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1541 | struct ath5k_chan_pcal_info *chinfo; | ||
1542 | u8 pier, pdg; | ||
1543 | |||
1544 | switch (mode) { | ||
1545 | case AR5K_EEPROM_MODE_11A: | ||
1546 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
1547 | return 0; | ||
1548 | chinfo = ee->ee_pwr_cal_a; | ||
1549 | break; | ||
1550 | case AR5K_EEPROM_MODE_11B: | ||
1551 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
1552 | return 0; | ||
1553 | chinfo = ee->ee_pwr_cal_b; | ||
1554 | break; | ||
1555 | case AR5K_EEPROM_MODE_11G: | ||
1556 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
1557 | return 0; | ||
1558 | chinfo = ee->ee_pwr_cal_g; | ||
1559 | break; | ||
1560 | default: | ||
1561 | return -EINVAL; | ||
1562 | } | ||
1563 | |||
1564 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
1565 | if (!chinfo[pier].pd_curves) | ||
1566 | continue; | ||
1567 | |||
1568 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | ||
1569 | struct ath5k_pdgain_info *pd = | ||
1570 | &chinfo[pier].pd_curves[pdg]; | ||
1571 | |||
1572 | if (pd != NULL) { | ||
1573 | kfree(pd->pd_step); | ||
1574 | kfree(pd->pd_pwr); | ||
1575 | } | ||
1576 | } | ||
1577 | |||
1578 | kfree(chinfo[pier].pd_curves); | ||
1579 | } | ||
1580 | |||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | /* Read conformance test limits used for regulatory control */ | 1595 | /* Read conformance test limits used for regulatory control */ |
1585 | static int | 1596 | static int |
1586 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | 1597 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) |
@@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) | |||
1721 | return ret; | 1732 | return ret; |
1722 | } | 1733 | } |
1723 | 1734 | ||
1724 | /* | ||
1725 | * Read the MAC address from eeprom | ||
1726 | */ | ||
1727 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
1728 | { | ||
1729 | u8 mac_d[ETH_ALEN] = {}; | ||
1730 | u32 total, offset; | ||
1731 | u16 data; | ||
1732 | int octet; | ||
1733 | |||
1734 | AR5K_EEPROM_READ(0x20, data); | ||
1735 | |||
1736 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
1737 | AR5K_EEPROM_READ(offset, data); | ||
1738 | |||
1739 | total += data; | ||
1740 | mac_d[octet + 1] = data & 0xff; | ||
1741 | mac_d[octet] = data >> 8; | ||
1742 | octet += 2; | ||
1743 | } | ||
1744 | |||
1745 | if (!total || total == 3 * 0xffff) | ||
1746 | return -EINVAL; | ||
1747 | |||
1748 | memcpy(mac, mac_d, ETH_ALEN); | ||
1749 | |||
1750 | return 0; | ||
1751 | } | ||
1752 | |||
1753 | 1735 | ||
1754 | /***********************\ | 1736 | /***********************\ |
1755 | * Init/Detach functions * | 1737 | * Init/Detach functions * |