Example #1
0
static void
dumpchannels(struct ath_hal *ah, int nc,
	const struct ieee80211_channel *chans, int16_t *txpow)
{
	int i;

	for (i = 0; i < nc; i++) {
		const struct ieee80211_channel *c = &chans[i];
		int type;

		if (showchannels)
			printf("%s%3d", sep,
			    ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags));
		else
			printf("%s%u", sep, c->ic_freq);
		if (IEEE80211_IS_CHAN_HALF(c))
			type = 'H';
		else if (IEEE80211_IS_CHAN_QUARTER(c))
			type = 'Q';
		else if (IEEE80211_IS_CHAN_TURBO(c))
			type = 'T';
		else if (IEEE80211_IS_CHAN_HT(c))
			type = 'N';
		else if (IEEE80211_IS_CHAN_A(c))
			type = 'A';
		else if (IEEE80211_IS_CHAN_108G(c))
			type = 'T';
		else if (IEEE80211_IS_CHAN_G(c))
			type = 'G';
		else
			type = 'B';
		if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c))
			type = tolower(type);
		if (isdfs && is4ms)
			printf("%c%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else if (isdfs)
			printf("%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else if (is4ms)
			printf("%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else
			printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5);
		if ((n++ % (showchannels ? 7 : 6)) == 0)
			sep = "\n";
		else
			sep = " ";
	}
}
Example #2
0
/*
 * Enable radar check
 */
void
ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan)
{
	/* Check if the current channel is radar-enabled */
	if (! IEEE80211_IS_CHAN_DFS(chan))
		return;
}
Example #3
0
/* Implement wmi_unified_vdev_start_cmd() here */
static int _ieee80211_resmgr_vap_start(ieee80211_resmgr_t resmgr,
                               ieee80211_vap_t vap, 
                               struct ieee80211_channel *chan,
                               u_int16_t reqid,
                               u_int16_t max_start_time)
{
    struct ieee80211com *ic = resmgr->ic;
    struct ol_ath_softc_net80211 *scn = OL_ATH_SOFTC_NET80211(ic);
    struct ol_ath_vap_net80211 *avn = OL_ATH_VAP_NET80211(vap);
    u_int32_t freq;
    bool disable_hw_ack= false;

printk("OL vap_start +\n");

    freq = ieee80211_chan2freq(resmgr->ic, chan);
    if (!freq) {
        printk("ERROR : INVALID Freq \n");
        return 0;
    }
#if ATH_SUPPORT_DFS
    if ( vap->iv_opmode == IEEE80211_M_HOSTAP &&
        IEEE80211_IS_CHAN_DFS(chan)) {
           disable_hw_ack = true;
    }
#endif

    /* BUG : Seen on AKronite, VDEV Start event response comes before setting
     * av_ol_resmgr_wait to TRUE, this make VAP not coming up issue.
     * Hence moving below assignment before sending VDEV_START_CMD_ID to target 
     */

    /* Interface is up, UMAC is waiting for
     * target response     
     */ 
    avn->av_ol_resmgr_wait = TRUE;

    spin_lock(&vap->init_lock);
    if (wmi_unified_vdev_start_send(scn->wmi_handle, avn->av_if_id, chan, freq, disable_hw_ack)) {
        printk("Unable to bring up the interface for ath_dev.\n");
        spin_unlock(&vap->init_lock);
        return -1;
    }

   /* The channel configured in target is not same always with the vap desired channel
      due to 20/40 coexistence scenarios, so, channel is saved to configure on VDEV START RESP */
   avn->av_ol_resmgr_chan = chan;
   vap->init_in_progress = true;
   spin_unlock(&vap->init_lock);

printk("OL vap_start -\n");
    return EBUSY;
}
Example #4
0
/*
 * Enable radar check.  Return 1 if the driver should
 * enable radar PHY errors, or 0 if not.
 */
int
ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan)
{
#if 0
    HAL_PHYERR_PARAM pe;

    /* Check if the hardware supports radar reporting */
    /* XXX TODO: migrate HAL_CAP_RADAR/HAL_CAP_AR to somewhere public! */
    if (ath_hal_getcapability(sc->sc_ah,
                              HAL_CAP_PHYDIAG, 0, NULL) != HAL_OK)
        return (0);

    /* Check if the current channel is radar-enabled */
    if (! IEEE80211_IS_CHAN_DFS(chan))
        return (0);

    /* Fetch the default parameters */
    memset(&pe, '\0', sizeof(pe));
    if (! ath_hal_getdfsdefaultthresh(sc->sc_ah, &pe))
        return (0);

    /* Enable radar PHY error reporting */
    sc->sc_dodfs = 1;

    /* Tell the hardware to enable radar reporting */
    pe.pe_enabled = 1;

    /* Flip on extension channel events only if doing HT40 */
    if (IEEE80211_IS_CHAN_HT40(chan))
        pe.pe_extchannel = 1;
    else
        pe.pe_extchannel = 0;

    ath_hal_enabledfs(sc->sc_ah, &pe);

    /*
     * Disable strong signal fast diversity - needed for
     * AR5212 and similar PHYs for reliable short pulse
     * duration.
     */
    (void) ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, 2, 0, NULL);

    return (1);
#else
    return (0);
#endif
}
void
dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen,
		   uint8_t r_rssi, uint8_t r_ext_rssi, uint32_t r_rs_tstamp,
		   uint64_t r_fulltsf, bool enable_log)
{
	struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs;
	struct dfs_ieee80211_channel *chan = ic->ic_curchan;
	struct dfs_event *event;
	struct dfs_phy_err e;
	int empty;

	if (dfs == NULL) {
		CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
			  "%s: sc_dfs is NULL\n", __func__);
		return;
	}

	dfs->dfs_phyerr_count++;
	dump_phyerr_contents(buf, datalen);
	/*
	 * XXX The combined_rssi_ok support has been removed.
	 * This was only clear for Owl.
	 *
	 * XXX TODO: re-add this; it requires passing in the ctl/ext
	 * RSSI set from the RX status descriptor.
	 *
	 * XXX TODO TODO: this may be done for us from the legacy
	 * phy error path in ath_dev; please review that code.
	 */

	/*
	 * At this time we have a radar pulse that we need to examine and
	 * queue. But if dfs_process_radarevent already detected radar and set
	 * CHANNEL_INTERFERENCE flag then do not queue any more radar data.
	 * When we are in a new channel this flag will be clear and we will
	 * start queueing data for new channel. (EV74162)
	 */
	if (dfs->dfs_debug_mask & ATH_DEBUG_DFS_PHYERR_PKT)
		dump_phyerr_contents(buf, datalen);

	if (chan == NULL) {
		CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
			  "%s: chan is NULL\n", __func__);
		return;
	}

	cdf_spin_lock_bh(&ic->chan_lock);
	if (IEEE80211_IS_CHAN_RADAR(chan)) {
		cdf_spin_unlock_bh(&ic->chan_lock);
		DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
			    "%s: Radar already found in the channel, "
			    " do not queue radar data\n", __func__);
		return;
	}

	cdf_spin_unlock_bh(&ic->chan_lock);
	dfs->ath_dfs_stats.total_phy_errors++;
	DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
		    "%s[%d] phyerr %d len %d\n",
		    __func__, __LINE__,
		    dfs->ath_dfs_stats.total_phy_errors, datalen);

	/*
	 * hardware stores this as 8 bit signed value.
	 * we will cap it at 0 if it is a negative number
	 */
	if (r_rssi & 0x80)
		r_rssi = 0;

	if (r_ext_rssi & 0x80)
		r_ext_rssi = 0;

	OS_MEMSET(&e, 0, sizeof(e));

	/*
	 * This is a bit evil - instead of just passing in
	 * the chip version, the existing code uses a set
	 * of HAL capability bits to determine what is
	 * possible.
	 *
	 * The way I'm decoding it is thus:
	 *
	 * + DFS enhancement? Merlin or later
	 * + DFS extension channel? Sowl or later. (Howl?)
	 * + otherwise, Owl (and legacy.)
	 */
	if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
		if (dfs_process_phyerr_bb_tlv(dfs, buf, datalen, r_rssi,
					      r_ext_rssi, r_rs_tstamp,
					      r_fulltsf, &e,
					      enable_log) == 0) {
			dfs->dfs_phyerr_reject_count++;
			return;
		} else {
			if (dfs->dfs_phyerr_freq_min > e.freq)
				dfs->dfs_phyerr_freq_min = e.freq;

			if (dfs->dfs_phyerr_freq_max < e.freq)
				dfs->dfs_phyerr_freq_max = e.freq;
		}
	} else if (dfs->dfs_caps.ath_dfs_use_enhancement) {
		if (dfs_process_phyerr_merlin(dfs, buf, datalen, r_rssi,
					      r_ext_rssi, r_rs_tstamp,
					      r_fulltsf, &e) == 0) {
			return;
		}
	} else if (dfs->dfs_caps.ath_dfs_ext_chan_ok) {
		if (dfs_process_phyerr_sowl(dfs, buf, datalen, r_rssi,
					    r_ext_rssi, r_rs_tstamp, r_fulltsf,
					    &e) == 0) {
			return;
		}
	} else {
		if (dfs_process_phyerr_owl(dfs, buf, datalen, r_rssi,
					   r_ext_rssi, r_rs_tstamp, r_fulltsf,
					   &e) == 0) {
			return;
		}
	}

	CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
		  "\n %s: Frequency at which the phyerror was injected = %d",
		  __func__, e.freq);
	/*
	 * If the hardware supports radar reporting on the extension channel
	 * it will supply FFT data for longer radar pulses.
	 *
	 * TLV chips don't go through this software check - the hardware
	 * check should be enough.  If we want to do software checking
	 * later on then someone will have to craft an FFT parser
	 * suitable for the TLV FFT data format.
	 */
	if ((!dfs->dfs_caps.ath_chip_is_bb_tlv) &&
	    dfs->dfs_caps.ath_dfs_ext_chan_ok) {
		/*
		 * HW has a known issue with chirping pulses injected at or
		 * around DC in 40MHz mode. Such pulses are reported with
		 * much lower durations and SW then discards them because
		 * they do not fit the minimum bin5 pulse duration.
		 *
		 * To work around this issue, if a pulse is within a 10us
		 * range of the bin5 min duration, check if the pulse is
		 * chirping. If the pulse is chirping, bump up the duration
		 * to the minimum bin5 duration.
		 *
		 * This makes sure that a valid chirping pulse will not be
		 * discarded because of incorrect low duration.
		 *
		 * TBD - Is it possible to calculate the 'real' duration of
		 * the pulse using the slope of the FFT data?
		 *
		 * TBD - Use FFT data to differentiate between radar pulses
		 * and false PHY errors.
		 * This will let us reduce the number of false alarms seen.
		 *
		 * BIN 5 chirping pulses are only for FCC or Japan MMK4 domain
		 */
		if (((dfs->dfsdomain == DFS_FCC_DOMAIN) ||
		     (dfs->dfsdomain == DFS_MKK4_DOMAIN)) &&
		    (e.dur >= MAYBE_BIN5_DUR) && (e.dur < MAX_BIN5_DUR)) {
			int add_dur;
			int slope = 0, dc_found = 0;

			/*
			 * Set the event chirping flags; as we're doing
			 * an actual chirp check.
			 */
			e.do_check_chirp = 1;
			e.is_hw_chirp = 0;
			e.is_sw_chirp = 0;

			/*
			 * dfs_check_chirping() expects is_pri and is_ext
			 * to be '1' for true and '0' for false for now,
			 * as the function itself uses these values in
			 * constructing things rather than testing them
			 * for 'true' or 'false'.
			 */
			add_dur = dfs_check_chirping(dfs, buf, datalen,
						     (e.is_pri ? 1 : 0),
						     (e.is_ext ? 1 : 0),
						     &slope, &dc_found);
			if (add_dur) {
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,
					    "old dur %d slope =%d\n", e.dur,
					    slope);
				e.is_sw_chirp = 1;
				/* bump up to a random bin5 pulse duration */
				if (e.dur < MIN_BIN5_DUR) {
					e.dur = dfs_get_random_bin5_dur(dfs,
							e.fulltsf);
				}
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,
					    "new dur %d\n", e.dur);
			} else {
				/* set the duration so that it is rejected */
				e.is_sw_chirp = 0;
				e.dur = MAX_BIN5_DUR + 100;
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,
						"is_chirping = %d dur=%d\n",
						add_dur, e.dur);
			}
		} else {
			/*
			 * We have a pulse that is either bigger than
			 * MAX_BIN5_DUR or * less than MAYBE_BIN5_DUR
			 */
			if ((dfs->dfsdomain == DFS_FCC_DOMAIN) ||
			    (dfs->dfsdomain == DFS_MKK4_DOMAIN)) {
				/*
				 * XXX Would this result in very large pulses
				 *     wrapping around to become short pulses?
				 */
				if (e.dur >= MAX_BIN5_DUR) {
					/*
					 * set the duration so that it is
					 * rejected
					 */
					e.dur = MAX_BIN5_DUR + 50;
				}
			}
		}
	}

	/*
	 * Add the parsed, checked and filtered entry to the radar pulse
	 * event list.  This is then checked by dfs_radar_processevent().
	 *
	 * XXX TODO: some filtering is still done below this point - fix
	 * XXX this!
	 */
	ATH_DFSEVENTQ_LOCK(dfs);
	empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
	ATH_DFSEVENTQ_UNLOCK(dfs);
	if (empty) {
		return;
	}

	/*
	 * If the channel is a turbo G channel, then the event is
	 * for the adaptive radio (AR) pattern matching rather than
	 * radar detection.
	 */
	cdf_spin_lock_bh(&ic->chan_lock);
	if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) {
		cdf_spin_unlock_bh(&ic->chan_lock);
		if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) {
			DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
				    "%s: DFS_AR_EN not enabled\n", __func__);
			return;
		}
		ATH_DFSEVENTQ_LOCK(dfs);
		event = STAILQ_FIRST(&(dfs->dfs_eventq));
		if (event == NULL) {
			ATH_DFSEVENTQ_UNLOCK(dfs);
			DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
				    "%s: no more events space left\n",
				    __func__);
			return;
		}
		STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
		ATH_DFSEVENTQ_UNLOCK(dfs);
		event->re_rssi = e.rssi;
		event->re_dur = e.dur;
		event->re_full_ts = e.fulltsf;
		event->re_ts = (e.rs_tstamp) & DFS_TSMASK;
		event->re_chanindex = dfs->dfs_curchan_radindex;
		event->re_flags = 0;
		event->sidx = e.sidx;

		/*
		 * Handle chirp flags.
		 */
		if (e.do_check_chirp) {
			event->re_flags |= DFS_EVENT_CHECKCHIRP;
			if (e.is_hw_chirp)
				event->re_flags |= DFS_EVENT_HW_CHIRP;
			if (e.is_sw_chirp)
				event->re_flags |= DFS_EVENT_SW_CHIRP;
		}

		ATH_ARQ_LOCK(dfs);
		STAILQ_INSERT_TAIL(&(dfs->dfs_arq), event, re_list);
		ATH_ARQ_UNLOCK(dfs);
	} else {
		if (IEEE80211_IS_CHAN_DFS(chan)) {
			cdf_spin_unlock_bh(&ic->chan_lock);
			if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) {
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
					    "%s: DFS_RADAR_EN not enabled\n",
					    __func__);
				return;
			}
			/*
			 * rssi is not accurate for short pulses, so do
			 * not filter based on that for short duration pulses
			 *
			 * XXX do this filtering above?
			 */
			if (dfs->dfs_caps.ath_dfs_ext_chan_ok) {
				if ((e.rssi < dfs->dfs_rinfo.rn_minrssithresh &&
				     (e.dur > 4)) ||
				    e.dur > (dfs->dfs_rinfo.rn_maxpulsedur)) {
					dfs->ath_dfs_stats.rssi_discards++;
					DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
						    "Extension channel pulse is "
						    "discarded: dur=%d, "
						    "maxpulsedur=%d, rssi=%d, "
						    "minrssi=%d\n",
						    e.dur,
						    dfs->dfs_rinfo.
						    rn_maxpulsedur, e.rssi,
						    dfs->dfs_rinfo.
						    rn_minrssithresh);
					return;
				}
			} else {
				if (e.rssi < dfs->dfs_rinfo.rn_minrssithresh ||
				    e.dur > dfs->dfs_rinfo.rn_maxpulsedur) {
					/* XXX TODO add a debug statement? */
					dfs->ath_dfs_stats.rssi_discards++;
					return;
				}
			}

			/*
			 * Add the event to the list, if there's space.
			 */
			ATH_DFSEVENTQ_LOCK(dfs);
			event = STAILQ_FIRST(&(dfs->dfs_eventq));
			if (event == NULL) {
				ATH_DFSEVENTQ_UNLOCK(dfs);
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
					    "%s: no more events space left\n",
					    __func__);
				return;
			}
			STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
			ATH_DFSEVENTQ_UNLOCK(dfs);

			dfs->dfs_phyerr_queued_count++;
			dfs->dfs_phyerr_w53_counter++;

			event->re_dur = e.dur;
			event->re_full_ts = e.fulltsf;
			event->re_ts = (e.rs_tstamp) & DFS_TSMASK;
			event->re_rssi = e.rssi;
			event->sidx = e.sidx;

			/*
			 * Handle chirp flags.
			 */
			if (e.do_check_chirp) {
				event->re_flags |= DFS_EVENT_CHECKCHIRP;
				if (e.is_hw_chirp)
					event->re_flags |= DFS_EVENT_HW_CHIRP;
				if (e.is_sw_chirp)
					event->re_flags |= DFS_EVENT_SW_CHIRP;
			}

			/*
			 * Correctly set which channel is being reported on
			 */
			if (e.is_pri) {
				event->re_chanindex = dfs->dfs_curchan_radindex;
			} else {
				if (dfs->dfs_extchan_radindex == -1) {
					DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,
						    "%s - phyerr on ext channel\n",
						    __func__);
				}
				event->re_chanindex = dfs->dfs_extchan_radindex;
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,
					    "%s New extension channel event is added "
					    "to queue\n", __func__);
			}
			ATH_DFSQ_LOCK(dfs);
			STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
			ATH_DFSQ_UNLOCK(dfs);
		} else {
			cdf_spin_unlock_bh(&ic->chan_lock);
		}
	}

	/*
	 * Schedule the radar/AR task as appropriate.
	 *
	 * XXX isn't a lock needed for ath_radar_tasksched?
	 */

/*
 *  Commenting out the dfs_process_ar_event() since the function is never
 *  called at run time as dfs_arq will be empty and the function
 *  dfs_process_ar_event is obsolete and function definition is removed
 *  as part of dfs_ar.c file
 *
 *  if (!STAILQ_EMPTY(&dfs->dfs_arq))
 *     // XXX shouldn't this be a task/timer too?
 *     dfs_process_ar_event(dfs, ic->ic_curchan);
 */

	if (!STAILQ_EMPTY(&dfs->dfs_radarq) && !dfs->ath_radar_tasksched) {
		dfs->ath_radar_tasksched = 1;
		OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
	}
#undef   EXT_CH_RADAR_FOUND
#undef   PRI_CH_RADAR_FOUND
#undef   EXT_CH_RADAR_EARLY_FOUND
}
Example #6
0
/*
 * Places the device in and out of reset and then places sane
 * values in the registers based on EEPROM config, initialization
 * vectors (as determined by the mode), and station configuration
 *
 * bChannelChange is used to preserve DMA/PCU registers across
 * a HW Reset during channel change.
 */
HAL_BOOL
ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
	struct ieee80211_channel *chan,
	HAL_BOOL bChannelChange,
	HAL_RESET_TYPE resetType,
	HAL_STATUS *status)
{
#define	N(a)	(sizeof (a) / sizeof (a[0]))
#define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)
	struct ath_hal_5212 *ahp = AH5212(ah);
	HAL_CHANNEL_INTERNAL *ichan;
	const HAL_EEPROM *ee;
	uint32_t saveFrameSeqCount, saveDefAntenna;
	uint32_t macStaId1, synthDelay, txFrm2TxDStart;
	uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
	int16_t cckOfdmPwrDelta = 0;
	u_int modesIndex, freqIndex;
	HAL_STATUS ecode;
	int i, regWrites = 0;
	uint32_t testReg;
	uint32_t saveLedState = 0;

	HALASSERT(ah->ah_magic == AR5212_MAGIC);
	ee = AH_PRIVATE(ah)->ah_eeprom;

	OS_MARK(ah, AH_MARK_RESET, bChannelChange);
	/*
	 * Map public channel to private.
	 */
	ichan = ath_hal_checkchannel(ah, chan);
	if (ichan == AH_NULL) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: invalid channel %u/0x%x; no mapping\n",
		    __func__, chan->ic_freq, chan->ic_flags);
		FAIL(HAL_EINVAL);
	}
	switch (opmode) {
	case HAL_M_STA:
	case HAL_M_IBSS:
	case HAL_M_HOSTAP:
	case HAL_M_MONITOR:
		break;
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
		    __func__, opmode);
		FAIL(HAL_EINVAL);
		break;
	}
	HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);

	/* Preserve certain DMA hardware registers on a channel change */
	if (bChannelChange) {
		/*
		 * On Venice, the TSF is almost preserved across a reset;
		 * it requires the doubling writes to the RESET_TSF
		 * bit in the AR_BEACON register; it also has the quirk
		 * of the TSF going back in time on the station (station
		 * latches onto the last beacon's tsf during a reset 50%
		 * of the times); the latter is not a problem for adhoc
		 * stations since as long as the TSF is behind, it will
		 * get resynchronized on receiving the next beacon; the
		 * TSF going backwards in time could be a problem for the
		 * sleep operation (supported on infrastructure stations
		 * only) - the best and most general fix for this situation
		 * is to resynchronize the various sleep/beacon timers on
		 * the receipt of the next beacon i.e. when the TSF itself
		 * gets resynchronized to the AP's TSF - power save is
		 * needed to be temporarily disabled until that time
		 *
		 * Need to save the sequence number to restore it after
		 * the reset!
		 */
		saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
	} else
		saveFrameSeqCount = 0;		/* NB: silence compiler */

	/* If the channel change is across the same mode - perform a fast channel change */
	if ((IS_2413(ah) || IS_5413(ah))) {
		/*
		 * Channel change can only be used when:
		 *  -channel change requested - so it's not the initial reset.
		 *  -it's not a change to the current channel - often called when switching modes
		 *   on a channel
		 *  -the modes of the previous and requested channel are the same - some ugly code for XR
		 */
		if (bChannelChange &&
		    AH_PRIVATE(ah)->ah_curchan != AH_NULL &&
		    (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
		    ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
		     (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
			if (ar5212ChannelChange(ah, chan))
				/* If ChannelChange completed - skip the rest of reset */
				return AH_TRUE;
		}
	}

	/*
	 * Preserve the antenna on a channel change
	 */
	saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
	if (saveDefAntenna == 0)		/* XXX magic constants */
		saveDefAntenna = 1;

	/* Save hardware flag before chip reset clears the register */
	macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & 
		(AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);

	/* Save led state from pci config register */
	if (!IS_5315(ah))
		saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
			 AR_PCICFG_LEDSLOW);

	ar5312RestoreClock(ah, opmode);		/* move to refclk operation */

	/*
	 * Adjust gain parameters before reset if
	 * there's an outstanding gain updated.
	 */
	(void) ar5212GetRfgain(ah);

	if (!ar5312ChipReset(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Setup the indices for the next set of register array writes */
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		freqIndex  = 2;
		modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 :
			     IEEE80211_IS_CHAN_G(chan) ? 4 : 3;
	} else {
		freqIndex  = 1;
		modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1;
	}

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);

	regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
	regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
		regWrites);
	ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))
		ar5212SetIFSTiming(ah, chan);

	/* Overwrite INI values for revised chipsets */
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
		/* ADC_CTL */
		OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
			     SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
			     SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
			     AR_PHY_ADC_CTL_OFF_PWDDAC |
			     AR_PHY_ADC_CTL_OFF_PWDADC);
		
		/* TX_PWR_ADJ */
		if (chan->channel == 2484) {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
		} else {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
		}
		
		if (IEEE80211_IS_CHAN_G(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
				     SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
				     SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
		} else {
			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
		}
		
		/* Add barker RSSI thresh enable as disabled */
		OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
			       AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
		OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
				 AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
		
		/* Set the mute mask to the correct default */
		OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
	}
	
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
		/* Clear reg to alllow RX_CLEAR line debug */
		OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
	}
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
#ifdef notyet
		/* Enable burst prefetch for the data queues */
		OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
		/* Enable double-buffering */
		OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
#endif
	}

	if (IS_5312_2_X(ah)) {
		/* ADC_CTRL */
		OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,
			     SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |
			     SM(4, AR_PHY_SIGMA_DELTA_FILT2) |
			     SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |
			     SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));

		if (IEEE80211_IS_CHAN_2GHZ(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);

		/* CCK Short parameter adjustment in 11B mode */
		if (IEEE80211_IS_CHAN_B(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);

		/* Set ADC/DAC select values */
		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);

		/* Increase 11A AGC Settling */
		if (IEEE80211_IS_CHAN_A(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);
	} else {
		/* Set ADC/DAC select values */
		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
	}

	/* Setup the transmit power values. */
	if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error init'ing transmit power\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Write the analog registers */
	if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
		    __func__);
		FAIL(HAL_EIO);
	}

	/* Write delta slope for OFDM enabled modes (A, G, Turbo) */
	if (IEEE80211_IS_CHAN_OFDM(chan)) {
		if (IS_5413(ah) ||
		   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
			ar5212SetSpurMitigation(ah, chan);
		ar5212SetDeltaSlope(ah, chan);
	}

	/* Setup board specific options for EEPROM version 3 */
	if (!ar5212SetBoardValues(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error setting board options\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Restore certain DMA hardware registers on a channel change */
	if (bChannelChange)
		OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
	OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
		| macStaId1
		| AR_STA_ID1_RTS_USE_DEF
		| ahp->ah_staId1Defaults
	);
	ar5212SetOperatingMode(ah, opmode);

	/* Set Venice BSSID mask according to current state */
	OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
	OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));

	/* Restore previous led state */
	if (!IS_5315(ah))
		OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);

	/* Restore previous antenna */
	OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);

	/* then our BSSID */
	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));

	/* Restore bmiss rssi & count thresholds */
	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);

	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */

	if (!ar5212SetChannel(ah, chan))
		FAIL(HAL_EIO);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);

	ar5212SetRateDurationTable(ah, chan);

	/* Set Tx frame start to tx data start delay */
	if (IS_RAD5112_ANY(ah) &&
	    (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
		txFrm2TxDStart = 
			IEEE80211_IS_CHAN_HALF(chan) ?
					TX_FRAME_D_START_HALF_RATE:
					TX_FRAME_D_START_QUARTER_RATE;
		OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 
			AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
	}

	/*
	 * Setup fast diversity.
	 * Fast diversity can be enabled or disabled via regadd.txt.
	 * Default is enabled.
	 * For reference,
	 *    Disable: reg        val
	 *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
	 *             0x00009970 0x192bb514
	 *             0x0000a208 0xd03e4648
	 *
	 *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
	 *             0x00009970 0x192fb514
	 *             0x0000a208 0xd03e6788
	 */

	/* XXX Setup pre PHY ENABLE EAR additions */

	/* flush SCAL reg */
	if (IS_5312_2_X(ah)) {
		(void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);
	}

	/*
	 * Wait for the frequency synth to settle (synth goes on
	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
	 * Value is in 100ns increments.
	 */
	synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
	if (IEEE80211_IS_CHAN_B(chan)) {
		synthDelay = (4 * synthDelay) / 22;
	} else {
		synthDelay /= 10;
	}

	/* Activate the PHY (includes baseband activate and synthesizer on) */
	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);

	/* 
	 * There is an issue if the AP starts the calibration before
	 * the base band timeout completes.  This could result in the
	 * rx_clear false triggering.  As a workaround we add delay an
	 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
	 * does not happen.
	 */
	if (IEEE80211_IS_CHAN_HALF(chan)) {
		OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
	} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
		OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
	} else {
		OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
	}

	/*
	 * The udelay method is not reliable with notebooks.
	 * Need to check to see if the baseband is ready
	 */
	testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
	/* Selects the Tx hold */
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
	i = 0;
	while ((i++ < 20) &&
	       (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */		OS_DELAY(200);
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);

	/* Calibrate the AGC and start a NF calculation */
	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
		  OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
		| AR_PHY_AGC_CONTROL_CAL
		| AR_PHY_AGC_CONTROL_NF);

	if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
		/* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 
			AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
			INIT_IQCAL_LOG_COUNT_MAX);
		OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
			AR_PHY_TIMING_CTRL4_DO_IQCAL);
		ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
	} else
		ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;

	/* Setup compression registers */
	ar5212SetCompRegs(ah);

	/* Set 1:1 QCU to DCU mapping for all queues */
	for (i = 0; i < AR_NUM_DCU; i++)
		OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);

	ahp->ah_intrTxqs = 0;
	for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
		ar5212ResetTxQueue(ah, i);

	/*
	 * Setup interrupt handling.  Note that ar5212ResetTxQueue
	 * manipulates the secondary IMR's as queues are enabled
	 * and disabled.  This is done with RMW ops to insure the
	 * settings we make here are preserved.
	 */
	ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
			| AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
			| AR_IMR_HIUERR
			;
	if (opmode == HAL_M_HOSTAP)
		ahp->ah_maskReg |= AR_IMR_MIB;
	OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
	/* Enable bus errors that are OR'd to set the HIUERR bit */
	OS_REG_WRITE(ah, AR_IMR_S2,
		OS_REG_READ(ah, AR_IMR_S2)
		| AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);

	if (AH_PRIVATE(ah)->ah_rfkillEnabled)
		ar5212EnableRfKill(ah);

	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: offset calibration failed to complete in 1ms;"
		    " noisy environment?\n", __func__);
	}

	/*
	 * Set clocks back to 32kHz if they had been using refClk, then
	 * use an external 32kHz crystal when sleeping, if one exists.
	 */
	ar5312SetupClock(ah, opmode);

	/*
	 * Writing to AR_BEACON will start timers. Hence it should
	 * be the last register to be written. Do not reset tsf, do
	 * not enable beacons at this point, but preserve other values
	 * like beaconInterval.
	 */
	OS_REG_WRITE(ah, AR_BEACON,
		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));

	/* XXX Setup post reset EAR additions */

	/*  QoS support */
	if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
	    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
	     AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
		OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);	/* XXX magic */
		OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);	/* XXX magic */
	}

	/* Turn on NOACK Support for QoS packets */
	OS_REG_WRITE(ah, AR_NOACK,
		     SM(2, AR_NOACK_2BIT_VALUE) |
		     SM(5, AR_NOACK_BIT_OFFSET) |
		     SM(0, AR_NOACK_BYTE_OFFSET));

	/* Restore user-specified settings */
	if (ahp->ah_miscMode != 0)
		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
	if (ahp->ah_slottime != (u_int) -1)
		ar5212SetSlotTime(ah, ahp->ah_slottime);
	if (ahp->ah_acktimeout != (u_int) -1)
		ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
	if (ahp->ah_ctstimeout != (u_int) -1)
		ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
	if (ahp->ah_sifstime != (u_int) -1)
		ar5212SetSifsTime(ah, ahp->ah_sifstime);
	if (AH_PRIVATE(ah)->ah_diagreg != 0)
		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);

	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */

	if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 
		chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;

	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);

	OS_MARK(ah, AH_MARK_RESET_DONE, 0);

	return AH_TRUE;
bad:
	OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
	if (status != AH_NULL)
		*status = ecode;
	return AH_FALSE;
#undef FAIL
#undef N
}
Example #7
0
/*
 * Process a radar event.
 *
 * If a radar event is found, return 1.  Otherwise, return 0.
 *
 * There is currently no way to specify that a radar event has occured on
 * a specific channel, so the current methodology is to mark both the pri
 * and ext channels as being unavailable.  This should be fixed for 802.11ac
 * or we'll quickly run out of valid channels to use.
 */
int
dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan)
{
    struct dfs_event re,*event;
    struct dfs_state *rs=NULL;
    struct dfs_filtertype *ft;
    struct dfs_filter *rf;
    int found, retval = 0, p, empty;
    int events_processed = 0;
    u_int32_t tabledepth, index;
    u_int64_t deltafull_ts = 0, this_ts, deltaT;
    struct ieee80211_channel *thischan;
    struct dfs_pulseline *pl;
    static u_int32_t  test_ts  = 0;
    static u_int32_t  diff_ts  = 0;
    int ext_chan_event_flag = 0;
    int i;

    if (dfs == NULL) {
        DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_sfs is NULL\n",
                    __func__);
        return 0;
    }
    pl = dfs->pulses;
    if ( !(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) {
        DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan\n",
                    __func__);
        dfs_reset_radarq(dfs);
        dfs_reset_alldelaylines(dfs);
        return 0;
    }
#ifndef ATH_DFS_RADAR_DETECTION_ONLY
    /* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */
    if (dfs->dfs_bangradar) {
        /* bangradar will always simulate radar found on the primary channel */
        rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex];
        dfs->dfs_bangradar = 0; /* reset */
        DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: bangradar\n", __func__);
        retval = 1;
        goto dfsfound;
    }
#endif

    /*
      The HW may miss some pulses especially with high channel loading.
      This is true for Japan W53 where channel loaoding is 50%. Also
      for ETSI where channel loading is 30% this can be an issue too.
      To take care of missing pulses, we introduce pri_margin multiplie.
      This is normally 2 but can be higher for W53.
    */

    if ((dfs->dfsdomain  == DFS_MKK4_DOMAIN) &&
            (dfs->dfs_caps.ath_chip_is_bb_tlv) &&
            (chan->ic_freq < FREQ_5500_MHZ)) {

        dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER;
        /* do not process W53 pulses unless we have a minimum number of them */
        if (dfs->dfs_phyerr_w53_counter >= 5) {
            /*
              for chips that support frequency information, we can
              relax PRI restriction if the frequency
              spread is narrow.
            */
            if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) < DFS_MAX_FREQ_SPREAD) {
                dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER;
            }
            DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d\n",
                        __func__,
                        dfs->dfs_phyerr_w53_counter,
                        dfs->dfs_phyerr_freq_max,
                        dfs->dfs_phyerr_freq_min,
                        dfs->dfs_pri_multiplier);
            dfs->dfs_phyerr_freq_min     = 0x7fffffff;
            dfs->dfs_phyerr_freq_max     = 0;
        } else {
            return 0;
        }
    }
    DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: pri_multiplier=%d\n", __func__, dfs->dfs_pri_multiplier);

    ATH_DFSQ_LOCK(dfs);
    empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
    ATH_DFSQ_UNLOCK(dfs);

    while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) {
        ATH_DFSQ_LOCK(dfs);
        event = STAILQ_FIRST(&(dfs->dfs_radarq));
        if (event != NULL)
            STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
        ATH_DFSQ_UNLOCK(dfs);

        if (event == NULL) {
            empty = 1;
            break;
        }
        events_processed++;
        re = *event;

        OS_MEMZERO(event, sizeof(struct dfs_event));
        ATH_DFSEVENTQ_LOCK(dfs);
        STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
        ATH_DFSEVENTQ_UNLOCK(dfs);

        found = 0;
        if (re.re_chanindex < DFS_NUM_RADAR_STATES)
            rs = &dfs->dfs_radar[re.re_chanindex];
        else {
            ATH_DFSQ_LOCK(dfs);
            empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
            ATH_DFSQ_UNLOCK(dfs);
            continue;
        }
        if (rs->rs_chan.ic_flagext & CHANNEL_INTERFERENCE) {
            ATH_DFSQ_LOCK(dfs);
            empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
            ATH_DFSQ_UNLOCK(dfs);
            continue;
        }

        if (dfs->dfs_rinfo.rn_lastfull_ts == 0) {
            /*
             * Either not started, or 64-bit rollover exactly to zero
             * Just prepend zeros to the 15-bit ts
             */
            dfs->dfs_rinfo.rn_ts_prefix = 0;
        } else {
            /* WAR 23031- patch duplicate ts on very short pulses */
            /* This pacth has two problems in linux environment.
             * 1)The time stamp created and hence PRI depends entirely on the latency.
             *   If the latency is high, it possibly can split two consecutive
             *   pulses in the same burst so far away (the same amount of latency)
             *   that make them look like they are from differenct bursts. It is
             *   observed to happen too often. It sure makes the detection fail.
             * 2)Even if the latency is not that bad, it simply shifts the duplicate
             *   timestamps to a new duplicate timestamp based on how they are processed.
             *   This is not worse but not good either.
             *
             *   Take this pulse as a good one and create a probable PRI later
             */
            if (re.re_dur == 0 && re.re_ts == dfs->dfs_rinfo.rn_last_unique_ts) {
                debug_dup[debug_dup_cnt++] = '1';
                DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "\n %s deltaT is 0 \n", __func__);
            } else {
                dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts;
                debug_dup[debug_dup_cnt++] = '0';
            }
            if (debug_dup_cnt >= 32) {
                debug_dup_cnt = 0;
            }


            if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) {
                dfs->dfs_rinfo.rn_ts_prefix +=
                    (((u_int64_t) 1) << DFS_TSSHIFT);
                /* Now, see if it's been more than 1 wrap */
                deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts;
                if (deltafull_ts >
                        ((u_int64_t)((DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts)))
                    deltafull_ts -= (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts;
                deltafull_ts = deltafull_ts >> DFS_TSSHIFT;
                if (deltafull_ts > 1) {
                    dfs->dfs_rinfo.rn_ts_prefix +=
                        ((deltafull_ts - 1) << DFS_TSSHIFT);
                }
            } else {
                deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts;
                if (deltafull_ts > (u_int64_t) DFS_TSMASK) {
                    deltafull_ts = deltafull_ts >> DFS_TSSHIFT;
                    dfs->dfs_rinfo.rn_ts_prefix +=
                        ((deltafull_ts - 1) << DFS_TSSHIFT);
                }
            }
Example #8
0
/*
 * This is called each time a channel change occurs, to (potentially) enable
 * the radar code.
 */
int dfs_radar_enable(struct ieee80211com *ic,
    struct ath_dfs_radar_tab_info *radar_info, int no_cac)
{
    int                                 is_ext_ch=IEEE80211_IS_CHAN_11N_HT40(ic->ic_curchan);
    int                                 is_fastclk = 0;
    //u_int32_t                        rfilt;
    struct ath_dfs                 *dfs=(struct ath_dfs *)ic->ic_dfs;
    struct ieee80211_channel *chan=ic->ic_curchan, *ext_ch = NULL;
  
	if (dfs == NULL) {
		DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: ic_dfs is NULL\n",
			__func__);
		return -EIO;
	}
	ic->ic_dfs_disable(ic, no_cac);

	/*
	 * Setting country code might change the DFS domain
	 * so initialize the DFS Radar filters
	 */
	dfs_init_radar_filters(ic, radar_info);
#if ATH_SUPPORT_DFS && ATH_SUPPORT_STA_DFS
	if ((ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS ||
                (ic->ic_opmode == IEEE80211_M_STA && ieee80211com_has_cap_ext(dfs->ic,IEEE80211_CEXT_STADFS)))) {
#else
	if ((ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS)) {
#endif
            	if (IEEE80211_IS_CHAN_DFS(chan)) {
			struct dfs_state *rs_pri=NULL, *rs_ext=NULL;
			u_int8_t index_pri, index_ext;
#ifdef ATH_ENABLE_AR
    dfs->dfs_proc_phyerr |= DFS_AR_EN;
#endif
    dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
    //printk( "%s[%d]: ==== 0x%08x\n", __func__, __LINE__, dfs->dfs_proc_phyerr);


                   if (is_ext_ch) {
                       ext_ch = ieee80211_get_extchan(ic);
                   }
			dfs_reset_alldelaylines(dfs);

			rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
			if (ext_ch) {
                            rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
                   }
    			if (rs_pri != NULL && ((ext_ch==NULL)||(rs_ext != NULL))) {
				struct ath_dfs_phyerr_param pe;

				OS_MEMSET(&pe, '\0', sizeof(pe));

				if (index_pri != dfs->dfs_curchan_radindex)
					dfs_reset_alldelaylines(dfs);

				dfs->dfs_curchan_radindex = (int16_t) index_pri;
                                
                                if (rs_ext)
			            dfs->dfs_extchan_radindex = (int16_t) index_ext;

				ath_dfs_phyerr_param_copy(&pe,
				    &rs_pri->rs_param);
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
				    "%s: firpwr=%d, rssi=%d, height=%d, "
				    "prssi=%d, inband=%d, relpwr=%d, "
				    "relstep=%d, maxlen=%d\n",
				    __func__,
				    pe.pe_firpwr,
				    pe.pe_rrssi,
				    pe.pe_height,
				    pe.pe_prssi,
				    pe.pe_inband,
				    pe.pe_relpwr,
				    pe.pe_relstep,
				    pe.pe_maxlen
				    );

#if 0 //Not needed
				/* Disable strong signal fast antenna diversity */
				ath_hal_setcapability(ah, HAL_CAP_DIVERSITY,
						      HAL_CAP_STRONG_DIV, 1, NULL);
#endif
	                    ic->ic_dfs_enable(ic, &is_fastclk, &pe);
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "Enabled radar detection on channel %d\n",
					chan->ic_freq);

                                dfs->dur_multiplier =  is_fastclk ? DFS_FAST_CLOCK_MULTIPLIER : DFS_NO_FAST_CLOCK_MULTIPLIER;
                    	DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
			"%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier);

			} else
				DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: No more radar states left\n",
					__func__);
		} 
	} 
	return 0;
}

int
dfs_control(struct ieee80211com *ic, u_int id,
                void *indata, u_int32_t insize,
                void *outdata, u_int32_t *outsize)
{
	int error = 0;
	struct ath_dfs_phyerr_param peout;
	struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs;
	struct dfs_ioctl_params *dfsparams;
    u_int32_t val=0;
#ifndef ATH_DFS_RADAR_DETECTION_ONLY
    struct dfsreq_nolinfo *nol;
    u_int32_t *data = NULL;
#endif /* ATH_DFS_RADAR_DETECTION_ONLY */
    int i;

	if (dfs == NULL) {
                DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s DFS is null\n", __func__);
                /* Enable/Disable DFS can be done prior to attach, So handle here */
	switch (id) {
        case DFS_DISABLE_DETECT:
                ic->ic_dfs_state.ignore_dfs = 1;
                DFS_PRINTK("%s enable detects, ignore_dfs %d\n", 
                    __func__,
		   ic->ic_dfs_state.ignore_dfs ? 1:0);
                break;
        case DFS_ENABLE_DETECT:
                ic->ic_dfs_state.ignore_dfs = 0;
                DFS_PRINTK("%s enable detects, ignore_dfs %d\n", 
                    __func__,
		    ic->ic_dfs_state.ignore_dfs ? 1:0);
                break;
        default:
            error = -EINVAL;
            break;
       }
		goto bad;
	}

      //printk("%s[%d] id =%d\n", __func__, __LINE__, id);
	switch (id) {
	case DFS_SET_THRESH:
		if (insize < sizeof(struct dfs_ioctl_params) || !indata) {
			DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
			    "%s: insize=%d, expected=%d bytes, indata=%p\n",
			    __func__, insize, sizeof(struct dfs_ioctl_params),
			    indata);
			error = -EINVAL;
			break;
		}
		dfsparams = (struct dfs_ioctl_params *) indata;
		if (!dfs_set_thresholds(ic, DFS_PARAM_FIRPWR, dfsparams->dfs_firpwr))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_RRSSI, dfsparams->dfs_rrssi))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_HEIGHT, dfsparams->dfs_height))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_PRSSI, dfsparams->dfs_prssi))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_INBAND, dfsparams->dfs_inband))
			error = -EINVAL;
		/* 5413 speicfic */
		if (!dfs_set_thresholds(ic, DFS_PARAM_RELPWR, dfsparams->dfs_relpwr))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_RELSTEP, dfsparams->dfs_relstep))
			error = -EINVAL;
		if (!dfs_set_thresholds(ic, DFS_PARAM_MAXLEN, dfsparams->dfs_maxlen))
			error = -EINVAL;
		break;
	case DFS_GET_THRESH:
		if (!outdata || !outsize || *outsize <sizeof(struct dfs_ioctl_params)) {
			error = -EINVAL;
			break;
		}
		*outsize = sizeof(struct dfs_ioctl_params);
		dfsparams = (struct dfs_ioctl_params *) outdata;

		/*
		 * Fetch the DFS thresholds using the internal representation.
		 */
		(void) dfs_get_thresholds(ic, &peout);

		/*
		 * Convert them to the dfs IOCTL representation.
		 */
		ath_dfs_dfsparam_to_ioctlparam(&peout, dfsparams);
                break;
	case DFS_RADARDETECTS:
		if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
			error = -EINVAL;
			break;
		}
		*outsize = sizeof (u_int32_t);
		*((u_int32_t *)outdata) = dfs->ath_dfs_stats.num_radar_detects;
		break;
        case DFS_DISABLE_DETECT:
                dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
                dfs->ic->ic_dfs_state.ignore_dfs = 1;
                DFS_PRINTK("%s enable detects, ignore_dfs %d\n", 
                    __func__,
		    dfs->ic->ic_dfs_state.ignore_dfs ? 1:0);
                break;
        case DFS_ENABLE_DETECT:
		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
                dfs->ic->ic_dfs_state.ignore_dfs = 0;
                DFS_PRINTK("%s enable detects, ignore_dfs %d\n", 
                    __func__,
		    dfs->ic->ic_dfs_state.ignore_dfs ? 1:0);
                break;
        case DFS_DISABLE_FFT:
                //UMACDFS: TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, false);
                DFS_PRINTK("%s TODO disable FFT val=0x%x \n", __func__, val);
                break;
        case DFS_ENABLE_FFT:
                //UMACDFS TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, true);
                DFS_PRINTK("%s TODO enable FFT val=0x%x \n", __func__, val);
                break;
        case DFS_SET_DEBUG_LEVEL:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
		dfs->dfs_debug_mask= *(u_int32_t *)indata;
		DFS_PRINTK("%s debug level now = 0x%x \n",
		    __func__,
		    dfs->dfs_debug_mask);
                if (dfs->dfs_debug_mask & ATH_DEBUG_DFS3) {
                    /* Enable debug Radar Event */
                    dfs->dfs_event_log_on = 1;
                } else {
                    dfs->dfs_event_log_on = 0;
                }
                break;
        case DFS_SET_FALSE_RSSI_THRES:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
		dfs->ath_dfs_false_rssi_thres= *(u_int32_t *)indata;
		DFS_PRINTK("%s false RSSI threshold now = 0x%x \n",
		    __func__,
		    dfs->ath_dfs_false_rssi_thres);
                break;
        case DFS_SET_PEAK_MAG:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
		dfs->ath_dfs_peak_mag= *(u_int32_t *)indata;
		DFS_PRINTK("%s peak_mag now = 0x%x \n",
		    __func__,
		    dfs->ath_dfs_peak_mag);
                break;
	case DFS_GET_CAC_VALID_TIME:
		if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
			error = -EINVAL;
			break;
		}
		*outsize = sizeof (u_int32_t);
		*((u_int32_t *)outdata) = dfs->ic->ic_dfs_state.cac_valid_time;
		break;
        case DFS_SET_CAC_VALID_TIME:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
		dfs->ic->ic_dfs_state.cac_valid_time = *(u_int32_t *)indata;
		DFS_PRINTK("%s dfs timeout = %d \n",
		    __func__,
		    dfs->ic->ic_dfs_state.cac_valid_time);
                break;
        case DFS_IGNORE_CAC:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
             if (*(u_int32_t *)indata) {
                 dfs->ic->ic_dfs_state.ignore_cac= 1;
             } else {
                 dfs->ic->ic_dfs_state.ignore_cac= 0;
             }
		DFS_PRINTK("%s ignore cac = 0x%x \n",
		    __func__,
		    dfs->ic->ic_dfs_state.ignore_cac);
                break;
        case DFS_SET_NOL_TIMEOUT:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
             if (*(int *)indata) {
                 dfs->ath_dfs_nol_timeout= *(int *)indata;
             } else {
                 dfs->ath_dfs_nol_timeout= DFS_NOL_TIMEOUT_S;
             }
		DFS_PRINTK("%s nol timeout = %d sec \n",
		    __func__,
		    dfs->ath_dfs_nol_timeout);
                break;
#ifndef ATH_DFS_RADAR_DETECTION_ONLY
    case DFS_MUTE_TIME:
        if (insize < sizeof(u_int32_t) || !indata) {
            error = -EINVAL;
            break;
        }
        data = (u_int32_t *) indata;
        dfs->ath_dfstesttime = *data;
        dfs->ath_dfstesttime *= (1000); //convert sec into ms
        break;
	case DFS_GET_USENOL:
		if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
			error = -EINVAL;
			break;
		}
		*outsize = sizeof(u_int32_t);
		*((u_int32_t *)outdata) = dfs->dfs_rinfo.rn_use_nol;
                 printk("%s:#Phyerr=%d, #false detect=%d, #queued=%d\n", __func__,dfs->dfs_phyerr_count, dfs->dfs_phyerr_reject_count, dfs->dfs_phyerr_queued_count);
                 printk("%s:dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d\n", __func__,dfs->dfs_phyerr_freq_min, dfs->dfs_phyerr_freq_max);
                 printk("%s:Total radar events detected=%d, entries in the radar queue follows:\n",  __func__,dfs->dfs_event_log_count);
                 for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count); i++) {
                         //DFS_DPRINTK(sc, ATH_DEBUG_DFS,"ts=%llu diff_ts=%u rssi=%u dur=%u\n", dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts, dfs->radar_log[i].rssi, dfs->radar_log[i].dur);
                         printk("ts=%llu diff_ts=%u rssi=%u dur=%u\n", dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts, dfs->radar_log[i].rssi, dfs->radar_log[i].dur);
                 }
                 dfs->dfs_event_log_count     = 0;
                 dfs->dfs_phyerr_count        = 0;
                 dfs->dfs_phyerr_reject_count = 0;
                 dfs->dfs_phyerr_queued_count = 0;
                dfs->dfs_phyerr_freq_min     = 0x7fffffff;
                dfs->dfs_phyerr_freq_max     = 0;
		break;
	case DFS_SET_USENOL:
		if (insize < sizeof(u_int32_t) || !indata) {
			error = -EINVAL;
			break;
		}
		dfs->dfs_rinfo.rn_use_nol = *(u_int32_t *)indata;
		/* iwpriv markdfs in linux can do the same thing... */
		break;
	case DFS_GET_NOL:
		if (!outdata || !outsize || *outsize < sizeof(struct dfsreq_nolinfo)) {
			error = -EINVAL;
			break;
		}
		*outsize = sizeof(struct dfsreq_nolinfo);
		nol = (struct dfsreq_nolinfo *)outdata;
		dfs_get_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, &nol->ic_nchans);
             dfs_print_nol(dfs);
		break;
	case DFS_SET_NOL:
		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
                        error = -EINVAL;
                        break;
                }
                nol = (struct dfsreq_nolinfo *) indata;
		dfs_set_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, nol->ic_nchans);
		break;

    case DFS_SHOW_NOL:
        dfs_print_nol(dfs);
        break;
#if ATH_SUPPORT_DFS && ATH_SUPPORT_STA_DFS
    case DFS_SHOW_NOLHISTORY:
        dfs_print_nolhistory(ic,dfs);
        break;
#endif
    case DFS_BANGRADAR:
 #if 0 //MERGE_TBD       
        if(sc->sc_nostabeacons)
        {
            printk("No radar detection Enabled \n");
            break;
        }
#endif        
        dfs->dfs_bangradar = 1;     
        dfs->ath_radar_tasksched = 1;
        OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
        break;
#endif /* ATH_DFS_RADAR_DETECTION_ONLY */
	default:
		error = -EINVAL;
	}
bad:
	return error;
}
Example #9
0
/*
 * Find the channel information according to the scan entry
 */
int rtt_find_channel_info (void *arg, wlan_scan_entry_t scan_entry)
{
    wmi_channel *wmi_chan;
    u_int32_t chan_mode;
    struct ieee80211com *ic;
    struct ieee80211_channel *se_chan;
    static const u_int modeflags[] = {
        0,                            /* IEEE80211_MODE_AUTO           */
        MODE_11A,         /* IEEE80211_MODE_11A            */
        MODE_11B,         /* IEEE80211_MODE_11B            */
        MODE_11G,         /* IEEE80211_MODE_11G            */
        0,                            /* IEEE80211_MODE_FH             */
        0,                            /* IEEE80211_MODE_TURBO_A        */
        0,                            /* IEEE80211_MODE_TURBO_G        */
        MODE_11NA_HT20,   /* IEEE80211_MODE_11NA_HT20      */
        MODE_11NG_HT20,   /* IEEE80211_MODE_11NG_HT20      */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40PLUS  */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40MINUS */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40PLUS  */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40MINUS */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40      */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40      */
        MODE_11AC_VHT20,  /* IEEE80211_MODE_11AC_VHT20     */
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40PLUS */
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40MINUS*/
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40     */
        MODE_11AC_VHT80,  /* IEEE80211_MODE_11AC_VHT80     */
    };

    adf_os_print("%s:\n", __func__);

    if (!(arg && scan_entry)) {
        return -1; //critical error
    }

    wmi_chan = ((channel_search *)arg)->channel;
    ic = ((channel_search *)arg)->ic;

    if(!(wmi_chan && ic)) {
        return -1; //critical error
    }

    se_chan = wlan_scan_entry_channel(scan_entry);

    if(!se_chan) {
        return -1; //critical error
    }

    wmi_chan->mhz = ieee80211_chan2freq(ic,se_chan);
    chan_mode = ieee80211_chan2mode(se_chan);
    WMI_SET_CHANNEL_MODE(wmi_chan, modeflags[chan_mode]);

    if(chan_mode == IEEE80211_MODE_11AC_VHT80) {
        if (se_chan->ic_ieee < 20) {
            wmi_chan->band_center_freq1 = ieee80211_ieee2mhz(
                                             se_chan->ic_vhtop_ch_freq_seg1,
                                             IEEE80211_CHAN_2GHZ);
        } else {
            wmi_chan->band_center_freq1 = ieee80211_ieee2mhz(
                                            se_chan->ic_vhtop_ch_freq_seg1,
                                            IEEE80211_CHAN_5GHZ);
        }
    } else if((chan_mode == IEEE80211_MODE_11NA_HT40PLUS) ||
              (chan_mode == IEEE80211_MODE_11NG_HT40PLUS) ||
              (chan_mode == IEEE80211_MODE_11AC_VHT40PLUS)) {
        wmi_chan->band_center_freq1 = wmi_chan->mhz + 10;
    } else if((chan_mode == IEEE80211_MODE_11NA_HT40MINUS) ||
              (chan_mode == IEEE80211_MODE_11NG_HT40MINUS) ||
              (chan_mode == IEEE80211_MODE_11AC_VHT40MINUS)) {
        wmi_chan->band_center_freq1 = wmi_chan->mhz - 10;
    } else {
        wmi_chan->band_center_freq1 = wmi_chan->mhz;
    }

    /* we do not support HT80PLUS80 yet */
    wmi_chan->band_center_freq2=0;
    WMI_SET_CHANNEL_MIN_POWER(wmi_chan, se_chan->ic_minpower);
    WMI_SET_CHANNEL_MAX_POWER(wmi_chan, se_chan->ic_maxpower);
    WMI_SET_CHANNEL_REG_POWER(wmi_chan, se_chan->ic_maxregpower);
    WMI_SET_CHANNEL_ANTENNA_MAX(wmi_chan, se_chan->ic_antennamax);
    WMI_SET_CHANNEL_REG_CLASSID(wmi_chan, se_chan->ic_regClassId);

    if (IEEE80211_IS_CHAN_DFS(se_chan))
        WMI_SET_CHANNEL_FLAG(wmi_chan, WMI_CHAN_FLAG_DFS);

    adf_os_print("WMI channel freq=%d, mode=%x band_center_freq1=%d\n", wmi_chan->mhz, 
        WMI_GET_CHANNEL_MODE(wmi_chan), wmi_chan->band_center_freq1);

    return 1; //seccessful!    
}
Example #10
0
static int 
ol_vdev_wmi_event_handler(ol_scn_t scn, u_int8_t *data, u_int16_t datalen, void *context)
{
    ieee80211_resmgr_t resmgr = (ieee80211_resmgr_t )context;
    wmi_vdev_start_response_event *wmi_vdev_start_resp_ev =
                                                (wmi_vdev_start_response_event *)data;
    wlan_if_t vaphandle;
    struct ieee80211com  *ic = resmgr->ic;
    struct ieee80211_channel *chan = NULL;
    struct ieee80211_node *ni;
    u_int8_t numvaps, actidx = 0;
    struct ol_ath_vap_net80211 *avn;
    bool do_notify = true;
    vaphandle = ol_ath_vap_get(scn, wmi_vdev_start_resp_ev->vdev_id);

    if (NULL == vaphandle) {
        printk("Event received for Invalid/Deleted vap handle\n");
        return 0;
    }

    avn = OL_ATH_VAP_NET80211(vaphandle);

    printk("ol_vdev_start_resp_ev for vap %d (%p)\n", wmi_vdev_start_resp_ev->vdev_id, scn->wmi_handle);

    spin_lock(&vaphandle->init_lock);

    switch (vaphandle->iv_opmode) {

        case IEEE80211_M_MONITOR:
               /* Handle same as HOSTAP */
        case IEEE80211_M_HOSTAP:
            /* If vap is not waiting for the WMI event from target
               return here
             */
            if(avn->av_ol_resmgr_wait == FALSE) {
                spin_unlock(&vaphandle->init_lock);
                return 0;
            }
             /* Resetting the ol_resmgr_wait flag*/
            avn->av_ol_resmgr_wait = FALSE;

            numvaps = ieee80211_vaps_active(ic);

            chan =  vaphandle->iv_des_chan[vaphandle->iv_des_mode];

            /* 
             * if there is a vap already running.
             * ignore the desired channel and use the
             * operating channel of the other vap.
             */
            /* so that cwm can do its own crap. need to untie from state */
            /* vap join is called here to wake up the chip if it is in sleep state */
            ieee80211_vap_join(vaphandle);
            
            if (numvaps == 0) {
                //AP_DFS: ieee80211_set_channel(ic, chan);
                if (wmi_vdev_start_resp_ev->resp_type != WMI_VDEV_RESTART_RESP_EVENT) {
                     /* 20/40 Mhz coexistence  handler */
                    if ((avn->av_ol_resmgr_chan != NULL) && (chan != avn->av_ol_resmgr_chan)) {
                        chan = avn->av_ol_resmgr_chan;
                    }

                    ic->ic_prevchan = ic->ic_curchan;
                    ic->ic_curchan = chan;
                    /*update channel history*/
                    actidx = ic->ic_chanidx;
                    ic->ic_chanhist[actidx].chanid = (ic->ic_curchan)->ic_ieee;
                    ic->ic_chanhist[actidx].chanjiffies = OS_GET_TIMESTAMP();
                    ic->ic_chanidx == (IEEE80211_CHAN_MAXHIST - 1) ? ic->ic_chanidx = 0 : ++(ic->ic_chanidx);
                    /* update max channel power to max regpower of current channel */
                    ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower);
                    ieee80211_wme_initparams(vaphandle);
                }

                /* ieee80211 Layer - Default Configuration */
                vaphandle->iv_bsschan = ic->ic_curchan;
                /* XXX reset erp state */
                ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode);
            } else {
                /* ieee80211 Layer - Default Configuration */
                vaphandle->iv_bsschan = ic->ic_curchan;
            }
            /* use the vap bsschan for dfs configure */
            if ( IEEE80211_IS_CHAN_DFS(vaphandle->iv_bsschan)) {
                   extern void ol_if_dfs_configure(struct ieee80211com *ic);
                   ol_if_dfs_configure(ic);
            }
            break;
        case IEEE80211_M_STA:

            ni = vaphandle->iv_bss;

            chan = ni->ni_chan;

            vaphandle->iv_bsschan = chan;
            
            ic->ic_prevchan = ic->ic_curchan;
            ic->ic_curchan = chan;
            /* update max channel power to max regpower of current channel */
            ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower);

            /* ieee80211 Layer - Default Configuration */
            vaphandle->iv_bsschan = ic->ic_curchan;

            /* XXX reset erp state */
            ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode);
            ieee80211_wme_initparams(vaphandle);
            if (wmi_vdev_start_resp_ev->resp_type == WMI_VDEV_RESTART_RESP_EVENT) {
                do_notify = false;
            }
            
            break;
        default:
            break;
    }

    vaphandle->init_in_progress = false;
    spin_unlock(&vaphandle->init_lock);

    /* Intimate start completion to VAP module */
    /* if STA, bypass notification for RESTERT EVENT */
    if (do_notify)
    ieee80211_notify_vap_start_complete(resmgr, vaphandle, IEEE80211_RESMGR_STATUS_SUCCESS);

    return 0;
}
Example #11
0
/*
 * This is called each time a channel change occurs, to (potentially) enable
 * the radar code.
 */
int dfs_radar_enable(struct ieee80211com *ic,
    struct ath_dfs_radar_tab_info *radar_info)
{
    int                                 is_ext_ch;
    int                                 is_fastclk = 0;
    int                                 radar_filters_init_status = 0;
    //u_int32_t                        rfilt;
    struct ath_dfs                      *dfs;
    struct dfs_state *rs_pri, *rs_ext;
    struct ieee80211_channel *chan=ic->ic_curchan, *ext_ch = NULL;
    is_ext_ch=IEEE80211_IS_CHAN_11N_HT40(ic->ic_curchan);
    dfs=(struct ath_dfs *)ic->ic_dfs;
    rs_pri = NULL;
    rs_ext = NULL;
#if 0
    int i;
#endif
   if (dfs == NULL) {
                DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: ic_dfs is NULL\n",
         __func__);

                return -EIO;
   }
           ic->ic_dfs_disable(ic);

   /*
    * Setting country code might change the DFS domain
    * so initialize the DFS Radar filters
    */
   radar_filters_init_status = dfs_init_radar_filters(ic, radar_info);

   /*
    * dfs_init_radar_filters() returns 1 on failure and
    * 0 on success.
    */
   if ( DFS_STATUS_FAIL == radar_filters_init_status ) {
      VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
                      "%s[%d]: DFS Radar Filters Initialization Failed",
                       __func__,  __LINE__);
      return -EIO;
   }

   if ((ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS)) {

                if (IEEE80211_IS_CHAN_DFS(chan)) {

         u_int8_t index_pri, index_ext;
#ifdef ATH_ENABLE_AR
    dfs->dfs_proc_phyerr |= DFS_AR_EN;
#endif
    dfs->dfs_proc_phyerr |= DFS_RADAR_EN;



                   if (is_ext_ch) {
                       ext_ch = ieee80211_get_extchan(ic);
                   }
         dfs_reset_alldelaylines(dfs);

         rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
         if (ext_ch) {
                            rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
                   }
         if (rs_pri != NULL && ((ext_ch==NULL)||(rs_ext != NULL))) {
             struct ath_dfs_phyerr_param pe;

             OS_MEMSET(&pe, '\0', sizeof(pe));

             if (index_pri != dfs->dfs_curchan_radindex)
                 dfs_reset_alldelaylines(dfs);

             dfs->dfs_curchan_radindex = (int16_t) index_pri;
             dfs->dfs_pri_multiplier_ini = radar_info->dfs_pri_multiplier;

             if (rs_ext)
                 dfs->dfs_extchan_radindex = (int16_t) index_ext;

             ath_dfs_phyerr_param_copy(&pe,
                     &rs_pri->rs_param);
             DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
                     "%s: firpwr=%d, rssi=%d, height=%d, "
                     "prssi=%d, inband=%d, relpwr=%d, "
                     "relstep=%d, maxlen=%d\n",
                     __func__,
                     pe.pe_firpwr,
                     pe.pe_rrssi,
                     pe.pe_height,
                     pe.pe_prssi,
                     pe.pe_inband,
                     pe.pe_relpwr,
                     pe.pe_relstep,
                     pe.pe_maxlen
                     );

             ic->ic_dfs_enable(ic, &is_fastclk, &pe);
             DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "Enabled radar detection on channel %d\n",
                     chan->ic_freq);
             dfs->dur_multiplier =
                 is_fastclk ? DFS_FAST_CLOCK_MULTIPLIER : DFS_NO_FAST_CLOCK_MULTIPLIER;
             DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
                     "%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier);
         } else
             DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: No more radar states left\n",
                     __func__);
      }
   }

   return DFS_STATUS_SUCCESS;
}