staging: r8188eu: introduce new core dir for RTL8188eu driver

This patchset is split in order to keep the file sizes down. This core
directory is part of the newer/better driver from GitHub modified by
Larry Finger. Import this as the basis for all future work going
forward.

Suggested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Link: https://lore.kernel.org/r/20210727232219.2948-2-phil@philpotter.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Phillip Potter 2021-07-28 00:22:14 +01:00 committed by Greg Kroah-Hartman
parent 5c872e1d25
commit 15865124fe
23 changed files with 36842 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,943 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_DEBUG_C_
#include <rtw_debug.h>
#include <rtw_version.h>
int proc_get_drv_version(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
int len = 0;
len += snprintf(page + len, count - len, "%s\n", DRIVERVERSION);
*eof = 1;
return len;
}
int proc_get_write_reg(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
*eof = 1;
return 0;
}
int proc_set_write_reg(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
char tmp[32];
u32 addr, val, len;
if (count < 3) {
DBG_88E("argument size is less than 3\n");
return -EFAULT;
}
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
int num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
if (num != 3) {
DBG_88E("invalid write_reg parameter!\n");
return count;
}
switch (len) {
case 1:
rtw_write8(padapter, addr, (u8)val);
break;
case 2:
rtw_write16(padapter, addr, (u16)val);
break;
case 4:
rtw_write32(padapter, addr, val);
break;
default:
DBG_88E("error write length =%d", len);
break;
}
}
return count;
}
static u32 proc_get_read_addr = 0xeeeeeeee;
static u32 proc_get_read_len = 0x4;
int proc_get_read_reg(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
if (proc_get_read_addr == 0xeeeeeeee) {
*eof = 1;
return len;
}
switch (proc_get_read_len) {
case 1:
len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
break;
case 2:
len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
break;
case 4:
len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
break;
default:
len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
break;
}
*eof = 1;
return len;
}
int proc_set_read_reg(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char tmp[16];
u32 addr, len;
if (count < 2) {
DBG_88E("argument size is less than 2\n");
return -EFAULT;
}
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
int num = sscanf(tmp, "%x %x", &addr, &len);
if (num != 2) {
DBG_88E("invalid read_reg parameter!\n");
return count;
}
proc_get_read_addr = addr;
proc_get_read_len = len;
}
return count;
}
int proc_get_fwstate(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
int len = 0;
len += snprintf(page + len, count - len, "fwstate=0x%x\n", get_fwstate(pmlmepriv));
*eof = 1;
return len;
}
int proc_get_sec_info(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct security_priv *psecuritypriv = &padapter->securitypriv;
int len = 0;
len += snprintf(page + len, count - len, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
*eof = 1;
return len;
}
int proc_get_mlmext_state(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
int len = 0;
len += snprintf(page + len, count - len, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
*eof = 1;
return len;
}
int proc_get_qos_option(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
int len = 0;
len += snprintf(page + len, count - len, "qos_option=%d\n", pmlmepriv->qospriv.qos_option);
*eof = 1;
return len;
}
int proc_get_ht_option(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
int len = 0;
len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option);
*eof = 1;
return len;
}
int proc_get_rf_info(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
int len = 0;
len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n",
pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
*eof = 1;
return len;
}
int proc_get_ap_info(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct sta_info *psta;
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct wlan_network *cur_network = &(pmlmepriv->cur_network);
struct sta_priv *pstapriv = &padapter->stapriv;
int len = 0;
psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
if (psta) {
int i;
struct recv_reorder_ctrl *preorder_ctrl;
len += snprintf(page + len, count - len, "SSID=%s\n", cur_network->network.Ssid.Ssid);
len += snprintf(page + len, count - len, "sta's macaddr:%pM\n", psta->hwaddr);
len += snprintf(page + len, count - len, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
if (preorder_ctrl->enable)
len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq);
}
} else {
len += snprintf(page + len, count - len, "can't get sta's macaddr, cur_network's macaddr: %pM\n", cur_network->network.MacAddress);
}
*eof = 1;
return len;
}
int proc_get_adapter_state(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
len += snprintf(page + len, count - len, "bSurpriseRemoved=%d, bDriverStopped=%d\n",
padapter->bSurpriseRemoved, padapter->bDriverStopped);
*eof = 1;
return len;
}
int proc_get_trx_info(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct recv_priv *precvpriv = &padapter->recvpriv;
int len = 0;
len += snprintf(page + len, count - len, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_ext_xmitbuf_cnt=%d, free_recvframe_cnt=%d\n",
pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt, precvpriv->free_recvframe_cnt);
len += snprintf(page + len, count - len, "rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt);
*eof = 1;
return len;
}
int proc_get_mac_reg_dump1(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
for (i = 0x0; i < 0x300; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_mac_reg_dump2(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
memset(page, 0, count);
for (i = 0x300; i < 0x600; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_mac_reg_dump3(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
for (i = 0x600; i < 0x800; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_bb_reg_dump1(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
for (i = 0x800; i < 0xB00; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_bb_reg_dump2(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
for (i = 0xB00; i < 0xE00; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_bb_reg_dump3(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1;
len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
for (i = 0xE00; i < 0x1000; i += 4) {
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x", i);
len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_rf_reg_dump1(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1, path;
u32 value;
len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
path = 1;
len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
for (i = 0; i < 0xC0; i++) {
value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x ", i);
len += snprintf(page + len, count - len, " 0x%08x ", value);
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_rf_reg_dump2(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1, path;
u32 value;
len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
path = 1;
len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
for (i = 0xC0; i < 0x100; i++) {
value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x ", i);
len += snprintf(page + len, count - len, " 0x%08x ", value);
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_rf_reg_dump3(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1, path;
u32 value;
len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
path = 2;
len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
for (i = 0; i < 0xC0; i++) {
value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x ", i);
len += snprintf(page + len, count - len, " 0x%08x ", value);
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_rf_reg_dump4(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
int i, j = 1, path;
u32 value;
len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
path = 2;
len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
for (i = 0xC0; i < 0x100; i++) {
value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
if (j%4 == 1)
len += snprintf(page + len, count - len, "0x%02x ", i);
len += snprintf(page + len, count - len, " 0x%08x ", value);
if ((j++)%4 == 0)
len += snprintf(page + len, count - len, "\n");
}
*eof = 1;
return len;
}
int proc_get_rx_signal(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
len = snprintf(page + len, count,
"rssi:%d\n"
"rxpwdb:%d\n"
"signal_strength:%u\n"
"signal_qual:%u\n"
"noise:%u\n",
padapter->recvpriv.rssi,
padapter->recvpriv.rxpwdb,
padapter->recvpriv.signal_strength,
padapter->recvpriv.signal_qual,
padapter->recvpriv.noise
);
*eof = 1;
return len;
}
int proc_set_rx_signal(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
char tmp[32];
u32 is_signal_dbg;
s32 signal_strength;
if (count < 1)
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
is_signal_dbg = is_signal_dbg == 0 ? 0 : 1;
if (is_signal_dbg && num != 2)
return count;
signal_strength = signal_strength > 100 ? 100 : signal_strength;
signal_strength = signal_strength < 0 ? 0 : signal_strength;
padapter->recvpriv.is_signal_dbg = is_signal_dbg;
padapter->recvpriv.signal_strength_dbg = signal_strength;
if (is_signal_dbg)
DBG_88E("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength);
else
DBG_88E("set %s\n", "HW_SIGNAL_STRENGTH");
}
return count;
}
int proc_get_ht_enable(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
int len = 0;
if (pregpriv)
len += snprintf(page + len, count - len,
"%d\n",
pregpriv->ht_enable
);
*eof = 1;
return len;
}
int proc_set_ht_enable(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
char tmp[32];
s32 mode = 0;
if (count < 1)
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
if (pregpriv) {
pregpriv->ht_enable = mode;
pr_info("ht_enable=%d\n", pregpriv->ht_enable);
}
}
return count;
}
int proc_get_cbw40_enable(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
int len = 0;
if (pregpriv)
len += snprintf(page + len, count - len,
"%d\n",
pregpriv->cbw40_enable
);
*eof = 1;
return len;
}
int proc_set_cbw40_enable(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
char tmp[32];
s32 mode = 0;
if (count < 1)
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
if (pregpriv) {
pregpriv->cbw40_enable = mode;
pr_info("cbw40_enable=%d\n", mode);
}
}
return count;
}
int proc_get_ampdu_enable(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
int len = 0;
if (pregpriv)
len += snprintf(page + len, count - len,
"%d\n",
pregpriv->ampdu_enable
);
*eof = 1;
return len;
}
int proc_set_ampdu_enable(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
char tmp[32];
s32 mode = 0;
if (count < 1)
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
if (pregpriv) {
pregpriv->ampdu_enable = mode;
pr_info("ampdu_enable=%d\n", mode);
}
}
return count;
}
int proc_get_two_path_rssi(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
int len = 0;
if (padapter)
len += snprintf(page + len, count - len,
"%d %d\n",
padapter->recvpriv.RxRssi[0],
padapter->recvpriv.RxRssi[1]
);
*eof = 1;
return len;
}
int proc_get_rx_stbc(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
int len = 0;
if (pregpriv)
len += snprintf(page + len, count - len,
"%d\n",
pregpriv->rx_stbc
);
*eof = 1;
return len;
}
int proc_set_rx_stbc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct registry_priv *pregpriv = &padapter->registrypriv;
char tmp[32];
u32 mode = 0;
if (count < 1)
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
if (pregpriv) {
pregpriv->rx_stbc = mode;
printk("rx_stbc=%d\n", mode);
}
}
return count;
}
int proc_get_rssi_disp(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
*eof = 1;
return 0;
}
int proc_set_rssi_disp(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct net_device *dev = (struct net_device *)data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
char tmp[32];
u32 enable = 0;
if (count < 1) {
DBG_88E("argument size is less than 1\n");
return -EFAULT;
}
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
int num = sscanf(tmp, "%x", &enable);
if (num != 1) {
DBG_88E("invalid set_rssi_disp parameter!\n");
return count;
}
if (enable) {
DBG_88E("Turn On Rx RSSI Display Function\n");
padapter->bRxRSSIDisplay = enable ;
} else {
DBG_88E("Turn Off Rx RSSI Display Function\n");
padapter->bRxRSSIDisplay = 0;
}
}
return count;
}
#ifdef CONFIG_88EU_AP_MODE
int proc_get_all_sta_info(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct sta_info *psta;
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct sta_priv *pstapriv = &padapter->stapriv;
int i, j;
struct list_head *plist, *phead;
struct recv_reorder_ctrl *preorder_ctrl;
int len = 0;
len += snprintf(page + len, count - len, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
spin_lock_bh(&pstapriv->sta_hash_lock);
for (i = 0; i < NUM_STA; i++) {
phead = &(pstapriv->sta_hash[i]);
plist = phead->next;
while (phead != plist) {
psta = container_of(plist, struct sta_info, hash_list);
plist = plist->next;
len += snprintf(page + len, count - len, "sta's macaddr: %pM\n", psta->hwaddr);
len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
len += snprintf(page + len, count - len, "sleepq_len=%d\n", psta->sleepq_len);
len += snprintf(page + len, count - len, "capability=0x%x\n", psta->capability);
len += snprintf(page + len, count - len, "flags=0x%x\n", psta->flags);
len += snprintf(page + len, count - len, "wpa_psk=0x%x\n", psta->wpa_psk);
len += snprintf(page + len, count - len, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
len += snprintf(page + len, count - len, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
len += snprintf(page + len, count - len, "qos_info=0x%x\n", psta->qos_info);
len += snprintf(page + len, count - len, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
for (j = 0; j < 16; j++) {
preorder_ctrl = &psta->recvreorder_ctrl[j];
if (preorder_ctrl->enable)
len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq);
}
}
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
*eof = 1;
return len;
}
#endif
int proc_get_best_channel(char *page, char **start,
off_t offset, int count,
int *eof, void *data)
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
int len = 0;
u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0;
for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
if (pmlmeext->channel_set[i].ChannelNum == 1)
index_24G = i;
if (pmlmeext->channel_set[i].ChannelNum == 36)
index_5G = i;
}
for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
/* 2.4G */
if (pmlmeext->channel_set[i].ChannelNum == 6) {
if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) {
index_24G = i;
best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
}
}
/* 5G */
if (pmlmeext->channel_set[i].ChannelNum >= 36 &&
pmlmeext->channel_set[i].ChannelNum < 140) {
/* Find primary channel */
if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0) &&
(pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
index_5G = i;
best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
}
}
if (pmlmeext->channel_set[i].ChannelNum >= 149 &&
pmlmeext->channel_set[i].ChannelNum < 165) {
/* find primary channel */
if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0) &&
(pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
index_5G = i;
best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
}
}
/* debug */
len += snprintf(page + len, count - len, "The rx cnt of channel %3d = %d\n",
pmlmeext->channel_set[i].ChannelNum, pmlmeext->channel_set[i].rx_count);
}
len += snprintf(page + len, count - len, "best_channel_5G = %d\n", best_channel_5G);
len += snprintf(page + len, count - len, "best_channel_24G = %d\n", best_channel_24G);
*eof = 1;
return len;
}

View File

@ -0,0 +1,872 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_EFUSE_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtw_efuse.h>
/*------------------------Define local variable------------------------------*/
u8 fakeEfuseBank;
u32 fakeEfuseUsedBytes;
u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
u32 BTEfuseUsedBytes;
u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u32 fakeBTEfuseUsedBytes;
u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
/*------------------------Define local variable------------------------------*/
/* */
#define REG_EFUSE_CTRL 0x0030
#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
/* */
bool
Efuse_Read1ByteFromFakeContent(
struct adapter *pAdapter,
u16 Offset,
u8 *Value);
bool
Efuse_Read1ByteFromFakeContent(
struct adapter *pAdapter,
u16 Offset,
u8 *Value)
{
if (Offset >= EFUSE_MAX_HW_SIZE)
return false;
if (fakeEfuseBank == 0)
*Value = fakeEfuseContent[Offset];
else
*Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
return true;
}
static bool
Efuse_Write1ByteToFakeContent(
struct adapter *pAdapter,
u16 Offset,
u8 Value)
{
if (Offset >= EFUSE_MAX_HW_SIZE)
return false;
if (fakeEfuseBank == 0) {
fakeEfuseContent[Offset] = Value;
} else {
fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
}
return true;
}
/*-----------------------------------------------------------------------------
* Function: Efuse_PowerSwitch
*
* 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_PowerSwitch(
struct adapter *pAdapter,
u8 write,
u8 PwrState)
{
pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
}
/*-----------------------------------------------------------------------------
* Function: efuse_GetCurrentSize
*
* 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_GetCurrentSize(
struct adapter *pAdapter,
u8 efuseType,
bool pseudo)
{
u16 ret = 0;
ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
return ret;
}
/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
u8
Efuse_CalculateWordCnts(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. */
/* Referred 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
ReadEFuseByte(
struct adapter *Adapter,
u16 _offset,
u8 *pbuf,
bool pseudo)
{
u32 value32;
u8 readbyte;
u16 retry;
if (pseudo) {
Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
return;
}
/* 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 < 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. */
rtw_udelay_os(50);
value32 = rtw_read32(Adapter, EFUSE_CTRL);
*pbuf = (u8)(value32 & 0xff);
}
/* */
/* Description: */
/* 1. Execute E-Fuse read byte operation according as map offset and */
/* save to E-Fuse table. */
/* 2. Referred 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. */
/* */
static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
{
Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
}
void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
)
{
pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
}
/*-----------------------------------------------------------------------------
* Function: EFUSE_Read1Byte
*
* 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_Read1Byte(struct adapter *Adapter, u16 Address)
{
u8 data;
u8 Bytetemp = {0x00};
u8 temp = {0x00};
u32 k = 0;
u16 contentLen = 0;
EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
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_Read1Byte */
/* 11/16/2008 MH Read one byte from real Efuse. */
u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
{
u8 tmpidx = 0;
u8 result;
if (pseudo) {
result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
return result;
}
/* -----------------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);
result = true;
} else {
*data = 0xff;
result = false;
}
return result;
}
/* 11/16/2008 MH Write one byte to reald Efuse. */
u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
{
u8 tmpidx = 0;
u8 result;
if (pseudo) {
result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
return result;
}
/* -----------------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)
result = true;
else
result = false;
return result;
}
int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
{
int ret = 0;
ret = pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
return ret;
}
int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
{
int ret;
ret = pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
return ret;
}
static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
{
int ret;
ret = pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
return ret;
}
/*-----------------------------------------------------------------------------
* Function: efuse_WordEnableDataRead
*
* 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_WordEnableDataRead(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_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
{
u8 ret = 0;
ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
return ret;
}
static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
{
return efuse_OneByteRead(padapter, address, value, false);
}
static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
{
return efuse_OneByteWrite(padapter, address, *value, false);
}
/*
* read/wirte raw efuse data
*/
u8 rtw_efuse_access(struct adapter *padapter, u8 write, 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 adapter *, u16, u8*);
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
if (start_addr > real_content_len)
return _FAIL;
if (write) {
if ((start_addr + cnts) > max_available_size)
return _FAIL;
rw8 = &efuse_write8;
} else {
rw8 = &efuse_read8;
}
Efuse_PowerSwitch(padapter, write, 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_PowerSwitch(padapter, write, false);
return res;
}
/* */
u16 efuse_GetMaxSize(struct adapter *padapter)
{
u16 max_size;
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
return max_size;
}
/* */
u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
{
Efuse_PowerSwitch(padapter, false, true);
*size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
Efuse_PowerSwitch(padapter, false, false);
return _SUCCESS;
}
/* */
u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u16 mapLen = 0;
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
if ((addr + cnts) > mapLen)
return _FAIL;
Efuse_PowerSwitch(padapter, false, true);
efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
Efuse_PowerSwitch(padapter, false, false);
return _SUCCESS;
}
u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u16 mapLen = 0;
EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
if ((addr + cnts) > mapLen)
return _FAIL;
Efuse_PowerSwitch(padapter, false, true);
efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
Efuse_PowerSwitch(padapter, false, false);
return _SUCCESS;
}
/* */
u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u8 offset, word_en;
u8 *map;
u8 newdata[PGPKT_DATA_SIZE + 1];
s32 i, idx;
u8 ret = _SUCCESS;
u16 mapLen = 0;
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
if ((addr + cnts) > mapLen)
return _FAIL;
map = rtw_zmalloc(mapLen);
if (map == NULL)
return _FAIL;
ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
if (ret == _FAIL)
goto exit;
Efuse_PowerSwitch(padapter, true, true);
offset = (addr >> 3);
word_en = 0xF;
memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
i = addr & 0x7; /* index of one package */
idx = 0; /* data index */
if (i & 0x1) {
/* odd start */
if (data[idx] != map[addr+idx]) {
word_en &= ~BIT(i >> 1);
newdata[i-1] = map[addr+idx-1];
newdata[i] = data[idx];
}
i++;
idx++;
}
do {
for (; i < PGPKT_DATA_SIZE; i += 2) {
if (cnts == idx)
break;
if ((cnts - idx) == 1) {
if (data[idx] != map[addr+idx]) {
word_en &= ~BIT(i >> 1);
newdata[i] = data[idx];
newdata[i+1] = map[addr+idx+1];
}
idx++;
break;
} else {
if ((data[idx] != map[addr+idx]) ||
(data[idx+1] != map[addr+idx+1])) {
word_en &= ~BIT(i >> 1);
newdata[i] = data[idx];
newdata[i+1] = data[idx + 1];
}
idx += 2;
}
if (idx == cnts)
break;
}
if (word_en != 0xF) {
ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
DBG_88E("offset=%x\n", offset);
DBG_88E("word_en=%x\n", word_en);
for (i = 0; i < PGPKT_DATA_SIZE; i++)
DBG_88E("data=%x \t", newdata[i]);
if (ret == _FAIL)
break;
}
if (idx == cnts)
break;
offset++;
i = 0;
word_en = 0xF;
memset(newdata, 0xFF, PGPKT_DATA_SIZE);
} while (1);
Efuse_PowerSwitch(padapter, true, false);
exit:
kfree(map);
return ret;
}
/* */
u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u8 offset, word_en;
u8 *map;
u8 newdata[PGPKT_DATA_SIZE + 1];
s32 i, idx;
u8 ret = _SUCCESS;
u16 mapLen = 0;
EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
if ((addr + cnts) > mapLen)
return _FAIL;
map = rtw_zmalloc(mapLen);
if (map == NULL)
return _FAIL;
ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
if (ret == _FAIL)
goto exit;
Efuse_PowerSwitch(padapter, true, true);
offset = (addr >> 3);
word_en = 0xF;
memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
i = addr & 0x7; /* index of one package */
idx = 0; /* data index */
if (i & 0x1) {
/* odd start */
if (data[idx] != map[addr+idx]) {
word_en &= ~BIT(i >> 1);
newdata[i-1] = map[addr+idx-1];
newdata[i] = data[idx];
}
i++;
idx++;
}
do {
for (; i < PGPKT_DATA_SIZE; i += 2) {
if (cnts == idx)
break;
if ((cnts - idx) == 1) {
if (data[idx] != map[addr+idx]) {
word_en &= ~BIT(i >> 1);
newdata[i] = data[idx];
newdata[i+1] = map[addr+idx+1];
}
idx++;
break;
} else {
if ((data[idx] != map[addr+idx]) ||
(data[idx+1] != map[addr+idx+1])) {
word_en &= ~BIT(i >> 1);
newdata[i] = data[idx];
newdata[i+1] = data[idx + 1];
}
idx += 2;
}
if (idx == cnts)
break;
}
if (word_en != 0xF) {
DBG_88E("%s: offset=%#X\n", __func__, offset);
DBG_88E("%s: word_en=%#X\n", __func__, word_en);
DBG_88E("%s: data=", __func__);
for (i = 0; i < PGPKT_DATA_SIZE; i++)
DBG_88E("0x%02X ", newdata[i]);
DBG_88E("\n");
ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
if (ret == _FAIL)
break;
}
if (idx == cnts)
break;
offset++;
i = 0;
word_en = 0xF;
memset(newdata, 0xFF, PGPKT_DATA_SIZE);
} while (1);
Efuse_PowerSwitch(padapter, true, false);
exit:
kfree(map);
return ret;
}
/*-----------------------------------------------------------------------------
* 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 adapter *pAdapter,
u16 Offset,
u8 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
} /* EFUSE_ShadowRead1Byte */
/* Read Two Bytes */
static void
efuse_ShadowRead2Byte(
struct 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_ShadowRead2Byte */
/* Read Four Bytes */
static void
efuse_ShadowRead4Byte(
struct 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_ReadAllMap
*
* Overview: Read All Efuse content
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/11/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
{
u16 mapLen = 0;
Efuse_PowerSwitch(pAdapter, false, true);
EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
Efuse_PowerSwitch(pAdapter, false, false);
}
/*-----------------------------------------------------------------------------
* Function: EFUSE_ShadowMapUpdate
*
* 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_ShadowMapUpdate(
struct adapter *pAdapter,
u8 efuseType,
bool pseudo)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
u16 mapLen = 0;
EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
if (pEEPROM->bautoload_fail_flag)
memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
else
Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
} /* EFUSE_ShadowMapUpdate */
/*-----------------------------------------------------------------------------
* Function: EFUSE_ShadowRead
*
* 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_ShadowRead(struct 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_ShadowRead */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,323 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
/*
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:
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>
#define rtw_le16_to_cpu(val) le16_to_cpu(val)
#define rtw_le32_to_cpu(val) le32_to_cpu(val)
#define rtw_cpu_to_le16(val) cpu_to_le16(val)
#define rtw_cpu_to_le32(val) cpu_to_le32(val)
u8 _rtw_read8(struct adapter *adapter, u32 addr)
{
u8 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
_read8 = pintfhdl->io_ops._read8;
r_val = _read8(pintfhdl, addr);
return r_val;
}
u16 _rtw_read16(struct adapter *adapter, u32 addr)
{
u16 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
_read16 = pintfhdl->io_ops._read16;
r_val = _read16(pintfhdl, addr);
return r_val;
}
u32 _rtw_read32(struct adapter *adapter, u32 addr)
{
u32 r_val;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
_read32 = pintfhdl->io_ops._read32;
r_val = _read32(pintfhdl, addr);
return r_val;
}
int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
int ret;
_write8 = pintfhdl->io_ops._write8;
ret = _write8(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write16(struct adapter *adapter, u32 addr, u16 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
int ret;
_write16 = pintfhdl->io_ops._write16;
ret = _write16(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write32(struct adapter *adapter, u32 addr, u32 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
int ret;
_write32 = pintfhdl->io_ops._write32;
ret = _write32(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_writeN(struct 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 (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
int ret;
_writeN = pintfhdl->io_ops._writeN;
ret = _writeN(pintfhdl, addr, length, pdata);
return RTW_STATUS_CODE(ret);
}
int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
int ret;
_write8_async = pintfhdl->io_ops._write8_async;
ret = _write8_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
int ret;
_write16_async = pintfhdl->io_ops._write16_async;
ret = _write16_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
int ret;
_write32_async = pintfhdl->io_ops._write32_async;
ret = _write32_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
("rtw_read_mem:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
adapter->bDriverStopped, adapter->bSurpriseRemoved));
return;
}
_read_mem = pintfhdl->io_ops._read_mem;
_read_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
_write_mem = pintfhdl->io_ops._write_mem;
_write_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
("rtw_read_port:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
adapter->bDriverStopped, adapter->bSurpriseRemoved));
return;
}
_read_port = pintfhdl->io_ops._read_port;
_read_port(pintfhdl, addr, cnt, pmem);
}
void _rtw_read_port_cancel(struct 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_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u32 ret = _SUCCESS;
_write_port = pintfhdl->io_ops._write_port;
ret = _write_port(pintfhdl, addr, cnt, pmem);
return ret;
}
u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
{
int ret = _SUCCESS;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
struct submit_ctx sctx;
rtw_sctx_init(&sctx, timeout_ms);
pxmitbuf->sctx = &sctx;
ret = _rtw_write_port(adapter, addr, cnt, pmem);
if (ret == _SUCCESS)
ret = rtw_sctx_wait(&sctx);
return ret;
}
void _rtw_write_port_cancel(struct 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_priv(struct 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#include<rtw_iol.h>
struct xmit_frame *rtw_IOL_accquire_xmit_frame(struct adapter *adapter)
{
struct xmit_frame *xmit_frame;
struct xmit_buf *xmitbuf;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
if (xmit_frame == NULL) {
DBG_88E("%s rtw_alloc_xmitframe return null\n", __func__);
goto exit;
}
xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
if (xmitbuf == NULL) {
DBG_88E("%s rtw_alloc_xmitbuf return null\n", __func__);
rtw_free_xmitframe(pxmitpriv, xmit_frame);
xmit_frame = NULL;
goto exit;
}
xmit_frame->frame_tag = MGNT_FRAMETAG;
xmit_frame->pxmitbuf = xmitbuf;
xmit_frame->buf_addr = xmitbuf->pbuf;
xmitbuf->priv_data = xmit_frame;
pattrib = &xmit_frame->attrib;
update_mgntframe_attrib(adapter, pattrib);
pattrib->qsel = 0x10;/* Beacon */
pattrib->subtype = WIFI_BEACON;
pattrib->pktlen = 0;
pattrib->last_txcmdsz = 0;
exit:
return xmit_frame;
}
int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
{
struct pkt_attrib *pattrib = &xmit_frame->attrib;
u16 buf_offset;
u32 ori_len;
buf_offset = TXDESC_OFFSET;
ori_len = buf_offset+pattrib->pktlen;
/* check if the io_buf can accommodate new cmds */
if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
DBG_88E("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n",
__func__ , ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
return _FAIL;
}
memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
pattrib->pktlen += cmd_len;
pattrib->last_txcmdsz += cmd_len;
return _SUCCESS;
}
bool rtw_IOL_applied(struct adapter *adapter)
{
if (1 == adapter->registrypriv.fw_iol)
return true;
if ((2 == adapter->registrypriv.fw_iol) && (!adapter_to_dvobj(adapter)->ishighspeed))
return true;
return false;
}
int rtw_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
{
return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms, bndy_cnt);
}
int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
{
return _SUCCESS;
}
int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFF) {
cmd.length = 12;
cmd.mask = cpu_to_le32(mask);
}
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFFFF) {
cmd.length = 12;
cmd.mask = cpu_to_le32(mask);
}
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFFFFFFFF) {
cmd.length = 12;
cmd.mask = cpu_to_le32(mask);
}
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16((rf_path<<8) | ((addr) & 0xFF));
cmd.data = cpu_to_le32(value);
if (mask != 0x000FFFFF) {
cmd.length = 12;
cmd.mask = cpu_to_le32(mask);
}
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16(us);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
cmd.address = cpu_to_le16(ms);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_END, cpu_to_le16(0xFFFF), cpu_to_le32(0xFF), 0x0};
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
{
u8 is_cmd_bndy = false;
if (((pxmit_frame->attrib.pktlen+32)%256) + 8 >= 256) {
rtw_IOL_append_END_cmd(pxmit_frame);
pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen+32)/256)+1)*256);
pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
is_cmd_bndy = true;
}
return is_cmd_bndy;
}
void rtw_IOL_cmd_buf_dump(struct adapter *Adapter, int buf_len, u8 *pbuf)
{
int i;
int j = 1;
pr_info("###### %s ######\n", __func__);
for (i = 0; i < buf_len; i++) {
printk("%02x-", *(pbuf+i));
if (j%32 == 0)
printk("\n");
j++;
}
printk("\n");
pr_info("=============ioreg_cmd len=%d===============\n", buf_len);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,655 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_PWRCTRL_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <osdep_intf.h>
#include <linux/usb.h>
void ips_enter(struct adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct xmit_priv *pxmit_priv = &padapter->xmitpriv;
if (padapter->registrypriv.mp_mode == 1)
return;
if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n");
DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
return;
}
_enter_pwrlock(&pwrpriv->lock);
pwrpriv->bips_processing = true;
/* syn ips_mode with request */
pwrpriv->ips_mode = pwrpriv->ips_mode_req;
pwrpriv->ips_enter_cnts++;
DBG_88E("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
if (rf_off == pwrpriv->change_rfpwrstate) {
pwrpriv->bpower_saving = true;
DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n");
if (pwrpriv->ips_mode == IPS_LEVEL_2)
pwrpriv->bkeepfwalive = true;
rtw_ips_pwr_down(padapter);
pwrpriv->rf_pwrstate = rf_off;
}
pwrpriv->bips_processing = false;
_exit_pwrlock(&pwrpriv->lock);
}
int ips_leave(struct 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;
_enter_pwrlock(&pwrpriv->lock);
if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
pwrpriv->bips_processing = true;
pwrpriv->change_rfpwrstate = rf_on;
pwrpriv->ips_leave_cnts++;
DBG_88E("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
result = rtw_ips_pwr_up(padapter);
if (result == _SUCCESS) {
pwrpriv->rf_pwrstate = rf_on;
}
DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n");
if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) || (_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) {
DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
set_channel_bwmode(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 & BIT(keyid)) {
if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
result = rtw_set_key(padapter, psecuritypriv, keyid, 1);
else
result = rtw_set_key(padapter, psecuritypriv, keyid, 0);
}
}
}
DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
pwrpriv->bips_processing = false;
pwrpriv->bkeepfwalive = false;
pwrpriv->bpower_saving = false;
}
_exit_pwrlock(&pwrpriv->lock);
return result;
}
static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
{
struct adapter *buddy = adapter->pbuddy_adapter;
struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
#ifdef CONFIG_88EU_P2P
struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
#endif
bool ret = false;
if (adapter->pwrctrlpriv.ips_deny_time >= jiffies)
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_UNDER_WPS) ||
check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) ||
#if defined(CONFIG_88EU_P2P)
!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
#else
0)
#endif
goto exit;
/* consider buddy, if exist */
if (buddy) {
struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
#ifdef CONFIG_88EU_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) ||
#if defined(CONFIG_88EU_P2P)
!rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE))
#else
0)
#endif
goto exit;
}
ret = true;
exit:
return ret;
}
void rtw_ps_processor(struct 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)
goto exit;
if (padapter->pwrctrlpriv.bHWPwrPindetect) {
rfpwrstate = RfOnOffDetect(padapter);
DBG_88E("@@@@- #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_suspend(padapter);
} else {
pwrpriv->change_rfpwrstate = rf_on;
rtw_hw_resume(padapter);
}
DBG_88E("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))
goto exit;
if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
pwrpriv->change_rfpwrstate = rf_off;
ips_enter(padapter);
}
exit:
rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
pwrpriv->ps_processing = false;
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
static void pwr_state_check_handler(struct timer_list *t)
#else
static void pwr_state_check_handler(void *FunctionContext)
#endif
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
struct adapter *padapter =
from_timer(padapter, t,
pwrctrlpriv.pwr_state_check_timer);
#else
struct adapter *padapter = (struct adapter *)FunctionContext;
#endif
rtw_ps_cmd(padapter);
}
/*
*
* Parameters
* padapter
* pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
*
*/
void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
{
u8 rpwm;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
pslv = PS_STATE(pslv);
if (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) ||
(!padapter->hw_init_completed)) {
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) {
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_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
pwrpriv->rpwm = pslv;
rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
pwrpriv->tog += 0x80;
pwrpriv->cpwm = pslv;
}
static u8 PS_RDY_CHECK(struct adapter *padapter)
{
u32 curr_time, delta_time;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
curr_time = jiffies;
delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
if (delta_time < LPS_DELAY_TIME)
return false;
if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
(check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
return false;
if (pwrpriv->bInSuspend)
return false;
if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
DBG_88E("Group handshake still in progress !!!\n");
return false;
}
return true;
}
void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
#ifdef CONFIG_88EU_P2P
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
#endif /* CONFIG_88EU_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 (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
if (ps_mode == PS_MODE_ACTIVE) {
#ifdef CONFIG_88EU_P2P
if (pwdinfo->opp_ps == 0) {
DBG_88E("rtw_set_ps_mode: Leave 802.11 power save\n");
pwrpriv->pwr_mode = ps_mode;
rtw_set_rpwm(padapter, PS_STATE_S4);
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
pwrpriv->bFwCurrentInPSMode = false;
}
} else {
#endif /* CONFIG_88EU_P2P */
if (PS_RDY_CHECK(padapter)) {
DBG_88E("%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_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
#ifdef CONFIG_88EU_P2P
/* Set CTWindow after LPS */
if (pwdinfo->opp_ps == 1)
p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
#endif /* CONFIG_88EU_P2P */
rtw_set_rpwm(padapter, PS_STATE_S2);
}
}
}
/*
* Return:
* 0: Leave OK
* -1: Timeout
* -2: Other error
*/
s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
{
u32 start_time;
u8 bAwake = false;
s32 err = 0;
start_time = jiffies;
while (1) {
rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
if (bAwake)
break;
if (padapter->bSurpriseRemoved) {
err = -2;
DBG_88E("%s: device surprise removed!!\n", __func__);
break;
}
if (rtw_get_passing_time_ms(start_time) > delay_ms) {
err = -1;
DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
break;
}
rtw_usleep_os(100);
}
return err;
}
/* */
/* Description: */
/* Enter the leisure power save mode. */
/* */
void LPS_Enter(struct adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (PS_RDY_CHECK(padapter) == false)
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_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
/* For Tenda W311R IOT issue */
rtw_set_ps_mode(padapter, pwrpriv->power_mgnt,
pwrpriv->smart_ps, 0x40);
}
} else {
pwrpriv->LpsIdleCount++;
}
}
}
#define LPS_LEAVE_TIMEOUT_MS 100
/* Description: */
/* Leave the leisure power save mode. */
void LPS_Leave(struct adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (pwrpriv->bLeisurePs) {
if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0x40);
if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
LPS_RF_ON_check(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 LeaveAllPowerSaveMode(struct adapter *Adapter)
{
struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
u8 enqueue = 0;
if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
}
}
void rtw_init_pwrctrl_priv(struct adapter *padapter)
{
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
_init_pwrlock(&pwrctrlpriv->lock);
pwrctrlpriv->rf_pwrstate = rf_on;
pwrctrlpriv->ips_enter_cnts = 0;
pwrctrlpriv->ips_leave_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;
if (padapter->registrypriv.mp_mode == 1)
pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE ;
else
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;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
timer_setup(&pwrctrlpriv->pwr_state_check_timer, pwr_state_check_handler, 0);
#else
_init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
#endif
}
void rtw_free_pwrctrl_priv(struct adapter *adapter)
{
struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv;
_free_pwrlock(&pwrctrlpriv->lock);
}
u8 rtw_interface_ps_func(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
{
u8 bResult = true;
rtw_hal_intf_ps_func(padapter, efunc_id, val);
return bResult;
}
inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ms);
}
/*
* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
* @adapter: pointer to struct adapter structure
* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
* Return _SUCCESS or _FAIL
*/
int _rtw_pwr_wakeup(struct 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 = jiffies;
if (pwrpriv->ips_deny_time < jiffies + rtw_ms_to_systime(ips_deffer_ms))
pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
if (pwrpriv->ps_processing) {
DBG_88E("%s wait ps_processing...\n", __func__);
while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
rtw_msleep_os(10);
if (pwrpriv->ps_processing)
DBG_88E("%s wait ps_processing timeout\n", __func__);
else
DBG_88E("%s wait ps_processing done\n", __func__);
}
/* System suspend is not allowed to wakeup */
if ((!pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) {
while (pwrpriv->bInSuspend &&
(rtw_get_passing_time_ms(start) <= 3000 ||
(rtw_get_passing_time_ms(start) <= 500)))
rtw_msleep_os(10);
if (pwrpriv->bInSuspend)
DBG_88E("%s wait bInSuspend timeout\n", __func__);
else
DBG_88E("%s wait bInSuspend done\n", __func__);
}
/* block??? */
if ((pwrpriv->bInternalAutoSuspend) && (padapter->net_closed)) {
ret = _FAIL;
goto exit;
}
/* I think this should be check in IPS, LPS, autosuspend functions... */
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
ret = _SUCCESS;
goto exit;
}
if (rf_off == pwrpriv->rf_pwrstate) {
DBG_88E("%s call ips_leave....\n", __func__);
if (_FAIL == ips_leave(padapter)) {
DBG_88E("======> ips_leave fail.............\n");
ret = _FAIL;
goto exit;
}
}
/* TODO: the following checking need to be merged... */
if (padapter->bDriverStopped || !padapter->bup ||
!padapter->hw_init_completed) {
DBG_88E("%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 < jiffies + rtw_ms_to_systime(ips_deffer_ms))
pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
return ret;
}
int rtw_pm_set_lps(struct 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)
LeaveAllPowerSaveMode(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_ips(struct 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_88E("%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_88E("%s %s\n", __func__, "IPS_NONE");
if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
return -EFAULT;
} else {
return -EINVAL;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_RF_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <xmit_osdep.h>
struct ch_freq {
u32 channel;
u32 frequency;
};
static struct ch_freq ch_freq_map[] = {
{1, 2412}, {2, 2417}, {3, 2422}, {4, 2427}, {5, 2432},
{6, 2437}, {7, 2442}, {8, 2447}, {9, 2452}, {10, 2457},
{11, 2462}, {12, 2467}, {13, 2472}, {14, 2484},
/* UNII */
{36, 5180}, {40, 5200}, {44, 5220}, {48, 5240}, {52, 5260},
{56, 5280}, {60, 5300}, {64, 5320}, {149, 5745}, {153, 5765},
{157, 5785}, {161, 5805}, {165, 5825}, {167, 5835}, {169, 5845},
{171, 5855}, {173, 5865},
/* HiperLAN2 */
{100, 5500}, {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580},
{120, 5600}, {124, 5620}, {128, 5640}, {132, 5660}, {136, 5680},
{140, 5700},
/* Japan MMAC */
{34, 5170}, {38, 5190}, {42, 5210}, {46, 5230},
/* Japan */
{184, 4920}, {188, 4940}, {192, 4960}, {196, 4980},
{208, 5040},/* Japan, means J08 */
{212, 5060},/* Japan, means J12 */
{216, 5080},/* Japan, means J16 */
};
static int ch_freq_map_num = (sizeof(ch_freq_map) / sizeof(struct ch_freq));
u32 rtw_ch2freq(u32 channel)
{
u8 i;
u32 freq = 0;
for (i = 0; i < ch_freq_map_num; i++) {
if (channel == ch_freq_map[i].channel) {
freq = ch_freq_map[i].frequency;
break;
}
}
if (i == ch_freq_map_num)
freq = 2412;
return freq;
}
u32 rtw_freq2ch(u32 freq)
{
u8 i;
u32 ch = 0;
for (i = 0; i < ch_freq_map_num; i++) {
if (freq == ch_freq_map[i].frequency) {
ch = ch_freq_map[i].channel;
break;
}
}
if (i == ch_freq_map_num)
ch = 1;
return ch;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#include <rtw_sreset.h>
void sreset_init_value(struct adapter *padapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
_rtw_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_value(struct adapter *padapter)
{
struct hal_data_8188e *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_status(struct adapter *padapter)
{
struct hal_data_8188e *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_88E("txdmastatu(%x)\n", val32);
psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
}
if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
DBG_88E("==>%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_88E("==> %s wifi_status(0x%x)\n", __func__, status);
/* status restore */
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
return status;
}
void sreset_set_wifi_error_status(struct adapter *padapter, u32 status)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status = status;
}

View File

@ -0,0 +1,609 @@
/******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#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>
static 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_queue(&psta->sleep_q);
psta->sleepq_len = 0;
_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
#ifdef CONFIG_88EU_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;
#ifdef CONFIG_88EU_AP_MODE
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;
#endif
psta->under_exist_checking = 0;
psta->keep_alive_trycnt = 0;
#endif /* CONFIG_88EU_AP_MODE */
}
u32 _rtw_init_sta_priv(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 -
((size_t)(pstapriv->pallocated_stainfo_buf) & 3);
_rtw_init_queue(&pstapriv->free_sta_queue);
spin_lock_init(&pstapriv->sta_hash_lock);
pstapriv->asoc_sta_count = 0;
_rtw_init_queue(&pstapriv->sleep_q);
_rtw_init_queue(&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_88EU_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 = 3; /* 3*2 = 6 sec */
pstapriv->max_num_sta = NUM_STA;
#endif
return _SUCCESS;
}
inline int rtw_stainfo_offset(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_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
return offset;
}
inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
{
if (!stainfo_offset_valid(offset))
DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
}
void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv);
void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv)
{
_rtw_spinlock_free(&psta_xmitpriv->lock);
_rtw_spinlock_free(&(psta_xmitpriv->be_q.sta_pending.lock));
_rtw_spinlock_free(&(psta_xmitpriv->bk_q.sta_pending.lock));
_rtw_spinlock_free(&(psta_xmitpriv->vi_q.sta_pending.lock));
_rtw_spinlock_free(&(psta_xmitpriv->vo_q.sta_pending.lock));
}
static void _rtw_free_sta_recv_priv_lock(struct sta_recv_priv *psta_recvpriv)
{
_rtw_spinlock_free(&psta_recvpriv->lock);
_rtw_spinlock_free(&(psta_recvpriv->defrag_q.lock));
}
void rtw_mfree_stainfo(struct sta_info *psta);
void rtw_mfree_stainfo(struct sta_info *psta)
{
if (&psta->lock != NULL)
_rtw_spinlock_free(&psta->lock);
_rtw_free_sta_xmit_priv_lock(&psta->sta_xmitpriv);
_rtw_free_sta_recv_priv_lock(&psta->sta_recvpriv);
}
/* this function is used to free the memory of lock || sema for all stainfos */
void rtw_mfree_all_stainfo(struct sta_priv *pstapriv);
void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
{
struct list_head *plist, *phead;
struct sta_info *psta = NULL;
spin_lock_bh(&pstapriv->sta_hash_lock);
phead = get_list_head(&pstapriv->free_sta_queue);
plist = phead->next;
while (phead != plist) {
psta = container_of(plist, struct sta_info , list);
plist = plist->next;
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
}
static void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
{
#ifdef CONFIG_88EU_AP_MODE
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
#endif
rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
_rtw_spinlock_free(&pstapriv->free_sta_queue.lock);
_rtw_spinlock_free(&pstapriv->sta_hash_lock);
_rtw_spinlock_free(&pstapriv->wakeup_q.lock);
_rtw_spinlock_free(&pstapriv->sleep_q.lock);
#ifdef CONFIG_88EU_AP_MODE
_rtw_spinlock_free(&pstapriv->asoc_list_lock);
_rtw_spinlock_free(&pstapriv->auth_list_lock);
_rtw_spinlock_free(&pacl_list->acl_node_q.lock);
#endif
}
u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
{
struct list_head *phead, *plist;
struct sta_info *psta = NULL;
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]);
plist = phead->next;
while (phead != plist) {
int i;
psta = container_of(plist, struct sta_info , hash_list);
plist = plist->next;
for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
_cancel_timer_ex(&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_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
s32 index;
struct list_head *phash_list;
struct sta_info *psta;
struct __queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
int i = 0;
u16 wRxSeqInitialValue = 0xffff;
pfree_sta_queue = &pstapriv->free_sta_queue;
spin_lock_bh(&pfree_sta_queue->lock);
if (list_empty(&pfree_sta_queue->queue)) {
spin_unlock_bh(&pfree_sta_queue->lock);
psta = NULL;
} else {
psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
list_del_init(&(psta->list));
spin_unlock_bh(&pfree_sta_queue->lock);
_rtw_init_stainfo(psta);
memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
index = wifi_mac_hash(hwaddr);
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index=%x", index));
if (index >= NUM_STA) {
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
psta = NULL;
goto exit;
}
phash_list = &(pstapriv->sta_hash[index]);
spin_lock_bh(&pstapriv->sta_hash_lock);
list_add_tail(&psta->hash_list, phash_list);
pstapriv->asoc_sta_count++ ;
spin_unlock_bh(&pstapriv->sta_hash_lock);
/* Commented by Albert 2009/08/13 */
/* 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_timer(pstapriv->padapter, 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 = 64;/* 64; */
_rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
rtw_init_recv_timer(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:
return psta;
}
/* using pstapriv->sta_hash_lock to protect */
u32 rtw_free_stainfo(struct adapter *padapter , struct sta_info *psta)
{
int i;
struct __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;
if (psta == NULL)
goto exit;
pfree_sta_queue = &pstapriv->free_sta_queue;
pstaxmitpriv = &psta->sta_xmitpriv;
spin_lock_bh(&pxmitpriv->lock);
rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
psta->sleepq_len = 0;
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
list_del_init(&(pstaxmitpriv->be_q.tx_pending));
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 */
_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
_cancel_timer_ex(&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 __queue *ppending_recvframe_queue;
struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
preorder_ctrl = &psta->recvreorder_ctrl[i];
_cancel_timer_ex(&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_recvframe(prframe, pfree_recv_queue);
}
spin_unlock_bh(&ppending_recvframe_queue->lock);
}
if (!(psta->state & WIFI_AP_STATE))
rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
#ifdef CONFIG_88EU_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 &= ~BIT(psta->aid);
pstapriv->tim_bitmap &= ~BIT(psta->aid);
if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
pstapriv->sta_aid[psta->aid - 1] = NULL;
psta->aid = 0;
}
psta->under_exist_checking = 0;
#endif /* CONFIG_88EU_AP_MODE */
spin_lock_bh(&pfree_sta_queue->lock);
list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
spin_unlock_bh(&pfree_sta_queue->lock);
exit:
return _SUCCESS;
}
/* free all stainfo which in sta_hash[all] */
void rtw_free_all_stainfo(struct adapter *padapter)
{
struct list_head *plist, *phead;
s32 index;
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
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]);
plist = phead->next;
while (phead != plist) {
psta = container_of(plist, struct sta_info , hash_list);
plist = plist->next;
if (pbcmc_stainfo != psta)
rtw_free_stainfo(padapter , psta);
}
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
}
/* any station allocated can be searched by hash list */
struct sta_info *rtw_get_stainfo(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_MCAST(hwaddr))
addr = bc_addr;
else
addr = hwaddr;
index = wifi_mac_hash(addr);
spin_lock_bh(&pstapriv->sta_hash_lock);
phead = &(pstapriv->sta_hash[index]);
plist = phead->next;
while (phead != plist) {
psta = container_of(plist, struct sta_info, hash_list);
if ((!memcmp(psta->hwaddr, addr, ETH_ALEN))) {
/* if found the matched address */
break;
}
psta = NULL;
plist = plist->next;
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
return psta;
}
u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
{
struct sta_info *psta;
u32 res = _SUCCESS;
unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct sta_priv *pstapriv = &padapter->stapriv;
psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
if (psta == NULL) {
res = _FAIL;
RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
goto exit;
}
/* default broadcast & multicast use macid 1 */
psta->mac_id = 1;
exit:
return res;
}
struct sta_info *rtw_get_bcmc_stainfo(struct 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_stainfo(pstapriv, bc_addr);
return psta;
}
u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
{
u8 res = true;
#ifdef CONFIG_88EU_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 __queue *pacl_node_q = &pacl_list->acl_node_q;
spin_lock_bh(&pacl_node_q->lock);
phead = get_list_head(pacl_node_q);
plist = phead->next;
while (phead != plist) {
paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
plist = plist->next;
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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff