staging: r8723au: Add source files for new driver - part 1

The Realtek USB device RTL8723AU is found in Lenovo Yoga 13 tablets.
A driver for it has been available in a GitHub repo for several months.
This commit contains the first part of the source files. The source
is arbitrarily split to avoid E-mail files that are too large.

Jes Sorensen at RedHat has made many improvements to the vendor code,
and he has been doing the testing. I do not have access to this device.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Larry Finger 2014-03-28 21:37:38 -05:00 коммит произвёл Greg Kroah-Hartman
Родитель 8e0c083234
Коммит 5e93f35209
17 изменённых файлов: 35551 добавлений и 0 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,718 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTW_EFUSE_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtw_efuse.h>
/*------------------------Define local variable------------------------------*/
/* */
#define REG_EFUSE_CTRL 0x0030
#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
/* */
/*-----------------------------------------------------------------------------
* Function: Efuse_PowerSwitch23a
*
* Overview: When we want to enable write operation, we should change to
* pwr on state. When we stop write, we should switch to 500k mode
* and disable LDO 2.5V.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/17/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
void
Efuse_PowerSwitch23a(
struct rtw_adapter * pAdapter,
u8 bWrite,
u8 PwrState)
{
pAdapter->HalFunc.EfusePowerSwitch(pAdapter, bWrite, PwrState);
}
/*-----------------------------------------------------------------------------
* Function: efuse_GetCurrentSize23a
*
* Overview: Get current efuse size!!!
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/16/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
u16
Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
{
u16 ret = 0;
ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType);
return ret;
}
/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
u8
Efuse_CalculateWordCnts23a(u8 word_en)
{
u8 word_cnts = 0;
if (!(word_en & BIT(0))) word_cnts++; /* 0 : write enable */
if (!(word_en & BIT(1))) word_cnts++;
if (!(word_en & BIT(2))) word_cnts++;
if (!(word_en & BIT(3))) word_cnts++;
return word_cnts;
}
/* */
/* Description: */
/* Execute E-Fuse read byte operation. */
/* Refered from SD1 Richard. */
/* */
/* Assumption: */
/* 1. Boot from E-Fuse and successfully auto-load. */
/* 2. PASSIVE_LEVEL (USB interface) */
/* */
/* Created by Roger, 2008.10.21. */
/* */
void
ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
{
u32 value32;
u8 readbyte;
u16 retry;
/* u32 start = rtw_get_current_time(); */
/* Write Address */
rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
/* Write bit 32 0 */
readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
/* Check bit 32 read-ready */
retry = 0;
value32 = rtw_read32(Adapter, EFUSE_CTRL);
/* while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) */
while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
{
value32 = rtw_read32(Adapter, EFUSE_CTRL);
retry++;
}
/* 20100205 Joseph: Add delay suggested by SD1 Victor. */
/* This fix the problem that Efuse read error in high temperature condition. */
/* Designer says that there shall be some delay after ready bit is set, or the */
/* result will always stay on last data we read. */
udelay(50);
value32 = rtw_read32(Adapter, EFUSE_CTRL);
*pbuf = (u8)(value32 & 0xff);
/* DBG_8723A("ReadEFuseByte23a _offset:%08u, in %d ms\n", _offset , rtw_get_passing_time_ms23a(start)); */
}
/* */
/* Description: */
/* 1. Execute E-Fuse read byte operation according as map offset and */
/* save to E-Fuse table. */
/* 2. Refered from SD1 Richard. */
/* */
/* Assumption: */
/* 1. Boot from E-Fuse and successfully auto-load. */
/* 2. PASSIVE_LEVEL (USB interface) */
/* */
/* Created by Roger, 2008.10.21. */
/* */
/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
/* 2. Add efuse utilization collect. */
/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
/* write addr must be after sec5. */
/* */
void
efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
u16 _offset, u16 _size_byte, u8 *pbuf);
void
efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
u16 _offset, u16 _size_byte, u8 *pbuf)
{
Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset,
_size_byte, pbuf);
}
void
EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
u8 type, void *pOut)
{
pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType,
type, pOut);
}
/*-----------------------------------------------------------------------------
* Function: EFUSE_Read1Byte23a
*
* Overview: Copy from WMAC fot EFUSE read 1 byte.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 09/23/2008 MHC Copy from WMAC.
*
*---------------------------------------------------------------------------*/
u8
EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
{
u8 data;
u8 Bytetemp = {0x00};
u8 temp = {0x00};
u32 k = 0;
u16 contentLen = 0;
EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
TYPE_EFUSE_REAL_CONTENT_LEN,
(void *)&contentLen);
if (Address < contentLen) /* E-fuse 512Byte */
{
/* Write E-fuse Register address bit0~7 */
temp = Address & 0xFF;
rtw_write8(Adapter, EFUSE_CTRL+1, temp);
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
/* Write E-fuse Register address bit8~9 */
temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
rtw_write8(Adapter, EFUSE_CTRL+2, temp);
/* Write 0x30[31]= 0 */
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
temp = Bytetemp & 0x7F;
rtw_write8(Adapter, EFUSE_CTRL+3, temp);
/* Wait Write-ready (0x30[31]= 1) */
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
while(!(Bytetemp & 0x80))
{
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
k++;
if (k == 1000)
{
k = 0;
break;
}
}
data = rtw_read8(Adapter, EFUSE_CTRL);
return data;
}
else
return 0xFF;
}/* EFUSE_Read1Byte23a */
/*-----------------------------------------------------------------------------
* Function: EFUSE_Write1Byte
*
* Overview: Copy from WMAC fot EFUSE write 1 byte.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 09/23/2008 MHC Copy from WMAC.
*
*---------------------------------------------------------------------------*/
void
EFUSE_Write1Byte(
struct rtw_adapter * Adapter,
u16 Address,
u8 Value);
void
EFUSE_Write1Byte(
struct rtw_adapter * Adapter,
u16 Address,
u8 Value)
{
u8 Bytetemp = {0x00};
u8 temp = {0x00};
u32 k = 0;
u16 contentLen = 0;
/* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
TYPE_EFUSE_REAL_CONTENT_LEN,
(void *)&contentLen);
if (Address < contentLen) /* E-fuse 512Byte */
{
rtw_write8(Adapter, EFUSE_CTRL, Value);
/* Write E-fuse Register address bit0~7 */
temp = Address & 0xFF;
rtw_write8(Adapter, EFUSE_CTRL+1, temp);
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
/* Write E-fuse Register address bit8~9 */
temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
rtw_write8(Adapter, EFUSE_CTRL+2, temp);
/* Write 0x30[31]= 1 */
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
temp = Bytetemp | 0x80;
rtw_write8(Adapter, EFUSE_CTRL+3, temp);
/* Wait Write-ready (0x30[31]= 0) */
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
while(Bytetemp & 0x80)
{
Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
k++;
if (k == 100)
{
k = 0;
break;
}
}
}
}/* EFUSE_Write1Byte */
/* 11/16/2008 MH Read one byte from real Efuse. */
u8
efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
{
u8 tmpidx = 0;
u8 bResult;
/* -----------------e-fuse reg ctrl --------------------------------- */
/* address */
rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
(rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
rtw_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
while(!(0x80 &rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
tmpidx++;
if (tmpidx < 100) {
*data = rtw_read8(pAdapter, EFUSE_CTRL);
bResult = true;
} else {
*data = 0xff;
bResult = false;
}
return bResult;
}
/* 11/16/2008 MH Write one byte to reald Efuse. */
u8
efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
{
u8 tmpidx = 0;
u8 bResult;
/* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
/* return 0; */
/* -----------------e-fuse reg ctrl --------------------------------- */
/* address */
rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
rtw_write8(pAdapter, EFUSE_CTRL+2,
(rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
while((0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100)) {
tmpidx++;
}
if (tmpidx<100)
{
bResult = true;
}
else
{
bResult = false;
}
return bResult;
}
int
Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data)
{
int ret = 0;
ret = pAdapter->HalFunc.Efuse_PgPacketRead23a(pAdapter, offset, data);
return ret;
}
int
Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset,
u8 word_en, u8 *data)
{
int ret;
ret = pAdapter->HalFunc.Efuse_PgPacketWrite23a(pAdapter, offset,
word_en, data);
return ret;
}
/*-----------------------------------------------------------------------------
* Function: efuse_WordEnableDataRead23a
*
* Overview: Read allowed word in current efuse section data.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/16/2008 MHC Create Version 0.
* 11/21/2008 MHC Fix Write bug when we only enable late word.
*
*---------------------------------------------------------------------------*/
void
efuse_WordEnableDataRead23a(u8 word_en,
u8 *sourdata,
u8 *targetdata)
{
if (!(word_en&BIT(0)))
{
targetdata[0] = sourdata[0];
targetdata[1] = sourdata[1];
}
if (!(word_en&BIT(1)))
{
targetdata[2] = sourdata[2];
targetdata[3] = sourdata[3];
}
if (!(word_en&BIT(2)))
{
targetdata[4] = sourdata[4];
targetdata[5] = sourdata[5];
}
if (!(word_en&BIT(3)))
{
targetdata[6] = sourdata[6];
targetdata[7] = sourdata[7];
}
}
u8
Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr,
u8 word_en, u8 *data)
{
u8 ret = 0;
ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr,
word_en, data);
return ret;
}
static u8 efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
{
return efuse_OneByteRead23a(padapter, address, value);
}
static u8 efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
{
return efuse_OneByteWrite23a(padapter, address, *value);
}
/*
* read/wirte raw efuse data
*/
u8 rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
u16 cnts, u8 *data)
{
int i = 0;
u16 real_content_len = 0, max_available_size = 0;
u8 res = _FAIL ;
u8 (*rw8)(struct rtw_adapter *, u16, u8*);
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_EFUSE_REAL_CONTENT_LEN,
(void *)&real_content_len);
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
(void *)&max_available_size);
if (start_addr > real_content_len)
return _FAIL;
if (true == bWrite) {
if ((start_addr + cnts) > max_available_size)
return _FAIL;
rw8 = &efuse_write8;
} else
rw8 = &efuse_read8;
Efuse_PowerSwitch23a(padapter, bWrite, true);
/* e-fuse one byte read / write */
for (i = 0; i < cnts; i++) {
if (start_addr >= real_content_len) {
res = _FAIL;
break;
}
res = rw8(padapter, start_addr++, data++);
if (_FAIL == res) break;
}
Efuse_PowerSwitch23a(padapter, bWrite, false);
return res;
}
/* */
u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
{
u16 max_size;
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
(void *)&max_size);
return max_size;
}
/* */
u8 efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size)
{
Efuse_PowerSwitch23a(padapter, false, true);
*size = Efuse_GetCurrentSize23a(padapter, EFUSE_WIFI);
Efuse_PowerSwitch23a(padapter, false, false);
return _SUCCESS;
}
/* */
u8 rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u16 mapLen = 0;
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
if ((addr + cnts) > mapLen)
return _FAIL;
Efuse_PowerSwitch23a(padapter, false, true);
efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data);
Efuse_PowerSwitch23a(padapter, false, false);
return _SUCCESS;
}
u8 rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u16 mapLen = 0;
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
if ((addr + cnts) > mapLen)
return _FAIL;
Efuse_PowerSwitch23a(padapter, false, true);
efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data);
Efuse_PowerSwitch23a(padapter, false, false);
return _SUCCESS;
}
/*-----------------------------------------------------------------------------
* Function: Efuse_ReadAllMap
*
* Overview: Read All Efuse content
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/11/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
void
Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
void
Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
{
u16 mapLen = 0;
Efuse_PowerSwitch23a(pAdapter, false, true);
EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
(void *)&mapLen);
efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
Efuse_PowerSwitch23a(pAdapter, false, false);
}
/*-----------------------------------------------------------------------------
* Function: efuse_ShadowRead1Byte
* efuse_ShadowRead2Byte
* efuse_ShadowRead4Byte
*
* Overview: Read from efuse init map by one/two/four bytes !!!!!
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/12/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
static void
efuse_ShadowRead1Byte(
struct rtw_adapter * pAdapter,
u16 Offset,
u8 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
} /* EFUSE_ShadowRead23a1Byte */
/* Read Two Bytes */
static void
efuse_ShadowRead2Byte(
struct rtw_adapter * pAdapter,
u16 Offset,
u16 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
} /* EFUSE_ShadowRead23a2Byte */
/* Read Four Bytes */
static void
efuse_ShadowRead4Byte(
struct rtw_adapter * pAdapter,
u16 Offset,
u32 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
*Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
*Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
} /* efuse_ShadowRead4Byte */
/*-----------------------------------------------------------------------------
* Function: EFUSE_ShadowMapUpdate23a
*
* Overview: Transfer current EFUSE content to shadow init and modify map.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/13/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
u16 mapLen = 0;
EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
if (pEEPROM->bautoload_fail_flag == true)
memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
else
Efuse_ReadAllMap(pAdapter, efuseType,
pEEPROM->efuse_eeprom_data);
}/* EFUSE_ShadowMapUpdate23a */
/*-----------------------------------------------------------------------------
* Function: EFUSE_ShadowRead23a
*
* Overview: Read from efuse init map !!!!!
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/12/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
void
EFUSE_ShadowRead23a(
struct rtw_adapter * pAdapter,
u8 Type,
u16 Offset,
u32 *Value )
{
if (Type == 1)
efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
else if (Type == 2)
efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
else if (Type == 4)
efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
} /* EFUSE_ShadowRead23a */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,266 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/*
The purpose of rtw_io.c
a. provides the API
b. provides the protocol engine
c. provides the software interface between caller and the hardware interface
Compiler Flag Option:
1. For USB:
a. USE_ASYNC_IRP: Both sync/async operations are provided.
Only sync read/rtw_write_mem operations are provided.
jackson@realtek.com.tw
*/
#define _RTW_IO_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtw_io.h>
#include <osdep_intf.h>
#include <usb_ops.h>
u8 _rtw_read823a(struct rtw_adapter *adapter, u32 addr)
{
u8 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
r_val = pintfhdl->io_ops._read8(pintfhdl, addr);
return r_val;
}
u16 _rtw_read1623a(struct rtw_adapter *adapter, u32 addr)
{
u16 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
r_val = pintfhdl->io_ops._read16(pintfhdl, addr);
return le16_to_cpu(r_val);
}
u32 _rtw_read3223a(struct rtw_adapter *adapter, u32 addr)
{
u32 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
r_val = pintfhdl->io_ops._read32(pintfhdl, addr);
return le32_to_cpu(r_val);
}
int _rtw_write823a(struct rtw_adapter *adapter, u32 addr, u8 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
ret = pintfhdl->io_ops._write8(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_write1623a(struct rtw_adapter *adapter, u32 addr, u16 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
val = cpu_to_le16(val);
ret = pintfhdl->io_ops._write16(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_write3223a(struct rtw_adapter *adapter, u32 addr, u32 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
val = cpu_to_le32(val);
ret = pintfhdl->io_ops._write32(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_writeN23a(struct rtw_adapter *adapter, u32 addr , u32 length , u8 *pdata)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = (struct intf_hdl*)&pio_priv->intf;
int ret;
ret = pintfhdl->io_ops._writeN(pintfhdl, addr, length, pdata);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_write823a_async23a(struct rtw_adapter *adapter, u32 addr, u8 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
ret = pintfhdl->io_ops._write8_async(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_write1623a_async(struct rtw_adapter *adapter, u32 addr, u16 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
val = cpu_to_le16(val);
ret = pintfhdl->io_ops._write16_async(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
int _rtw_write3223a_async23a(struct rtw_adapter *adapter, u32 addr, u32 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
int ret;
val = cpu_to_le32(val);
ret = pintfhdl->io_ops._write32_async(pintfhdl, addr, val);
return RTW_STATUS_CODE23a(ret);
}
void _rtw_read_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
if ((adapter->bDriverStopped == true) ||
(adapter->bSurpriseRemoved == true)) {
RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
("rtw_read_mem:bDriverStopped(%d) OR "
"bSurpriseRemoved(%d)", adapter->bDriverStopped,
adapter->bSurpriseRemoved));
return;
}
pintfhdl->io_ops._read_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_write_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
pintfhdl->io_ops._write_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_read_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
struct recv_buf *rbuf)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
if ((adapter->bDriverStopped == true) ||
(adapter->bSurpriseRemoved == true)) {
RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
("rtw_read_port:bDriverStopped(%d) OR "
"bSurpriseRemoved(%d)", adapter->bDriverStopped,
adapter->bSurpriseRemoved));
return;
}
pintfhdl->io_ops._read_port(pintfhdl, addr, cnt, rbuf);
}
void _rtw_read_port23a_cancel(struct rtw_adapter *adapter)
{
void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
_read_port_cancel = pintfhdl->io_ops._read_port_cancel;
if (_read_port_cancel)
_read_port_cancel(pintfhdl);
}
u32 _rtw_write_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
struct xmit_buf *xbuf)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
u32 ret = _SUCCESS;
ret = pintfhdl->io_ops._write_port(pintfhdl, addr, cnt, xbuf);
return ret;
}
u32 _rtw_write_port23a_and_wait23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
struct xmit_buf *pxmitbuf, int timeout_ms)
{
int ret = _SUCCESS;
struct submit_ctx sctx;
rtw_sctx_init23a(&sctx, timeout_ms);
pxmitbuf->sctx = &sctx;
ret = _rtw_write_port23a(adapter, addr, cnt, pxmitbuf);
if (ret == _SUCCESS)
ret = rtw_sctx_wait23a(&sctx);
return ret;
}
void _rtw_write_port23a_cancel(struct rtw_adapter *adapter)
{
void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &pio_priv->intf;
_write_port_cancel = pintfhdl->io_ops._write_port_cancel;
if (_write_port_cancel)
_write_port_cancel(pintfhdl);
}
int rtw_init_io_priv23a(struct rtw_adapter *padapter,
void (*set_intf_ops)(struct _io_ops *pops))
{
struct io_priv *piopriv = &padapter->iopriv;
struct intf_hdl *pintf = &piopriv->intf;
if (set_intf_ops == NULL)
return _FAIL;
piopriv->padapter = padapter;
pintf->padapter = padapter;
pintf->pintf_dev = adapter_to_dvobj(padapter);
set_intf_ops(&pintf->io_ops);
return _SUCCESS;
}

Просмотреть файл

@ -0,0 +1,601 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTW_IOCTL_SET_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtw_ioctl_set.h>
#include <hal_intf.h>
#include <usb_osintf.h>
#include <usb_ops.h>
#include <linux/ieee80211.h>
u8 rtw_do_join23a(struct rtw_adapter *padapter)
{
struct list_head *plist, *phead;
u8* pibss = NULL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct rtw_queue *queue = &pmlmepriv->scanned_queue;
u8 ret = _SUCCESS;
spin_lock_bh(&pmlmepriv->scanned_queue.lock);
phead = get_list_head(queue);
plist = phead->next;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("\n rtw_do_join23a: phead = %p; plist = %p\n\n\n",
phead, plist));
pmlmepriv->cur_network.join_res = -2;
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
pmlmepriv->to_join = true;
if (_rtw_queue_empty23a(queue) == true) {
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
/* when set_ssid/set_bssid for rtw_do_join23a(), but
scanning queue is empty */
/* we try to issue sitesurvey firstly */
if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false ||
rtw_to_roaming(padapter) > 0) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("rtw_do_join23a(): site survey if scanned_queue "
"is empty\n."));
/* submit site_survey23a_cmd */
ret = rtw_sitesurvey_cmd23a(padapter,
&pmlmepriv->assoc_ssid, 1,
NULL, 0);
if (ret != _SUCCESS) {
pmlmepriv->to_join = false;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("rtw_do_join23a(): site survey return "
"error\n."));
}
} else {
pmlmepriv->to_join = false;
ret = _FAIL;
}
goto exit;
} else {
int select_ret;
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
select_ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
if (select_ret == _SUCCESS) {
pmlmepriv->to_join = false;
mod_timer(&pmlmepriv->assoc_timer,
jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
} else {
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
struct wlan_bssid_ex *pdev_network;
/* submit createbss_cmd to change to a
ADHOC_MASTER */
/* pmlmepriv->lock has been acquired by
caller... */
pdev_network =
&padapter->registrypriv.dev_network;
pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
pibss = padapter->registrypriv.dev_network.MacAddress;
memcpy(&pdev_network->Ssid,
&pmlmepriv->assoc_ssid,
sizeof(struct cfg80211_ssid));
rtw_update_registrypriv_dev_network23a(padapter);
rtw_generate_random_ibss23a(pibss);
if (rtw_createbss_cmd23a(padapter) != _SUCCESS) {
RT_TRACE(_module_rtl871x_ioctl_set_c_,
_drv_err_,
("***Error =>do_goin: rtw_creat"
"ebss_cmd status FAIL***\n"));
ret = false;
goto exit;
}
pmlmepriv->to_join = false;
RT_TRACE(_module_rtl871x_ioctl_set_c_,
_drv_info_,
("***Error => rtw_select_and_join_from"
"_scanned_queue FAIL under STA_Mode"
"***\n "));
} else {
/* can't associate ; reset under-linking */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
/* when set_ssid/set_bssid for rtw_do_join23a(),
but there are no desired bss in scanning
queue */
/* we try to issue sitesurvey firstly */
if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==
false || rtw_to_roaming(padapter) > 0) {
/* DBG_8723A("rtw_do_join23a() when no "
"desired bss in scanning queue\n");
*/
ret = rtw_sitesurvey_cmd23a(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
if (ret != _SUCCESS) {
pmlmepriv->to_join = false;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
}
} else {
ret = _FAIL;
pmlmepriv->to_join = false;
}
}
}
}
exit:
return ret;
}
u8 rtw_set_802_11_ssid23a(struct rtw_adapter* padapter, struct cfg80211_ssid *ssid)
{
u8 status = _SUCCESS;
u32 cur_time = 0;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *pnetwork = &pmlmepriv->cur_network;
DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
ssid->ssid, get_fwstate(pmlmepriv));
if (padapter->hw_init_completed == false) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("set_ssid: hw_init_completed == false =>exit!!!\n"));
status = _FAIL;
goto exit;
}
spin_lock_bh(&pmlmepriv->lock);
DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
goto handle_tkip_countermeasure;
} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
goto release_mlme_lock;
}
if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true)
{
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
if ((pmlmepriv->assoc_ssid.ssid_len == ssid->ssid_len) &&
!memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid,
ssid->ssid_len)) {
if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false))
{
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("Set SSID is the same ssid, fw_state = 0x%08x\n",
get_fwstate(pmlmepriv)));
if (rtw_is_same_ibss23a(padapter, pnetwork) == false)
{
/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
rtw_disassoc_cmd23a(padapter, 0, true);
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
rtw_indicate_disconnect23a(padapter);
rtw_free_assoc_resources23a(padapter, 1);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
} else {
goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
}
} else {
rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_JOINBSS, 1);
}
} else {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("Set SSID not the same ssid\n"));
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("set_ssid =[%s] len = 0x%x\n", ssid->ssid,
(unsigned int)ssid->ssid_len));
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("assoc_ssid =[%s] len = 0x%x\n",
pmlmepriv->assoc_ssid.ssid,
(unsigned int)pmlmepriv->assoc_ssid.ssid_len));
rtw_disassoc_cmd23a(padapter, 0, true);
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
rtw_indicate_disconnect23a(padapter);
rtw_free_assoc_resources23a(padapter, 1);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
}
}
handle_tkip_countermeasure:
if (padapter->securitypriv.btkip_countermeasure == true) {
cur_time = jiffies;
if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ)
{
padapter->securitypriv.btkip_countermeasure = false;
padapter->securitypriv.btkip_countermeasure_time = 0;
}
else
{
status = _FAIL;
goto release_mlme_lock;
}
}
memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct cfg80211_ssid));
pmlmepriv->assoc_by_bssid = false;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
pmlmepriv->to_join = true;
}
else {
status = rtw_do_join23a(padapter);
}
release_mlme_lock:
spin_unlock_bh(&pmlmepriv->lock);
exit:
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("-rtw_set_802_11_ssid23a: status =%d\n", status));
return status;
}
u8 rtw_set_802_11_infrastructure_mode23a(struct rtw_adapter* padapter,
enum ndis_802_11_net_infra networktype)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
enum ndis_802_11_net_infra* pold_state = &cur_network->network.InfrastructureMode;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
("+rtw_set_802_11_infrastructure_mode23a: old =%d new =%d fw_state = 0x%08x\n",
*pold_state, networktype, get_fwstate(pmlmepriv)));
if (*pold_state != networktype)
{
spin_lock_bh(&pmlmepriv->lock);
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
/* DBG_8723A("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
if (*pold_state == Ndis802_11APMode)
{
/* change to other mode from Ndis802_11APMode */
cur_network->join_res = -1;
#ifdef CONFIG_8723AU_AP_MODE
stop_ap_mode23a(padapter);
#endif
}
if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||(*pold_state == Ndis802_11IBSS))
rtw_disassoc_cmd23a(padapter, 0, true);
if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
rtw_free_assoc_resources23a(padapter, 1);
if ((*pold_state == Ndis802_11Infrastructure) ||(*pold_state == Ndis802_11IBSS))
{
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
{
rtw_indicate_disconnect23a(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
}
}
*pold_state = networktype;
_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
switch (networktype)
{
case Ndis802_11IBSS:
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
break;
case Ndis802_11Infrastructure:
set_fwstate(pmlmepriv, WIFI_STATION_STATE);
break;
case Ndis802_11APMode:
set_fwstate(pmlmepriv, WIFI_AP_STATE);
#ifdef CONFIG_8723AU_AP_MODE
start_ap_mode23a(padapter);
/* rtw_indicate_connect23a(padapter); */
#endif
break;
case Ndis802_11AutoUnknown:
case Ndis802_11InfrastructureMax:
break;
}
/* SecClearAllKeys(adapter); */
/* RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", */
/* get_fwstate(pmlmepriv))); */
spin_unlock_bh(&pmlmepriv->lock);
}
return true;
}
u8 rtw_set_802_11_bssid23a_list_scan(struct rtw_adapter *padapter,
struct cfg80211_ssid *pssid, int ssid_max_num)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 res = true;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("+rtw_set_802_11_bssid23a_list_scan(), fw_state =%x\n",
get_fwstate(pmlmepriv)));
if (!padapter) {
res = false;
goto exit;
}
if (padapter->hw_init_completed == false) {
res = false;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("\n === rtw_set_802_11_bssid23a_list_scan:"
"hw_init_completed == false ===\n"));
goto exit;
}
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
(pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
/* Scan or linking is in progress, do nothing. */
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("rtw_set_802_11_bssid23a_list_scan fail since fw_state "
"= %x\n", get_fwstate(pmlmepriv)));
res = true;
if (check_fwstate(pmlmepriv,
(_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n"));
} else {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("\n###pmlmepriv->sitesurveyctrl.traffic_"
"busy == true\n"));
}
} else {
if (rtw_is_scan_deny(padapter)) {
DBG_8723A(FUNC_ADPT_FMT": scan deny\n",
FUNC_ADPT_ARG(padapter));
return _SUCCESS;
}
spin_lock_bh(&pmlmepriv->lock);
res = rtw_sitesurvey_cmd23a(padapter, pssid, ssid_max_num,
NULL, 0);
spin_unlock_bh(&pmlmepriv->lock);
}
exit:
return res;
}
u8 rtw_set_802_11_authentication_mode23a(struct rtw_adapter* padapter,
enum ndis_802_11_auth_mode authmode)
{
struct security_priv *psecuritypriv = &padapter->securitypriv;
int res;
u8 ret;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("set_802_11_auth.mode(): mode =%x\n", authmode));
psecuritypriv->ndisauthtype = authmode;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("rtw_set_802_11_authentication_mode23a:"
"psecuritypriv->ndisauthtype =%d",
psecuritypriv->ndisauthtype));
if (psecuritypriv->ndisauthtype > 3)
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
res = rtw_set_auth23a(padapter, psecuritypriv);
if (res == _SUCCESS)
ret = true;
else
ret = false;
return ret;
}
u8 rtw_set_802_11_add_wep23a(struct rtw_adapter* padapter,
struct ndis_802_11_wep *wep)
{
u8 bdefaultkey;
u8 btransmitkey;
int keyid, res;
struct security_priv *psecuritypriv = &padapter->securitypriv;
u8 ret = _SUCCESS;
bdefaultkey = (wep->KeyIndex & 0x40000000) > 0 ? false : true;
btransmitkey = (wep->KeyIndex & 0x80000000) > 0 ? true : false;
keyid = wep->KeyIndex & 0x3fffffff;
if (keyid >= 4) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("MgntActrtw_set_802_11_add_wep23a:keyid>4 =>fail\n"));
ret = false;
goto exit;
}
switch (wep->KeyLength)
{
case 5:
psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 5\n"));
break;
case 13:
psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 13\n"));
break;
default:
psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength!= 5 "
"or 13\n"));
break;
}
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("rtw_set_802_11_add_wep23a:befor memcpy, wep->KeyLength = 0x%x "
"wep->KeyIndex = 0x%x keyid =%x\n",
wep->KeyLength, wep->KeyIndex, keyid));
memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
&wep->KeyMaterial, wep->KeyLength);
psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
psecuritypriv->dot11PrivacyKeyIndex = keyid;
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("rtw_set_802_11_add_wep23a:security key material : %x %x %x %x "
"%x %x %x %x %x %x %x %x %x\n",
psecuritypriv->dot11DefKey[keyid].skey[0],
psecuritypriv->dot11DefKey[keyid].skey[1],
psecuritypriv->dot11DefKey[keyid].skey[2],
psecuritypriv->dot11DefKey[keyid].skey[3],
psecuritypriv->dot11DefKey[keyid].skey[4],
psecuritypriv->dot11DefKey[keyid].skey[5],
psecuritypriv->dot11DefKey[keyid].skey[6],
psecuritypriv->dot11DefKey[keyid].skey[7],
psecuritypriv->dot11DefKey[keyid].skey[8],
psecuritypriv->dot11DefKey[keyid].skey[9],
psecuritypriv->dot11DefKey[keyid].skey[10],
psecuritypriv->dot11DefKey[keyid].skey[11],
psecuritypriv->dot11DefKey[keyid].skey[12]));
res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
if (res == _FAIL)
ret = false;
exit:
return ret;
}
/*
* rtw_get_cur_max_rate23a -
* @adapter: pointer to _adapter structure
*
* Return 0 or 100Kbps
*/
u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
{
int i = 0;
u8 *p;
u16 rate = 0, max_rate = 0;
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct registry_priv *pregistrypriv = &adapter->registrypriv;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
struct ieee80211_ht_cap *pht_capie;
u8 rf_type = 0;
u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
u16 mcs_rate = 0;
u32 ht_ielen = 0;
if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
return 0;
if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
p = rtw_get_ie23a(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
&ht_ielen, pcur_bss->IELength - 12);
if (p && ht_ielen > 0) {
pht_capie = (struct ieee80211_ht_cap *)(p + 2);
memcpy(&mcs_rate, &pht_capie->mcs, 2);
/* bw_40MHz = (pht_capie->cap_info&
IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
/* cur_bwmod is updated by beacon, pmlmeinfo is
updated by association response */
bw_40MHz = (pmlmeext->cur_bwmode &&
(HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH &
pmlmeinfo->HT_info.infos[0])) ? 1:0;
/* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
short_GI_20 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_20) ? 1:0;
short_GI_40 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_40) ? 1:0;
rtw23a_hal_get_hwreg(adapter, HW_VAR_RF_TYPE,
(u8 *)(&rf_type));
max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
pregistrypriv->cbw40_enable,
short_GI_20, short_GI_40,
pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
);
}
} else {
while ((pcur_bss->SupportedRates[i] != 0) &&
(pcur_bss->SupportedRates[i] != 0xFF)) {
rate = pcur_bss->SupportedRates[i] & 0x7F;
if (rate>max_rate)
max_rate = rate;
i++;
}
max_rate = max_rate * 10 / 2;
}
return max_rate;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,686 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTW_PWRCTRL_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <osdep_intf.h>
#ifdef CONFIG_8723AU_BT_COEXIST
#include <rtl8723a_hal.h>
#endif
void ips_enter23a(struct rtw_adapter * padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
down(&pwrpriv->lock);
pwrpriv->bips_processing = true;
/* syn ips_mode with request */
pwrpriv->ips_mode = pwrpriv->ips_mode_req;
pwrpriv->ips_enter23a_cnts++;
DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts);
#ifdef CONFIG_8723AU_BT_COEXIST
BTDM_TurnOffBtCoexistBeforeEnterIPS(padapter);
#endif
if (rf_off == pwrpriv->change_rfpwrstate)
{
pwrpriv->bpower_saving = true;
DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n");
if (pwrpriv->ips_mode == IPS_LEVEL_2)
pwrpriv->bkeepfwalive = true;
rtw_ips_pwr_down23a(padapter);
pwrpriv->rf_pwrstate = rf_off;
}
pwrpriv->bips_processing = false;
up(&pwrpriv->lock);
}
int ips_leave23a(struct rtw_adapter * padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int result = _SUCCESS;
int keyid;
down(&pwrpriv->lock);
if ((pwrpriv->rf_pwrstate == rf_off) &&!pwrpriv->bips_processing)
{
pwrpriv->bips_processing = true;
pwrpriv->change_rfpwrstate = rf_on;
pwrpriv->ips_leave23a_cnts++;
DBG_8723A("==>ips_leave23a cnts:%d\n", pwrpriv->ips_leave23a_cnts);
if ((result = rtw_ips_pwr_up23a(padapter)) == _SUCCESS) {
pwrpriv->rf_pwrstate = rf_on;
}
DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n");
if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm))
{
DBG_8723A("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
set_channel_bwmode23a(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
for (keyid = 0;keyid<4;keyid++) {
if (pmlmepriv->key_mask & CHKBIT(keyid)) {
if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
else
result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0);
}
}
}
DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
pwrpriv->bips_processing = false;
pwrpriv->bkeepfwalive = false;
pwrpriv->bpower_saving = false;
}
up(&pwrpriv->lock);
return result;
}
static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter)
{
struct rtw_adapter *buddy = adapter->pbuddy_adapter;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
#ifdef CONFIG_8723AU_P2P
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
#endif
bool ret = false;
if (adapter->pwrctrlpriv.ips_deny_time >= rtw_get_current_time())
goto exit;
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
|| check_fwstate(pmlmepriv, WIFI_AP_STATE)
|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
|| !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
) {
goto exit;
}
/* consider buddy, if exist */
if (buddy) {
struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
#ifdef CONFIG_8723AU_P2P
struct wifidirect_info *b_pwdinfo = &buddy->wdinfo;
#endif
if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
|| check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
|| check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
|| check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
|| !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
) {
goto exit;
}
}
if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
DBG_8723A_LEVEL(_drv_always_, "There are some pkts to transmit\n");
DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
goto exit;
}
ret = true;
exit:
return ret;
}
void rtw_ps_processor23a(struct rtw_adapter*padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
enum rt_rf_power_state rfpwrstate;
pwrpriv->ps_processing = true;
if (pwrpriv->bips_processing == true)
goto exit;
if (padapter->pwrctrlpriv.bHWPwrPindetect) {
rfpwrstate = RfOnOffDetect23a(padapter);
DBG_8723A("@@@@- #2 %s ==> rfstate:%s\n", __func__, (rfpwrstate == rf_on)?"rf_on":"rf_off");
if (rfpwrstate!= pwrpriv->rf_pwrstate) {
if (rfpwrstate == rf_off) {
pwrpriv->change_rfpwrstate = rf_off;
pwrpriv->brfoffbyhw = true;
padapter->bCardDisableWOHSM = true;
rtw_hw_suspend23a(padapter);
} else {
pwrpriv->change_rfpwrstate = rf_on;
rtw_hw_resume23a(padapter);
}
DBG_8723A("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
}
pwrpriv->pwr_state_check_cnts ++;
}
if (pwrpriv->ips_mode_req == IPS_NONE)
goto exit;
if (rtw_pwr_unassociated_idle(padapter) == false)
goto exit;
if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0))
{
DBG_8723A("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
pwrpriv->change_rfpwrstate = rf_off;
ips_enter23a(padapter);
}
exit:
rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
pwrpriv->ps_processing = false;
return;
}
static void pwr_state_check_handler(unsigned long data)
{
struct rtw_adapter *padapter = (struct rtw_adapter *)data;
rtw_ps_cmd23a(padapter);
}
/*
*
* Parameters
* padapter
* pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
*
*/
void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
{
u8 rpwm;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
pslv = PS_STATE(pslv);
if (true == pwrpriv->btcoex_rfon)
{
if (pslv < PS_STATE_S4)
pslv = PS_STATE_S3;
}
if (pwrpriv->rpwm == pslv) {
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
return;
}
if ((padapter->bSurpriseRemoved == true) ||
(padapter->hw_init_completed == false)) {
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
__func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
pwrpriv->cpwm = PS_STATE_S4;
return;
}
if (padapter->bDriverStopped == true) {
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
if (pslv < PS_STATE_S2) {
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
return;
}
}
rpwm = pslv | pwrpriv->tog;
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
("rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm));
pwrpriv->rpwm = pslv;
rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
pwrpriv->tog += 0x80;
pwrpriv->cpwm = pslv;
}
u8 PS_RDY_CHECK(struct rtw_adapter * padapter)
{
unsigned long delta_time;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp;
if (delta_time < LPS_DELAY_TIME)
{
return false;
}
if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) ||
(check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
return false;
if (true == pwrpriv->bInSuspend)
return false;
if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false))
{
DBG_8723A("Group handshake still in progress !!!\n");
return false;
}
if (!rtw_cfg80211_pwr_mgmt(padapter))
return false;
return true;
}
void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
#ifdef CONFIG_8723AU_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
#endif /* CONFIG_8723AU_P2P */
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
("%s: PowerMode =%d Smart_PS =%d\n",
__func__, ps_mode, smart_ps));
if (ps_mode > PM_Card_Disable) {
RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
return;
}
if (pwrpriv->pwr_mode == ps_mode)
{
if (PS_MODE_ACTIVE == ps_mode) return;
if ((pwrpriv->smart_ps == smart_ps) &&
(pwrpriv->bcn_ant_mode == bcn_ant_mode))
{
return;
}
}
if (ps_mode == PS_MODE_ACTIVE) {
#ifdef CONFIG_8723AU_P2P
if (pwdinfo->opp_ps == 0)
#endif /* CONFIG_8723AU_P2P */
{
DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n");
pwrpriv->pwr_mode = ps_mode;
rtw_set_rpwm23a(padapter, PS_STATE_S4);
rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
pwrpriv->bFwCurrentInPSMode = false;
}
}
else
{
if (PS_RDY_CHECK(padapter)
#ifdef CONFIG_8723AU_BT_COEXIST
|| (BT_1Ant(padapter) == true)
#endif
)
{
DBG_8723A("%s: Enter 802.11 power save\n", __func__);
pwrpriv->bFwCurrentInPSMode = true;
pwrpriv->pwr_mode = ps_mode;
pwrpriv->smart_ps = smart_ps;
pwrpriv->bcn_ant_mode = bcn_ant_mode;
rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
#ifdef CONFIG_8723AU_P2P
/* Set CTWindow after LPS */
if (pwdinfo->opp_ps == 1)
p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 0);
#endif /* CONFIG_8723AU_P2P */
rtw_set_rpwm23a(padapter, PS_STATE_S2);
}
}
}
/*
* Return:
* 0: Leave OK
* -1: Timeout
* -2: Other error
*/
s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms)
{
u32 start_time;
u8 bAwake = false;
s32 err = 0;
start_time = rtw_get_current_time();
while (1)
{
rtw23a_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
if (true == bAwake)
break;
if (true == padapter->bSurpriseRemoved)
{
err = -2;
DBG_8723A("%s: device surprise removed!!\n", __func__);
break;
}
if (rtw_get_passing_time_ms23a(start_time) > delay_ms)
{
err = -1;
DBG_8723A("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
break;
}
udelay(100);
}
return err;
}
/* Description: */
/* Enter the leisure power save mode. */
void LPS_Enter23a(struct rtw_adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (!PS_RDY_CHECK(padapter))
return;
if (pwrpriv->bLeisurePs) {
/* Idle for a while if we connect to AP a while ago. */
if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
pwrpriv->bpower_saving = true;
DBG_8723A("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
/* For Tenda W311R IOT issue */
rtw_set_ps_mode23a(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
}
} else {
pwrpriv->LpsIdleCount++;
}
}
}
/* Description: */
/* Leave the leisure power save mode. */
void LPS_Leave23a(struct rtw_adapter *padapter)
{
#define LPS_LEAVE_TIMEOUT_MS 100
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (pwrpriv->bLeisurePs) {
if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0);
if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
LPS_RF_ON_check23a(padapter, LPS_LEAVE_TIMEOUT_MS);
}
}
pwrpriv->bpower_saving = false;
}
/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
/* Move code to function by tynli. 2010.03.26. */
void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter)
{
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
u8 enqueue = 0;
/* DBG_8723A("%s.....\n", __func__); */
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
{ /* connect */
#ifdef CONFIG_8723AU_P2P
p2p_ps_wk_cmd23a(Adapter, P2P_PS_DISABLE, enqueue);
#endif /* CONFIG_8723AU_P2P */
rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue);
}
}
void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter)
{
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
sema_init(&pwrctrlpriv->lock, 1);
pwrctrlpriv->rf_pwrstate = rf_on;
pwrctrlpriv->ips_enter23a_cnts = 0;
pwrctrlpriv->ips_leave23a_cnts = 0;
pwrctrlpriv->bips_processing = false;
pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
pwrctrlpriv->pwr_state_check_cnts = 0;
pwrctrlpriv->bInternalAutoSuspend = false;
pwrctrlpriv->bInSuspend = false;
pwrctrlpriv->bkeepfwalive = false;
pwrctrlpriv->LpsIdleCount = 0;
pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
pwrctrlpriv->bFwCurrentInPSMode = false;
pwrctrlpriv->rpwm = 0;
pwrctrlpriv->cpwm = PS_STATE_S4;
pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
pwrctrlpriv->bcn_ant_mode = 0;
pwrctrlpriv->tog = 0x80;
pwrctrlpriv->btcoex_rfon = false;
setup_timer(&pwrctrlpriv->pwr_state_check_timer,
pwr_state_check_handler, (unsigned long)padapter);
}
void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter)
{
}
u8 rtw_interface_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8* val)
{
u8 bResult = true;
rtw_hal_intf_ps_func23a(padapter, efunc_id, val);
return bResult;
}
inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ms);
}
/*
* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
* @adapter: pointer to _adapter structure
* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
* Return _SUCCESS or _FAIL
*/
int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int ret = _SUCCESS;
u32 start = rtw_get_current_time();
if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms))
pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms);
if (pwrpriv->ps_processing) {
DBG_8723A("%s wait ps_processing...\n", __func__);
while (pwrpriv->ps_processing && rtw_get_passing_time_ms23a(start) <= 3000)
msleep(10);
if (pwrpriv->ps_processing)
DBG_8723A("%s wait ps_processing timeout\n", __func__);
else
DBG_8723A("%s wait ps_processing done\n", __func__);
}
if (rtw_hal_sreset_inprogress(padapter)) {
DBG_8723A("%s wait sreset_inprogress...\n", __func__);
while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms23a(start) <= 4000)
msleep(10);
if (rtw_hal_sreset_inprogress(padapter))
DBG_8723A("%s wait sreset_inprogress timeout\n", __func__);
else
DBG_8723A("%s wait sreset_inprogress done\n", __func__);
}
if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
DBG_8723A("%s wait bInSuspend...\n", __func__);
while (pwrpriv->bInSuspend &&
(rtw_get_passing_time_ms23a(start) <= 3000)) {
msleep(10);
}
if (pwrpriv->bInSuspend)
DBG_8723A("%s wait bInSuspend timeout\n", __func__);
else
DBG_8723A("%s wait bInSuspend done\n", __func__);
}
/* System suspend is not allowed to wakeup */
if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
ret = _FAIL;
goto exit;
}
/* block??? */
if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) {
ret = _FAIL;
goto exit;
}
/* I think this should be check in IPS, LPS, autosuspend functions... */
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
{
ret = _SUCCESS;
goto exit;
}
if (rf_off == pwrpriv->rf_pwrstate) {
DBG_8723A("%s call ips_leave23a....\n", __func__);
if (_FAIL == ips_leave23a(padapter)) {
DBG_8723A("======> ips_leave23a fail.............\n");
ret = _FAIL;
goto exit;
}
}
/* TODO: the following checking need to be merged... */
if (padapter->bDriverStopped || !padapter->bup ||
!padapter->hw_init_completed) {
DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed "
"=%u\n", caller, padapter->bDriverStopped,
padapter->bup, padapter->hw_init_completed);
ret = false;
goto exit;
}
exit:
if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms))
pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms);
return ret;
}
int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode)
{
int ret = 0;
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
if (mode < PS_MODE_NUM)
{
if (pwrctrlpriv->power_mgnt != mode)
{
if (PS_MODE_ACTIVE == mode)
{
LeaveAllPowerSaveMode23a(padapter);
}
else
{
pwrctrlpriv->LpsIdleCount = 2;
}
pwrctrlpriv->power_mgnt = mode;
pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
}
}
else
{
ret = -EINVAL;
}
return ret;
}
int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode)
{
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
rtw_ips_mode_req(pwrctrlpriv, mode);
DBG_8723A("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
return 0;
}
else if (mode == IPS_NONE) {
rtw_ips_mode_req(pwrctrlpriv, mode);
DBG_8723A("%s %s\n", __func__, "IPS_NONE");
if ((padapter->bSurpriseRemoved == 0)&&_FAIL == rtw_pwr_wakeup(padapter))
return -EFAULT;
}
else {
return -EINVAL;
}
return 0;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,253 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include<rtw_sreset.h>
void sreset_init_value23a(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
mutex_init(&psrtpriv->silentreset_mutex);
psrtpriv->silent_reset_inprogress = false;
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
psrtpriv->last_tx_time = 0;
psrtpriv->last_tx_complete_time = 0;
}
void sreset_reset_value23a(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
psrtpriv->silent_reset_inprogress = false;
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
psrtpriv->last_tx_time = 0;
psrtpriv->last_tx_complete_time = 0;
}
u8 sreset_get_wifi_status23a(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
u8 status = WIFI_STATUS_SUCCESS;
u32 val32 = 0;
if (psrtpriv->silent_reset_inprogress)
return status;
val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
if (val32 == 0xeaeaeaea) {
psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
} else if (val32 != 0) {
DBG_8723A("txdmastatu(%x)\n", val32);
psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
}
if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
DBG_8723A("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
status = (psrtpriv->Wifi_Error_Status &~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
}
DBG_8723A("==> %s wifi_status(0x%x)\n", __func__, status);
/* status restore */
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
return status;
}
void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status = status;
}
void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.dbg_trigger_point = tgp;
}
bool sreset_inprogress(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
return pHalData->srestpriv.silent_reset_inprogress;
}
static void sreset_restore_security_station(struct rtw_adapter *padapter)
{
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta;
struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
u8 val8;
if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
val8 = 0xcc;
else
val8 = 0xcf;
rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
if (psta == NULL) {
/* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
} else {
/* pairwise key */
rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
/* group key */
rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
}
}
}
static void sreset_restore_network_station(struct rtw_adapter *padapter)
{
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
u8 threshold;
rtw_setopmode_cmd23a(padapter, Ndis802_11Infrastructure);
/* TH = 1 => means that invalidate usb rx aggregation */
/* TH = 0 => means that validate usb rx aggregation, use init value. */
if (mlmepriv->htpriv.ht_option) {
if (padapter->registrypriv.wifi_spec == 1)
threshold = 1;
else
threshold = 0;
rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
} else {
threshold = 1;
rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
}
set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
/* disable dynamic functions, such as high power, DIG */
/* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
{
u8 join_type = 0;
rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
}
Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
mlmeext_joinbss_event_callback23a(padapter, 1);
/* restore Sequence No. */
rtw_write8(padapter, 0x4dc, padapter->xmitpriv.nqos_ssn);
sreset_restore_security_station(padapter);
}
static void sreset_restore_network_status(struct rtw_adapter *padapter)
{
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
sreset_restore_network_station(padapter);
} else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
rtw_ap_restore_network(padapter);
} else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
} else {
DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
}
}
static void sreset_stop_adapter(struct rtw_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (padapter == NULL)
return;
DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
if (!rtw_netif_queue_stopped(padapter->pnetdev))
netif_tx_stop_all_queues(padapter->pnetdev);
rtw_cancel_all_timer23a(padapter);
/* TODO: OS and HCI independent */
tasklet_kill(&pxmitpriv->xmit_tasklet);
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
rtw_scan_abort23a(padapter);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
rtw23a_join_to_handler((unsigned long)padapter);
}
static void sreset_start_adapter(struct rtw_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (padapter == NULL)
return;
DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
sreset_restore_network_status(padapter);
}
/* TODO: OS and HCI independent */
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
jiffies + msecs_to_jiffies(2000));
if (rtw_netif_queue_stopped(padapter->pnetdev))
netif_tx_wake_all_queues(padapter->pnetdev);
}
void sreset_reset(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
unsigned long start = jiffies;
DBG_8723A("%s\n", __func__);
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
mutex_lock(&psrtpriv->silentreset_mutex);
psrtpriv->silent_reset_inprogress = true;
pwrpriv->change_rfpwrstate = rf_off;
sreset_stop_adapter(padapter);
ips_enter23a(padapter);
ips_leave23a(padapter);
sreset_start_adapter(padapter);
psrtpriv->silent_reset_inprogress = false;
mutex_unlock(&psrtpriv->silentreset_mutex);
DBG_8723A("%s done in %d ms\n", __func__,
jiffies_to_msecs(jiffies - start));
}

Просмотреть файл

@ -0,0 +1,509 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTW_STA_MGT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <xmit_osdep.h>
#include <mlme_osdep.h>
#include <sta_info.h>
void _rtw_init_stainfo(struct sta_info *psta)
{
memset((u8 *)psta, 0, sizeof (struct sta_info));
spin_lock_init(&psta->lock);
INIT_LIST_HEAD(&psta->list);
INIT_LIST_HEAD(&psta->hash_list);
_rtw_init_queue23a(&psta->sleep_q);
psta->sleepq_len = 0;
_rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv);
_rtw_init_sta_recv_priv23a(&psta->sta_recvpriv);
#ifdef CONFIG_8723AU_AP_MODE
INIT_LIST_HEAD(&psta->asoc_list);
INIT_LIST_HEAD(&psta->auth_list);
psta->expire_to = 0;
psta->flags = 0;
psta->capability = 0;
psta->bpairwise_key_installed = false;
psta->nonerp_set = 0;
psta->no_short_slot_time_set = 0;
psta->no_short_preamble_set = 0;
psta->no_ht_gf_set = 0;
psta->no_ht_set = 0;
psta->ht_20mhz_set = 0;
psta->keep_alive_trycnt = 0;
#endif /* CONFIG_8723AU_AP_MODE */
}
u32 _rtw_init_sta_priv23a(struct sta_priv *pstapriv)
{
struct sta_info *psta;
s32 i;
pstapriv->pallocated_stainfo_buf = rtw_zvmalloc(sizeof(struct sta_info) * NUM_STA+ 4);
if (!pstapriv->pallocated_stainfo_buf)
return _FAIL;
pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
((unsigned long)(pstapriv->pallocated_stainfo_buf) & 3);
_rtw_init_queue23a(&pstapriv->free_sta_queue);
spin_lock_init(&pstapriv->sta_hash_lock);
pstapriv->asoc_sta_count = 0;
_rtw_init_queue23a(&pstapriv->sleep_q);
_rtw_init_queue23a(&pstapriv->wakeup_q);
psta = (struct sta_info *)(pstapriv->pstainfo_buf);
for (i = 0; i < NUM_STA; i++) {
_rtw_init_stainfo(psta);
INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
psta++;
}
#ifdef CONFIG_8723AU_AP_MODE
pstapriv->sta_dz_bitmap = 0;
pstapriv->tim_bitmap = 0;
INIT_LIST_HEAD(&pstapriv->asoc_list);
INIT_LIST_HEAD(&pstapriv->auth_list);
spin_lock_init(&pstapriv->asoc_list_lock);
spin_lock_init(&pstapriv->auth_list_lock);
pstapriv->asoc_list_cnt = 0;
pstapriv->auth_list_cnt = 0;
pstapriv->auth_to = 3; /* 3*2 = 6 sec */
pstapriv->assoc_to = 3;
/* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, expire after no any traffic. */
/* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, expire after no any traffic. */
pstapriv->expire_to = 3; /* 3*2 = 6 sec */
pstapriv->max_num_sta = NUM_STA;
#endif
return _SUCCESS;
}
inline int rtw_stainfo_offset23a(struct sta_priv *stapriv, struct sta_info *sta)
{
int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
if (!stainfo_offset_valid(offset))
DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
return offset;
}
inline struct sta_info *rtw_get_stainfo23a_by_offset23a(struct sta_priv *stapriv, int offset)
{
if (!stainfo_offset_valid(offset))
DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
}
/* this function is used to free the memory of lock || sema for all stainfos */
void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
{
struct list_head *plist, *phead;
struct sta_info *psta;
spin_lock_bh(&pstapriv->sta_hash_lock);
phead = get_list_head(&pstapriv->free_sta_queue);
/* we really achieve a lot in this loop .... */
list_for_each(plist, phead)
psta = container_of(plist, struct sta_info, list);
spin_unlock_bh(&pstapriv->sta_hash_lock);
}
void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
{
rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
}
u32 _rtw_free_sta_priv23a(struct sta_priv *pstapriv)
{
struct list_head *phead, *plist, *ptmp;
struct sta_info *psta;
struct recv_reorder_ctrl *preorder_ctrl;
int index;
if (pstapriv) {
/* delete all reordering_ctrl_timer */
spin_lock_bh(&pstapriv->sta_hash_lock);
for (index = 0; index < NUM_STA; index++) {
phead = &pstapriv->sta_hash[index];
list_for_each_safe(plist, ptmp, phead) {
int i;
psta = container_of(plist, struct sta_info,
hash_list);
for (i = 0; i < 16 ; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
}
}
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
/*===============================*/
rtw_mfree_sta_priv_lock(pstapriv);
if (pstapriv->pallocated_stainfo_buf)
rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
}
return _SUCCESS;
}
struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
{
struct list_head *phash_list;
struct sta_info *psta;
struct rtw_queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
uint tmp_aid;
s32 index;
int i = 0;
u16 wRxSeqInitialValue = 0xffff;
pfree_sta_queue = &pstapriv->free_sta_queue;
spin_lock_bh(&pstapriv->sta_hash_lock);
if (_rtw_queue_empty23a(pfree_sta_queue)) {
spin_unlock_bh(&pstapriv->sta_hash_lock);
return NULL;
}
psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
list_del_init(&psta->list);
tmp_aid = psta->aid;
_rtw_init_stainfo(psta);
psta->padapter = pstapriv->padapter;
memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
index = wifi_mac_hash(hwaddr);
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
("rtw_alloc_stainfo23a: index = %x", index));
if (index >= NUM_STA) {
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
psta = NULL;
goto exit;
}
phash_list = &pstapriv->sta_hash[index];
list_add_tail(&psta->hash_list, phash_list);
pstapriv->asoc_sta_count ++ ;
/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
/* So, we initialize the tid_rxseq variable as the 0xffff. */
for (i = 0; i < 16; i++)
memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
("alloc number_%d stainfo with hwaddr = %pM\n",
pstapriv->asoc_sta_count, hwaddr));
init_addba_retry_timer23a(psta);
/* for A-MPDU Rx reordering buffer control */
for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
preorder_ctrl->padapter = pstapriv->padapter;
preorder_ctrl->enable = false;
preorder_ctrl->indicate_seq = 0xffff;
preorder_ctrl->wend_b = 0xffff;
/* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
preorder_ctrl->wsize_b = 64;/* 64; */
_rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue);
rtw_init_recv_timer23a(preorder_ctrl);
}
/* init for DM */
psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
/* init for the sequence number of received management frame */
psta->RxMgmtFrameSeqNum = 0xffff;
exit:
spin_unlock_bh(&pstapriv->sta_hash_lock);
return psta;
}
/* using pstapriv->sta_hash_lock to protect */
u32 rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
{
struct rtw_queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
struct sta_xmit_priv *pstaxmitpriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct sta_priv *pstapriv = &padapter->stapriv;
struct hw_xmit *phwxmit;
int i;
if (psta == NULL)
goto exit;
spin_lock_bh(&psta->lock);
psta->state &= ~_FW_LINKED;
spin_unlock_bh(&psta->lock);
pfree_sta_queue = &pstapriv->free_sta_queue;
pstaxmitpriv = &psta->sta_xmitpriv;
spin_lock_bh(&pxmitpriv->lock);
rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q);
psta->sleepq_len = 0;
/* vo */
rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
list_del_init(&pstaxmitpriv->vo_q.tx_pending);
phwxmit = pxmitpriv->hwxmits;
phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
pstaxmitpriv->vo_q.qcnt = 0;
/* vi */
rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
list_del_init(&pstaxmitpriv->vi_q.tx_pending);
phwxmit = pxmitpriv->hwxmits+1;
phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
pstaxmitpriv->vi_q.qcnt = 0;
/* be */
rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
list_del_init(&pstaxmitpriv->be_q.tx_pending);
phwxmit = pxmitpriv->hwxmits+2;
phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
pstaxmitpriv->be_q.qcnt = 0;
/* bk */
rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
list_del_init(&pstaxmitpriv->bk_q.tx_pending);
phwxmit = pxmitpriv->hwxmits+3;
phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
pstaxmitpriv->bk_q.qcnt = 0;
spin_unlock_bh(&pxmitpriv->lock);
list_del_init(&psta->hash_list);
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n", pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5]));
pstapriv->asoc_sta_count --;
/* re-init sta_info; 20061114 will be init in alloc_stainfo */
/* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
/* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
del_timer_sync(&psta->addba_retry_timer);
/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
for (i = 0; i < 16; i++) {
struct list_head *phead, *plist;
struct recv_frame *prframe;
struct rtw_queue *ppending_recvframe_queue;
struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
preorder_ctrl = &psta->recvreorder_ctrl[i];
del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
spin_lock_bh(&ppending_recvframe_queue->lock);
phead = get_list_head(ppending_recvframe_queue);
plist = phead->next;
while (!list_empty(phead)) {
prframe = container_of(plist, struct recv_frame, list);
plist = plist->next;
list_del_init(&prframe->list);
rtw_free_recvframe23a(prframe, pfree_recv_queue);
}
spin_unlock_bh(&ppending_recvframe_queue->lock);
}
if (!(psta->state & WIFI_AP_STATE))
rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, false);
#ifdef CONFIG_8723AU_AP_MODE
spin_lock_bh(&pstapriv->auth_list_lock);
if (!list_empty(&psta->auth_list)) {
list_del_init(&psta->auth_list);
pstapriv->auth_list_cnt--;
}
spin_unlock_bh(&pstapriv->auth_list_lock);
psta->expire_to = 0;
psta->sleepq_ac_len = 0;
psta->qos_info = 0;
psta->max_sp_len = 0;
psta->uapsd_bk = 0;
psta->uapsd_be = 0;
psta->uapsd_vi = 0;
psta->uapsd_vo = 0;
psta->has_legacy_ac = 0;
pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
if ((psta->aid >0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
pstapriv->sta_aid[psta->aid - 1] = NULL;
psta->aid = 0;
}
#endif /* CONFIG_8723AU_AP_MODE */
list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
exit:
return _SUCCESS;
}
/* free all stainfo which in sta_hash[all] */
void rtw_free_all_stainfo23a(struct rtw_adapter *padapter)
{
struct list_head *plist, *phead, *ptmp;
struct sta_info *psta;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info* pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
s32 index; if (pstapriv->asoc_sta_count == 1)
return;
spin_lock_bh(&pstapriv->sta_hash_lock);
for (index = 0; index < NUM_STA; index++) {
phead = &pstapriv->sta_hash[index];
list_for_each_safe(plist, ptmp, phead) {
psta = container_of(plist, struct sta_info, hash_list);
if (pbcmc_stainfo!= psta)
rtw_free_stainfo23a(padapter, psta);
}
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
}
/* any station allocated can be searched by hash list */
struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
{
struct list_head *plist, *phead;
struct sta_info *psta = NULL;
u32 index;
u8 *addr;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (hwaddr == NULL)
return NULL;
if (is_multicast_ether_addr(hwaddr))
addr = bc_addr;
else
addr = hwaddr;
index = wifi_mac_hash(addr);
spin_lock_bh(&pstapriv->sta_hash_lock);
phead = &pstapriv->sta_hash[index];
list_for_each(plist, phead) {
psta = container_of(plist, struct sta_info, hash_list);
if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
/* if found the matched address */
break;
}
psta = NULL;
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
return psta;
}
u32 rtw_init_bcmc_stainfo23a(struct rtw_adapter* padapter)
{
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta;
struct tx_servq *ptxservq;
u32 res = _SUCCESS;
unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
psta = rtw_alloc_stainfo23a(pstapriv, bcast_addr);
if (psta == NULL) {
res = _FAIL;
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
("rtw_alloc_stainfo23a fail"));
return res;
}
/* default broadcast & multicast use macid 1 */
psta->mac_id = 1;
ptxservq = &psta->sta_xmitpriv.be_q;
return _SUCCESS;
}
struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter)
{
struct sta_info *psta;
struct sta_priv *pstapriv = &padapter->stapriv;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
psta = rtw_get_stainfo23a(pstapriv, bc_addr);
return psta;
}
u8 rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr)
{
u8 res = true;
#ifdef CONFIG_8723AU_AP_MODE
struct list_head *plist, *phead;
struct rtw_wlan_acl_node *paclnode;
u8 match = false;
struct sta_priv *pstapriv = &padapter->stapriv;
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
spin_lock_bh(&pacl_node_q->lock);
phead = get_list_head(pacl_node_q);
list_for_each(plist, phead) {
paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
if (paclnode->valid) {
match = true;
break;
}
}
}
spin_unlock_bh(&pacl_node_q->lock);
if (pacl_list->mode == 1)/* accept unless in deny list */
res = (match) ? false : true;
else if (pacl_list->mode == 2)/* deny unless in accept list */
res = (match) ? true : false;
else
res = true;
#endif
return res;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу