예제 #1
0
/*
 * Return the centre frequency for the current operating channel and
 * event.
 *
 * This is for post-Owl 11n chips which report pri/extension channel
 * events.
 */
static inline uint16_t
dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
{
   struct ieee80211com *ic;
   int chan_offset = 0, chan_width;

   /* Handle edge cases during startup/transition, shouldn't happen! */
   if (dfs == NULL)
      return (0);
   if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL)
      return (0);

   ic = dfs->ic;

   /*
    *
    * For wide channels, DC and ext frequencies need a bit of hand-holding
    * based on whether it's an upper or lower channel.
    */
   chan_width = dfs_get_event_freqwidth(dfs);

   if (IEEE80211_IS_CHAN_11N_HT40PLUS(ic->ic_curchan))
      chan_offset = chan_width;
   else if (IEEE80211_IS_CHAN_11N_HT40MINUS(ic->ic_curchan))
      chan_offset = -chan_width;
   else
      chan_offset = 0;

   /*
    * Check for DC events first - the sowl code may just set all
    * the bits together..
    */
   if (is_dc) {
      /*
       * XXX TODO: Should DC events be considered 40MHz wide here?
       */
      return (ieee80211_chan2freq(ic, ic->ic_curchan) +
          (chan_offset / 2));
   }

   /*
    * For non-wide channels, the centre frequency is just ic_freq.
    * The centre frequency for pri events is still ic_freq.
    */
   if (is_pri) {
      return (ieee80211_chan2freq(ic, ic->ic_curchan));
   }

   if (is_ext) {
      return (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width);
   }

   /* XXX shouldn't get here */
   return (ieee80211_chan2freq(ic, ic->ic_curchan));
}
예제 #2
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;
}
예제 #3
0
/*
 * Calculate the channel centre in MHz.
 */
static int
tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs)
{
	uint32_t chan_centre;
	uint32_t chan_width;
	int chan_offset;

	/*
	 * For now, just handle up to VHT80 correctly.
	 */
	if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) {
		DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?\n",
		    __func__, dfs->ic);
		return (0);
	/*
	 * For now, the only 11ac channel with freq1/freq2 setup is
	 * VHT80.
	 *
	 * XXX should have a flag macro to check this!
	 */
	} else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) {
		/* 11AC, so cfreq1/cfreq2 are setup */

		/*
		 * XXX if it's 80+80 this won't work - need to use seg
		 * appropriately!
		 */

		chan_centre = dfs->ic->ic_ieee2mhz(
		    dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1,
		    dfs->ic->ic_curchan->ic_flags);
	} else {
		/* HT20/HT40 */

		/*
		 * XXX this is hard-coded - it should be 5 or 10 for
		 * half/quarter appropriately.
		 */
		chan_width = 20;

		/* Grab default channel centre */
		chan_centre = ieee80211_chan2freq(dfs->ic,
		    dfs->ic->ic_curchan);

		/* Calculate offset based on HT40U/HT40D and VHT40U/VHT40D */
		if (IEEE80211_IS_CHAN_11N_HT40PLUS(dfs->ic->ic_curchan) ||
		    dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40PLUS)
			chan_offset = chan_width;
		else if (IEEE80211_IS_CHAN_11N_HT40MINUS(dfs->ic->ic_curchan) ||
		    dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40MINUS)
			chan_offset = -chan_width;
		else
			chan_offset = 0;

		/* Calculate new _real_ channel centre */
		chan_centre += (chan_offset / 2);
	}

	/*
	 * XXX half/quarter rate support!
	 */

	/* Return ev_chan_centre in MHz */
	return (chan_centre);
}
예제 #4
0
/*
 * Parse the radar summary frame.
 *
 * The frame contents _minus_ the TLV are passed in.
 */
static void
radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len,
    struct rx_radar_status *rsu)
{
   uint32_t rs[2];
   int freq_centre, freq;

   /* Drop out if we have < 2 DWORDs available */
   if (len < sizeof(rs)) {
      DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR |
          ATH_DEBUG_DFS_PHYERR_SUM,
          "%s: len (%zu) < expected (%zu)!",
          __func__,
          len,
          sizeof(rs));
   }

   /*
    * Since the TLVs may be unaligned for some reason
    * we take a private copy into aligned memory.
    * This enables us to use the HAL-like accessor macros
    * into the DWORDs to access sub-DWORD fields.
    */
   OS_MEMCPY(rs, buf, sizeof(rs));

        DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x", __func__, rs[0], rs[1]);
// DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):", __func__, buf);

   /* Populate the fields from the summary report */
   rsu->tsf_offset =
       MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET);
   rsu->pulse_duration =
       MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR);
   rsu->is_chirp =
       MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP);
   rsu->sidx = sign_extend_32(
           MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_SIDX),
             10);
   rsu->freq_offset =
           calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs));

   /* These are only relevant if the pulse is a chirp */
   rsu->delta_peak = sign_extend_32(
       MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_PEAK),
           6);
   rsu->delta_diff =
       MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF);

   /* WAR for FCC Type 4*/
   /*
    * HW is giving longer pulse duration (in case of VHT80, with traffic)
    * which fails to detect FCC type4 radar pulses. Added a work around to
    * fix the pulse duration and duration delta.
    *
    * IF VHT80
    *   && (primary_channel==30MHz || primary_channel== -30MHz)
    *   && -4 <= pulse_index <= 4
    *   && !chirp
    *   && pulse duration > 20 us
    * THEN
    *   Set pulse duration to 20 us
    */

   freq = ieee80211_chan2freq(dfs->ic, dfs->ic->ic_curchan);
   freq_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1;

   if ((IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan) &&
            (abs(freq - freq_centre) == 30) &&
            !rsu->is_chirp &&
            abs(rsu->sidx) <= 4 &&
            rsu->pulse_duration > 20)){
      rsu->pulse_duration = 20;
   }

}
예제 #5
0
파일: ol_if_rtt.c 프로젝트: KHATEEBNSIT/AP
/*
 * 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!    
}