Deleted Added
full compact
ar5416_misc.c (231864) ar5416_misc.c (231927)
1/*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
1/*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 231864 2012-02-17 08:45:08Z adrian $
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 231927 2012-02-20 03:07:07Z adrian $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_desc.h" /* NB: for HAL_PHYERR* */
25

--- 689 unchanged lines hidden (view full) ---

715
716 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
717 "<0x806c>=0x%x\n", __func__, hang_sig);
718
719 return 0;
720#undef N
721}
722#undef NUM_STATUS_READS
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_desc.h" /* NB: for HAL_PHYERR* */
25

--- 689 unchanged lines hidden (view full) ---

715
716 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
717 "<0x806c>=0x%x\n", __func__, hang_sig);
718
719 return 0;
720#undef N
721}
722#undef NUM_STATUS_READS
723
724/*
725 * Get the radar parameter values and return them in the pe
726 * structure
727 */
728void
729ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
730{
731 uint32_t val, temp;
732
733 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
734
735 temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
736 temp |= 0xFFFFFF80;
737 pe->pe_firpwr = temp;
738 pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
739 pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
740 pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
741 pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
742
743 /* RADAR_1 values */
744 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
745 pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
746 pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
747 pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
748
749 pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
750 AR_PHY_RADAR_EXT_ENA);
751
752 pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
753 AR_PHY_RADAR_1_USE_FIR128);
754 pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
755 AR_PHY_RADAR_1_BLOCK_CHECK);
756 pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
757 AR_PHY_RADAR_1_MAX_RRSSI);
758 pe->pe_enabled = !!
759 (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA);
760 pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
761 AR_PHY_RADAR_1_RELPWR_ENA);
762 pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
763 AR_PHY_RADAR_1_RELSTEP_CHECK);
764}
765
766/*
767 * Enable radar detection and set the radar parameters per the
768 * values in pe
769 */
770void
771ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
772{
773 uint32_t val;
774
775 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
776
777 if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
778 val &= ~AR_PHY_RADAR_0_FIRPWR;
779 val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
780 }
781 if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
782 val &= ~AR_PHY_RADAR_0_RRSSI;
783 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
784 }
785 if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
786 val &= ~AR_PHY_RADAR_0_HEIGHT;
787 val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
788 }
789 if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
790 val &= ~AR_PHY_RADAR_0_PRSSI;
791 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
792 }
793 if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
794 val &= ~AR_PHY_RADAR_0_INBAND;
795 val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
796 }
797
798 /*Enable FFT data*/
799 val |= AR_PHY_RADAR_0_FFT_ENA;
800 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
801
802 /* Implicitly enable */
803 if (pe->pe_enabled == 1)
804 OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
805 else if (pe->pe_enabled == 0)
806 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
807
808 if (pe->pe_usefir128 == 1)
809 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
810 else if (pe->pe_usefir128 == 0)
811 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
812
813 if (pe->pe_enmaxrssi == 1)
814 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
815 else if (pe->pe_enmaxrssi == 0)
816 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
817
818 if (pe->pe_blockradar == 1)
819 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
820 else if (pe->pe_blockradar == 0)
821 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
822
823 if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
824 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
825 val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
826 val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
827 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
828 }
829 if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
830 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
831 val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
832 val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
833 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
834 }
835
836 if (pe->pe_en_relstep_check == 1)
837 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
838 AR_PHY_RADAR_1_RELSTEP_CHECK);
839 else if (pe->pe_en_relstep_check == 0)
840 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
841 AR_PHY_RADAR_1_RELSTEP_CHECK);
842
843 if (pe->pe_enrelpwr == 1)
844 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
845 AR_PHY_RADAR_1_RELPWR_ENA);
846 else if (pe->pe_enrelpwr == 0)
847 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
848 AR_PHY_RADAR_1_RELPWR_ENA);
849
850 if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
851 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
852 val &= ~AR_PHY_RADAR_1_MAXLEN;
853 val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
854 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
855 }
856
857 /*
858 * Enable HT/40 if the upper layer asks;
859 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
860 * is available.
861 */
862 if (pe->pe_extchannel == 1)
863 OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
864 else if (pe->pe_extchannel == 0)
865 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
866}
867
868/*
869 * Extract the radar event information from the given phy error.
870 *
871 * Returns AH_TRUE if the phy error was actually a phy error,
872 * AH_FALSE if the phy error wasn't a phy error.
873 */
874
875/* Flags for pulse_bw_info */
876#define PRI_CH_RADAR_FOUND 0x01
877#define EXT_CH_RADAR_FOUND 0x02
878#define EXT_CH_RADAR_EARLY_FOUND 0x04
879
880HAL_BOOL
881ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
882 uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
883{
884 HAL_BOOL doDfsExtCh;
885 HAL_BOOL doDfsEnhanced;
886 HAL_BOOL doDfsCombinedRssi;
887
888 uint8_t rssi = 0, ext_rssi = 0;
889 uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
890 uint32_t dur = 0;
891 int pri_found = 1, ext_found = 0;
892 int early_ext = 0;
893 int is_dc = 0;
894 uint16_t datalen; /* length from the RX status field */
895
896 /* Check whether the given phy error is a radar event */
897 if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
898 (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {
899 return AH_FALSE;
900 }
901
902 /* Grab copies of the capabilities; just to make the code clearer */
903 doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
904 doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
905 doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
906
907 datalen = rxs->rs_datalen;
908
909 /* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
910 if (doDfsCombinedRssi)
911 rssi = (uint8_t) rxs->rs_rssi;
912 else
913 rssi = (uint8_t) rxs->rs_rssi_ctl[0];
914
915 /* Set this; but only use it if doDfsExtCh is set */
916 ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
917
918 /* Cap it at 0 if the RSSI is a negative number */
919 if (rssi & 0x80)
920 rssi = 0;
921
922 if (ext_rssi & 0x80)
923 ext_rssi = 0;
924
925 /*
926 * Fetch the relevant data from the frame
927 */
928 if (doDfsExtCh) {
929 if (datalen < 3)
930 return AH_FALSE;
931
932 /* Last three bytes of the frame are of interest */
933 pulse_length_pri = *(buf + datalen - 3);
934 pulse_length_ext = *(buf + datalen - 2);
935 pulse_bw_info = *(buf + datalen - 1);
936 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
937 " pulse_length_ext=%d, pulse_bw_info=%x\n",
938 __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
939 pulse_bw_info);
940 } else {
941 /* The pulse width is byte 0 of the data */
942 if (datalen >= 1)
943 dur = ((uint8_t) buf[0]) & 0xff;
944 else
945 dur = 0;
946
947 if (dur == 0 && rssi == 0) {
948 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
949 return AH_FALSE;
950 }
951
952 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
953
954 /* Single-channel only */
955 pri_found = 1;
956 ext_found = 0;
957 }
958
959 /*
960 * If doing extended channel data, pulse_bw_info must
961 * have one of the flags set.
962 */
963 if (doDfsExtCh && pulse_bw_info == 0x0)
964 return AH_FALSE;
965
966 /*
967 * If the extended channel data is available, calculate
968 * which to pay attention to.
969 */
970 if (doDfsExtCh) {
971 /* If pulse is on DC, take the larger duration of the two */
972 if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
973 (pulse_bw_info & PRI_CH_RADAR_FOUND)) {
974 is_dc = 1;
975 if (pulse_length_ext > pulse_length_pri) {
976 dur = pulse_length_ext;
977 pri_found = 0;
978 ext_found = 1;
979 } else {
980 dur = pulse_length_pri;
981 pri_found = 1;
982 ext_found = 0;
983 }
984 } else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
985 dur = pulse_length_ext;
986 pri_found = 0;
987 ext_found = 1;
988 early_ext = 1;
989 } else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
990 dur = pulse_length_pri;
991 pri_found = 1;
992 ext_found = 0;
993 } else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
994 dur = pulse_length_ext;
995 pri_found = 0;
996 ext_found = 1;
997 }
998
999 }
1000
1001 /*
1002 * For enhanced DFS (Merlin and later), pulse_bw_info has
1003 * implications for selecting the correct RSSI value.
1004 */
1005 if (doDfsEnhanced) {
1006 switch (pulse_bw_info & 0x03) {
1007 case 0:
1008 /* No radar? */
1009 rssi = 0;
1010 break;
1011 case PRI_CH_RADAR_FOUND:
1012 /* Radar in primary channel */
1013 /* Cannot use ctrl channel RSSI if ext channel is stronger */
1014 if (ext_rssi >= (rssi + 3)) {
1015 rssi = 0;
1016 };
1017 break;
1018 case EXT_CH_RADAR_FOUND:
1019 /* Radar in extended channel */
1020 /* Cannot use ext channel RSSI if ctrl channel is stronger */
1021 if (rssi >= (ext_rssi + 12)) {
1022 rssi = 0;
1023 } else {
1024 rssi = ext_rssi;
1025 }
1026 break;
1027 case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
1028 /* When both are present, use stronger one */
1029 if (rssi < ext_rssi)
1030 rssi = ext_rssi;
1031 break;
1032 }
1033 }
1034
1035 /*
1036 * If not doing enhanced DFS, choose the ext channel if
1037 * it is stronger than the main channel
1038 */
1039 if (doDfsExtCh && !doDfsEnhanced) {
1040 if ((ext_rssi > rssi) && (ext_rssi < 128))
1041 rssi = ext_rssi;
1042 }
1043
1044 /*
1045 * XXX what happens if the above code decides the RSSI
1046 * XXX wasn't valid, an sets it to 0?
1047 */
1048
1049 /*
1050 * Fill out dfs_event structure.
1051 */
1052 event->re_full_ts = fulltsf;
1053 event->re_ts = rxs->rs_tstamp;
1054 event->re_rssi = rssi;
1055 event->re_dur = dur;
1056
1057 event->re_flags = 0;
1058 if (pri_found)
1059 event->re_flags |= HAL_DFS_EVENT_PRICH;
1060 if (ext_found)
1061 event->re_flags |= HAL_DFS_EVENT_EXTCH;
1062 if (early_ext)
1063 event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
1064 if (is_dc)
1065 event->re_flags |= HAL_DFS_EVENT_ISDC;
1066
1067 return AH_TRUE;
1068}
1069
1070/*
1071 * Return whether fast-clock is currently enabled for this
1072 * channel.
1073 */
1074HAL_BOOL
1075ar5416IsFastClockEnabled(struct ath_hal *ah)
1076{
1077 struct ath_hal_private *ahp = AH_PRIVATE(ah);
1078
1079 return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
1080}