Ejemplo n.º 1
0
static void
print_chaninfo(const struct ieee80211_channel *c)
{
	char buf[14];

	buf[0] = '\0';
	if (IEEE80211_IS_CHAN_FHSS(c))
		strlcat(buf, " FHSS", sizeof(buf));
	if (IEEE80211_IS_CHAN_A(c))
		strlcat(buf, " 11a", sizeof(buf));
	/* XXX 11g schizophrenia */
	if (IEEE80211_IS_CHAN_G(c) ||
	    IEEE80211_IS_CHAN_PUREG(c))
		strlcat(buf, " 11g", sizeof(buf));
	else if (IEEE80211_IS_CHAN_B(c))
		strlcat(buf, " 11b", sizeof(buf));
	if (IEEE80211_IS_CHAN_STURBO(c))
		strlcat(buf, " Static", sizeof(buf));
	if (IEEE80211_IS_CHAN_DTURBO(c))
		strlcat(buf, " Dynamic", sizeof(buf));
	if (IEEE80211_IS_CHAN_HALF(c))
		strlcat(buf, " Half", sizeof(buf));
	if (IEEE80211_IS_CHAN_QUARTER(c))
		strlcat(buf, " Quarter", sizeof(buf));
	printf("Channel %3u : %u%c%c Mhz%-14.14s",
		c->ic_ieee, c->ic_freq,
		IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ', 
	        IEEE80211_IS_CHAN_RADAR(c) ? '!' : ' ', 
	       buf);
}
Ejemplo n.º 2
0
static void
cac_timeout_callout(void *arg)
{
	struct ieee80211vap *vap = arg;
	struct ieee80211com *ic;
	struct ieee80211_dfs_state *dfs;
	int i;

	wlan_serialize_enter();
	ic = vap->iv_ic;
	dfs = &ic->ic_dfs;
	if (vap->iv_state != IEEE80211_S_CAC) {	/* NB: just in case */
		wlan_serialize_exit();
		return;
	}
	/*
	 * When radar is detected during a CAC we are woken
	 * up prematurely to switch to a new channel.
	 * Check the channel to decide how to act.
	 */
	if (IEEE80211_IS_CHAN_RADAR(ic->ic_curchan)) {
		ieee80211_notify_cac(ic, ic->ic_curchan,
		    IEEE80211_NOTIFY_CAC_RADAR);

		if_printf(vap->iv_ifp,
		    "CAC timer on channel %u (%u MHz) stopped due to radar\n",
		    ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq);

		/* XXX clobbers any existing desired channel */
		/* NB: dfs->newchan may be NULL, that's ok */
		vap->iv_des_chan = dfs->newchan;
		/* XXX recursive lock need ieee80211_new_state_locked */
		ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
	} else {
		if_printf(vap->iv_ifp,
		    "CAC timer on channel %u (%u MHz) expired; "
		    "no radar detected\n",
		    ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq);
		/*
		 * Mark all channels with the current frequency
		 * as having completed CAC; this keeps us from
		 * doing it again until we change channels.
		 */
		for (i = 0; i < ic->ic_nchans; i++) {
			struct ieee80211_channel *c = &ic->ic_channels[i];
			if (c->ic_freq == ic->ic_curchan->ic_freq)
				c->ic_state |= IEEE80211_CHANSTATE_CACDONE;
		}
		ieee80211_notify_cac(ic, ic->ic_curchan,
		    IEEE80211_NOTIFY_CAC_EXPIRE);
		ieee80211_cac_completeswitch(vap);
	}
	wlan_serialize_exit();
}
Ejemplo n.º 3
0
struct ieee80211_channel *
ieee80211_dfs_pickchannel(struct ieee80211com *ic)
{
    struct ieee80211_channel *c;
    int i, flags;
    uint16_t v;

    /*
     * Consult the scan cache first.
     */
    flags = ic->ic_curchan->ic_flags & IEEE80211_CHAN_ALL;
    /*
     * XXX if curchan is HT this will never find a channel
     * XXX 'cuz we scan only legacy channels
     */
    c = ieee80211_scan_pickchannel(ic, flags);
    if (c != NULL)
        return c;
    /*
     * No channel found in scan cache; select a compatible
     * one at random (skipping channels where radar has
     * been detected).
     */
    get_random_bytes(&v, sizeof(v));
    v %= ic->ic_nchans;
    for (i = v; i < ic->ic_nchans; i++) {
        c = &ic->ic_channels[i];
        if (!IEEE80211_IS_CHAN_RADAR(c) &&
                (c->ic_flags & flags) == flags)
            return c;
    }
    for (i = 0; i < v; i++) {
        c = &ic->ic_channels[i];
        if (!IEEE80211_IS_CHAN_RADAR(c) &&
                (c->ic_flags & flags) == flags)
            return c;
    }
    if_printf(ic->ic_ifp, "HELP, no channel located to switch to!\n");
    return NULL;
}
Ejemplo n.º 4
0
static void
dfs_timeout(void *arg)
{
	struct ieee80211com *ic = arg;
	struct ieee80211_dfs_state *dfs = &ic->ic_dfs;
	struct ieee80211_channel *c;
	int i, oldest, now;

	IEEE80211_LOCK_ASSERT(ic);

	now = oldest = ticks;
	for (i = 0; i < ic->ic_nchans; i++) {
		c = &ic->ic_channels[i];
		if (IEEE80211_IS_CHAN_RADAR(c)) {
			if (time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
				c->ic_state &= ~IEEE80211_CHANSTATE_RADAR;
				if (c->ic_state & IEEE80211_CHANSTATE_NORADAR) {
					/*
					 * NB: do this here so we get only one
					 * msg instead of one for every channel
					 * table entry.
					 */
					if_printf(ic->ic_ifp, "radar on channel"
					    " %u (%u MHz) cleared after timeout\n",
					    c->ic_ieee, c->ic_freq);
					/* notify user space */
					c->ic_state &=
					    ~IEEE80211_CHANSTATE_NORADAR;
					ieee80211_notify_radar(ic, c);
				}
			} else if (dfs->nol_event[i] < oldest)
				oldest = dfs->nol_event[i];
		}
	}
	if (oldest != now) {
		/* arrange to process next channel up for a status change */
		callout_schedule_dfly(&dfs->nol_timer, oldest + NOL_TIMEOUT - now,
				dfs_timeout, ic);
	}
}
Ejemplo n.º 5
0
/*
 * IEEE80211_M_IBSS+IEEE80211_M_AHDEMO vap state machine handler.
 */
static int
adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
	struct ieee80211com *ic = vap->iv_ic;
	struct ieee80211_node *ni;
	enum ieee80211_state ostate;

	IEEE80211_LOCK_ASSERT(vap->iv_ic);

	ostate = vap->iv_state;
	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
	    __func__, ieee80211_state_name[ostate],
	    ieee80211_state_name[nstate], arg);
	vap->iv_state = nstate;			/* state transition */
	if (ostate != IEEE80211_S_SCAN)
		ieee80211_cancel_scan(vap);	/* background scan */
	ni = vap->iv_bss;			/* NB: no reference held */
	switch (nstate) {
	case IEEE80211_S_INIT:
		switch (ostate) {
		case IEEE80211_S_SCAN:
			ieee80211_cancel_scan(vap);
			break;
		default:
			break;
		}
		if (ostate != IEEE80211_S_INIT) {
			/* NB: optimize INIT -> INIT case */
			ieee80211_reset_bss(vap);
		}
		break;
	case IEEE80211_S_SCAN:
		switch (ostate) {
		case IEEE80211_S_RUN:		/* beacon miss */
			/* purge station table; entries are stale */
			ieee80211_iterate_nodes(&ic->ic_sta, sta_leave, vap);
			/* fall thru... */
		case IEEE80211_S_INIT:
			if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
			    !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
				/*
				 * Already have a channel; bypass the
				 * scan and startup immediately.
				 */
				ieee80211_create_ibss(vap,
				    ieee80211_ht_adjust_channel(ic,
				    vap->iv_des_chan, vap->iv_flags_ht));
				break;
			}
			/*
			 * Initiate a scan.  We can come here as a result
			 * of an IEEE80211_IOC_SCAN_REQ too in which case
			 * the vap will be marked with IEEE80211_FEXT_SCANREQ
			 * and the scan request parameters will be present
			 * in iv_scanreq.  Otherwise we do the default.
			 */
			if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
				ieee80211_check_scan(vap,
				    vap->iv_scanreq_flags,
				    vap->iv_scanreq_duration,
				    vap->iv_scanreq_mindwell,
				    vap->iv_scanreq_maxdwell,
				    vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
				vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
			} else
				ieee80211_check_scan_current(vap);
			break;
		case IEEE80211_S_SCAN:
			/*
			 * This can happen because of a change in state
			 * that requires a reset.  Trigger a new scan
			 * unless we're in manual roaming mode in which
			 * case an application must issue an explicit request.
			 */
			if (vap->iv_roaming == IEEE80211_ROAMING_AUTO)
				ieee80211_check_scan_current(vap);
			break;
		default:
			goto invalid;
		}
		break;
	case IEEE80211_S_RUN:
		if (vap->iv_flags & IEEE80211_F_WPA) {
			/* XXX validate prerequisites */
		}
		switch (ostate) {
		case IEEE80211_S_SCAN:
#ifdef IEEE80211_DEBUG
			if (ieee80211_msg_debug(vap)) {
				ieee80211_note(vap,
				    "synchronized with %s ssid ",
				    ether_sprintf(ni->ni_bssid));
				ieee80211_print_essid(vap->iv_bss->ni_essid,
				    ni->ni_esslen);
				/* XXX MCS/HT */
				printf(" channel %d start %uMb\n",
				    ieee80211_chan2ieee(ic, ic->ic_curchan),
				    IEEE80211_RATE2MBS(ni->ni_txrate));
			}
#endif
			break;
		case IEEE80211_S_RUN:	/* IBSS merge */
			break;
		default:
			goto invalid;
		}
		/*
		 * When 802.1x is not in use mark the port authorized
		 * at this point so traffic can flow.
		 */
		if (ni->ni_authmode != IEEE80211_AUTH_8021X)
			ieee80211_node_authorize(ni);
		/*
		 * Fake association when joining an existing bss.
		 */
		if (!IEEE80211_ADDR_EQ(ni->ni_macaddr, vap->iv_myaddr) &&
		    ic->ic_newassoc != NULL)
			ic->ic_newassoc(ni, ostate != IEEE80211_S_RUN);
		break;
	case IEEE80211_S_SLEEP:
		vap->iv_sta_ps(vap, 0);
		break;
	default:
	invalid:
		IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
		    "%s: unexpected state transition %s -> %s\n", __func__,
		    ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
		break;
	}
	return 0;
}
Ejemplo n.º 6
0
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
}