blob: bab0df08d8263354c1c99d8c625ca311e40d5820 [file] [log] [blame]
/*
* Copyright (c) 2007-2008 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "cprecomp.h"
/* zfAddFreqChangeReq should be called inside the critical section */
static void zfAddFreqChangeReq(zdev_t* dev, u16_t frequency, u8_t bw40,
u8_t extOffset, zfpFreqChangeCompleteCb cb)
{
zmw_get_wlan_dev(dev);
//printk("zfAddFreqChangeReq freqReqQueueTail%d\n", wd->freqCtrl.freqReqQueueTail);
wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueTail] = frequency;
wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueTail] = bw40;
wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueTail] = extOffset;
wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueTail] = cb;
wd->freqCtrl.freqReqQueueTail++;
if ( wd->freqCtrl.freqReqQueueTail >= ZM_MAX_FREQ_REQ_QUEUE )
{
wd->freqCtrl.freqReqQueueTail = 0;
}
}
void zfCoreSetFrequencyV2(zdev_t* dev, u16_t frequency, zfpFreqChangeCompleteCb cb)
{
zfCoreSetFrequencyEx(dev, frequency, 0, 0, cb);
}
void zfCoreSetFrequencyExV2(zdev_t* dev, u16_t frequency, u8_t bw40,
u8_t extOffset, zfpFreqChangeCompleteCb cb, u8_t forceSetFreq)
{
u8_t setFreqImmed = 0;
u8_t initRF = 0;
zmw_get_wlan_dev(dev);
zmw_declare_for_critical_section();
zm_msg1_scan(ZM_LV_1, "Freq=", frequency);
zmw_enter_critical_section(dev);
if ((wd->sta.currentFrequency == frequency)
&& (wd->sta.currentBw40 == bw40)
&& (wd->sta.currentExtOffset == extOffset))
{
if ( forceSetFreq == 0 && wd->sta.flagFreqChanging == 0 )
{
goto done;
}
}
#ifdef ZM_FB50
/*if(frequency!=2437) {
zmw_leave_critical_section(dev);
return;
}*/
#endif
zfAddFreqChangeReq(dev, frequency, bw40, extOffset, cb);
// zm_assert( wd->sta.flagFreqChanging == 0 );
//wd->sta.flagFreqChanging = 1;
if ( wd->sta.flagFreqChanging == 0 )
{
if ((wd->sta.currentBw40 != bw40) || (wd->sta.currentExtOffset != extOffset))
{
initRF = 1;
}
wd->sta.currentFrequency = frequency;
wd->sta.currentBw40 = bw40;
wd->sta.currentExtOffset = extOffset;
setFreqImmed = 1;
}
wd->sta.flagFreqChanging++;
zmw_leave_critical_section(dev);
if ( setFreqImmed )
{
//zfHpSetFrequency(dev, frequency, 0);
if ( forceSetFreq )
{ // Cold reset to reset the frequency after scanning !
zm_debug_msg0("#6_1 20070917");
zm_debug_msg0("It is happen!!! No error message");
zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, 2);
}
else
{
zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, initRF);
}
if ( zfStaIsConnected(dev)
&& (frequency == wd->frequency)) {
wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
}
}
return;
done:
zmw_leave_critical_section(dev);
if ( cb != NULL )
{
cb(dev);
}
zfPushVtxq(dev);
return;
}
void zfCoreSetFrequencyEx(zdev_t* dev, u16_t frequency, u8_t bw40,
u8_t extOffset, zfpFreqChangeCompleteCb cb)
{
zfCoreSetFrequencyExV2(dev, frequency, bw40, extOffset, cb, 0);
}
void zfCoreSetFrequency(zdev_t* dev, u16_t frequency)
{
zfCoreSetFrequencyV2(dev, frequency, NULL);
}
/* zfRemoveFreqChangeReq SHOULD NOT be called inside the critical section */
static void zfRemoveFreqChangeReq(zdev_t* dev)
{
zfpFreqChangeCompleteCb cb = NULL;
u16_t frequency;
u8_t bw40;
u8_t extOffset;
u16_t compFreq = 0;
u8_t compBw40 = 0;
u8_t compExtOffset = 0;
zmw_get_wlan_dev(dev);
zmw_declare_for_critical_section();
zmw_enter_critical_section(dev);
if (wd->freqCtrl.freqReqQueueHead != wd->freqCtrl.freqReqQueueTail)
{
zm_msg1_scan(ZM_LV_1, "Freq=",
wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead]);
compFreq = wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead];
compBw40 = wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueHead];
compExtOffset = wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueHead];
wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] = 0;
cb = wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueHead];
wd->freqCtrl.freqReqQueueHead++;
if ( wd->freqCtrl.freqReqQueueHead >= ZM_MAX_FREQ_REQ_QUEUE )
{
wd->freqCtrl.freqReqQueueHead = 0;
}
}
zmw_leave_critical_section(dev);
if ( cb != NULL )
{
cb(dev);
}
zmw_enter_critical_section(dev);
while (wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] != 0)
{
frequency = wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead];
bw40 = wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueHead];
extOffset=wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueHead];
if ((compFreq == frequency)
&& (compBw40 == bw40)
&& (compExtOffset == extOffset))
{
/* Duplicated frequency command */
zm_msg1_scan(ZM_LV_1, "Duplicated Freq=", frequency);
cb = wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueHead];
wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] = 0;
wd->freqCtrl.freqReqQueueHead++;
if ( wd->freqCtrl.freqReqQueueHead >= ZM_MAX_FREQ_REQ_QUEUE )
{
wd->freqCtrl.freqReqQueueHead = 0;
}
if ( wd->sta.flagFreqChanging != 0 )
{
wd->sta.flagFreqChanging--;
}
zmw_leave_critical_section(dev);
if ( cb != NULL )
{
cb(dev);
}
zmw_enter_critical_section(dev);
}
else
{
u8_t initRF = 0;
if ((wd->sta.currentBw40 != bw40) || (wd->sta.currentExtOffset != extOffset))
{
initRF = 1;
}
wd->sta.currentFrequency = frequency;
wd->sta.currentBw40 = bw40;
wd->sta.currentExtOffset = extOffset;
zmw_leave_critical_section(dev);
zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, initRF);
if ( zfStaIsConnected(dev)
&& (frequency == wd->frequency)) {
wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
}
return;
}
}
zmw_leave_critical_section(dev);
return;
}
void zfCoreSetFrequencyComplete(zdev_t* dev)
{
zmw_get_wlan_dev(dev);
zmw_declare_for_critical_section();
zm_msg1_scan(ZM_LV_1, "flagFreqChanging=", wd->sta.flagFreqChanging);
zmw_enter_critical_section(dev);
//wd->sta.flagFreqChanging = 0;
if ( wd->sta.flagFreqChanging != 0 )
{
wd->sta.flagFreqChanging--;
}
zmw_leave_critical_section(dev);
zfRemoveFreqChangeReq(dev);
zfPushVtxq(dev);
return;
}
void zfReSetCurrentFrequency(zdev_t* dev)
{
zmw_get_wlan_dev(dev);
zm_debug_msg0("It is happen!!! No error message");
zfCoreSetFrequencyExV2(dev, wd->frequency, 0, 0, NULL, 1);
}