12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/****************************************************************************** 22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * rtl8712_cmd.c 32865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 42865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. 52865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Linux device driver for RTL8192SU 62865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 72865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is free software; you can redistribute it and/or modify it 82865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * under the terms of version 2 of the GNU General Public License as 92865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * published by the Free Software Foundation. 102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT 122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * more details. 152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * You should have received a copy of the GNU General Public License along with 172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * this program; if not, write to the Free Software Foundation, Inc., 182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Modifications for inclusion into the Linux staging tree are 212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2010 Larry Finger. All rights reserved. 222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Contact information: 242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * WLAN FAE <wlanfae@realtek.com>. 252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Larry Finger <Larry.Finger@lwfinger.net> 262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ******************************************************************************/ 282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define _RTL8712_CMD_C_ 302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 31359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/compiler.h> 32359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/kernel.h> 33359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/errno.h> 34359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/slab.h> 35359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/module.h> 36359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/kref.h> 37359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/netdevice.h> 38359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/skbuff.h> 39359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/usb.h> 40359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/usb/ch9.h> 41359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/circ_buf.h> 42359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/uaccess.h> 43359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <asm/byteorder.h> 44359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/atomic.h> 45359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/semaphore.h> 46359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/rtnetlink.h> 47359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar 482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h" 492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h" 502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "recv_osdep.h" 512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "mlme_osdep.h" 522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "rtl871x_ioctl_set.h" 532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void check_hw_pbc(struct _adapter *padapter) 552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 tmp1byte; 572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write8(padapter, MAC_PINMUX_CTRL, (GPIOMUX_EN | GPIOSEL_GPIO)); 592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmp1byte = r8712_read8(padapter, GPIO_IO_SEL); 602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmp1byte &= ~(HAL_8192S_HW_GPIO_WPS_BIT); 612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write8(padapter, GPIO_IO_SEL, tmp1byte); 622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmp1byte = r8712_read8(padapter, GPIO_CTRL); 632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (tmp1byte == 0xff) 6477e73e8c90aded3215ecb4d05b9c91ec94349b61Thomas Cort return; 652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (tmp1byte&HAL_8192S_HW_GPIO_WPS_BIT) { 662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* Here we only set bPbcPressed to true 672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * After trigger PBC, the variable will be set to false */ 682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger DBG_8712("CheckPbcGPIO - PBC is pressed !!!!\n"); 692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* 0 is the default value and it means the application monitors 70be10ac2b961e348919ce09d2b88471116d865087Justin P. Mattock * the HW PBC doesn't provide its pid to driver. */ 712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (padapter->pid == 0) 722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger kill_pid(find_vpid(padapter->pid), SIGUSR1, 1); 742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* query rx phy status from fw. 782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Adhoc mode: beacon. 792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Infrastructure mode: beacon , data. */ 802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void query_fw_rx_phy_status(struct _adapter *padapter) 812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 val32 = 0; 832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int pollingcnts = 50; 842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true) { 862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write32(padapter, IOCMD_CTRL_REG, 0xf4000001); 872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger msleep(100); 882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* Wait FW complete IO Cmd */ 892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger while ((r8712_read32(padapter, IOCMD_CTRL_REG)) && 902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pollingcnts > 0)) { 912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pollingcnts--; 922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger msleep(20); 932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pollingcnts != 0) 952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger val32 = r8712_read32(padapter, IOCMD_DATA_REG); 962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else /* time out */ 972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger val32 = 0; 982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger val32 = val32 >> 4; 992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->recvpriv.fw_rssi = 1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (u8)r8712_signal_scale_mapping(val32); 1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* check mlme, hw, phy, or dynamic algorithm status. */ 1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void StatusWatchdogCallback(struct _adapter *padapter) 1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger check_hw_pbc(padapter); 1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger query_fw_rx_phy_status(padapter); 1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void r871x_internal_cmd_hdl(struct _adapter *padapter, u8 *pbuf) 1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct drvint_cmd_parm *pdrvcmd; 1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!pbuf) 1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdrvcmd = (struct drvint_cmd_parm *)pbuf; 1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pdrvcmd->i_cid) { 1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case WDG_WK_CID: 1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger StatusWatchdogCallback(padapter); 1212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger kfree(pdrvcmd->pbuf); 1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 read_macreg_hdl(struct _adapter *padapter, u8 *pbuf) 1292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* invoke cmd->callback function */ 1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 1392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 1402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 write_macreg_hdl(struct _adapter *padapter, u8 *pbuf) 1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* invoke cmd->callback function */ 1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 1512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) 1572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 val; 1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct readBB_parm *prdbbparm; 1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger prdbbparm = (struct readBB_parm *)pcmd->parmbuf; 1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd->rsp && pcmd->rspsz > 0) 1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); 1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 1692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 1712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 1722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 write_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) 1752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 1772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct writeBB_parm *pwritebbparm; 1782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 1792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pwritebbparm = (struct writeBB_parm *)pcmd->parmbuf; 1812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 1822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 1832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 1842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 1862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 1872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 read_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) 1902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 val; 1922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 1932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct readRF_parm *prdrfparm; 1942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 1952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger prdrfparm = (struct readRF_parm *)pcmd->parmbuf; 1972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd->rsp && pcmd->rspsz > 0) 1982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); 1992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 2002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 2012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 2022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 2032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 2042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 2052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 write_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) 2082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 2102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct writeRF_parm *pwriterfparm; 2112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 2122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pwriterfparm = (struct writeRF_parm *)pcmd->parmbuf; 2142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd->cmdcode].callback; 2152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback == NULL) 2162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 2172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 2182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 2192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 2202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 sys_suspend_hdl(struct _adapter *padapter, u8 *pbuf) 2232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; 2252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_suspend_parm *psetusbsuspend; 2262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger psetusbsuspend = (struct usb_suspend_parm *)pcmd->parmbuf; 2282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 2292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return H2C_SUCCESS; 2302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, 2332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd) 2342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd_r; 2362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd == NULL) 2382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return pcmd; 2392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = NULL; 2402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pcmd->cmdcode) { 2422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Read_MACREG): 2432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger read_macreg_hdl(padapter, (u8 *)pcmd); 2442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = pcmd; 2452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Write_MACREG): 2472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger write_macreg_hdl(padapter, (u8 *)pcmd); 2482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = pcmd; 2492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Read_BBREG): 2512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger read_bbreg_hdl(padapter, (u8 *)pcmd); 2522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Write_BBREG): 2542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger write_bbreg_hdl(padapter, (u8 *)pcmd); 2552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Read_RFREG): 2572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger read_rfreg_hdl(padapter, (u8 *)pcmd); 2582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_Write_RFREG): 2602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger write_rfreg_hdl(padapter, (u8 *)pcmd); 2612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_SetUsbSuspend): 2632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sys_suspend_hdl(padapter, (u8 *)pcmd); 2642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case GEN_CMD_CODE(_JoinBss): 2662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_joinbss_reset(padapter); 2672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* Before set JoinBss_CMD to FW, driver must ensure FW is in 2682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * PS_MODE_ACTIVE. Directly write rpwm to radio on and assign 2692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * new pwr_mode to Driver, instead of use workitem to change 2702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * state. */ 2712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) { 2722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE; 2732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _enter_pwrlock(&(padapter->pwrctrlpriv.lock)); 2742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_set_rpwm(padapter, PS_STATE_S4); 2752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger up(&(padapter->pwrctrlpriv.lock)); 2762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = pcmd; 2782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _DRV_INT_CMD_: 2802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r871x_internal_cmd_hdl(padapter, pcmd->parmbuf); 2812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 2822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = NULL; 2832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 2852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_r = pcmd; 2862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */ 2892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u8 check_cmd_fifo(struct _adapter *padapter, uint sz) 2922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2938ffca9eae662004016a6d60a2a79ce93f81f150ePeter Senna Tschudin return _SUCCESS; 2942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd) 2972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int pollingcnts = 50; 2992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write32(pAdapter, IOCMD_CTRL_REG, cmd); 3012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger msleep(100); 3022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger while ((0 != r8712_read32(pAdapter, IOCMD_CTRL_REG)) && 3032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pollingcnts > 0)) { 3042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pollingcnts--; 3052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger msleep(20); 3062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pollingcnts == 0) 3082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return false; 3092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return true; 3102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag) 3132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (flag == 0) /* set */ 3152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write32(pAdapter, IOCMD_DATA_REG, *value); 3162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else /* query */ 3172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *value = r8712_read32(pAdapter, IOCMD_DATA_REG); 3182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_cmd_thread(void *context) 3212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_obj *pcmd; 3232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int cmdsz, wr_sz, *pcmdbuf, *prspbuf; 3242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_desc *pdesc; 3252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); 3262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)context; 3272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 3282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 329fee51243ee16e824742698903773f26e1ea48df1James A Shackleford allow_signal(SIGTERM); 3302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger while (1) { 3312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((_down_sema(&(pcmdpriv->cmd_queue_sema))) == _FAIL) 3322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((padapter->bDriverStopped == true) || 3342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (padapter->bSurpriseRemoved == true)) 3352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (r8712_register_cmd_alive(padapter) != _SUCCESS) 3372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger continue; 3382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger_next: 3392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd = r8712_dequeue_cmd(&(pcmdpriv->cmd_queue)); 3402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!(pcmd)) { 3412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_unregister_cmd_alive(padapter); 3422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger continue; 3432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmdbuf = (unsigned int *)pcmdpriv->cmd_buf; 3452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger prspbuf = (unsigned int *)pcmdpriv->rsp_buf; 3462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc = (struct tx_desc *)pcmdbuf; 3472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memset(pdesc, 0, TXDESC_SIZE); 3482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd = cmd_hdl_filter(padapter, pcmd); 3492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd) { /* if pcmd != NULL, cmd will be handled by f/w */ 3502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *) 3512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger &padapter->dvobjpriv; 3522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 blnPending = 0; 35302a29d2d9209ad24258432057886a5af5816c388Tapasweni Pathak 3542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmdpriv->cmd_issued_cnt++; 355d913e54ef08da6f831df47a45f2ca1b11579eba4James A Shackleford cmdsz = round_up(pcmd->cmdsz, 8); 3562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger wr_sz = TXDESC_SIZE + 8 + cmdsz; 3572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc->txdw0 |= cpu_to_le32((wr_sz-TXDESC_SIZE) & 3582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x0000ffff); 3592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pdvobj->ishighspeed) { 3602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((wr_sz % 512) == 0) 3612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnPending = 1; 3622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 3632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((wr_sz % 64) == 0) 3642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnPending = 1; 3652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (blnPending) /* 32 bytes for TX Desc - 8 offset */ 3672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + 3682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger OFFSET_SZ + 8) << OFFSET_SHT) & 3692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00ff0000); 3702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else { 3712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + 3722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger OFFSET_SZ) << 3732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger OFFSET_SHT) & 3742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00ff0000); 3752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 3772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pdesc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 3782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00001f00); 3792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmdbuf += (TXDESC_SIZE >> 2); 3802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) | 3812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pcmd->cmdcode << 16) | 3822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pcmdpriv->cmd_seq << 24)); 38377e73e8c90aded3215ecb4d05b9c91ec94349b61Thomas Cort pcmdbuf += 2; /* 8 bytes alignment */ 3842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 3852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger while (check_cmd_fifo(padapter, wr_sz) == _FAIL) { 3862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((padapter->bDriverStopped == true) || 3872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (padapter->bSurpriseRemoved == true)) 3882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger msleep(100); 3902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger continue; 3912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (blnPending) 3932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger wr_sz += 8; /* Append 8 bytes */ 3942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, 3952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (u8 *)pdesc); 3962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmdpriv->cmd_seq++; 3972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd->cmdcode == GEN_CMD_CODE(_CreateBss)) { 3982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd->res = H2C_SUCCESS; 3992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback = cmd_callback[pcmd-> 4002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger cmdcode].callback; 4012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd_callback) 4022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd_callback(padapter, pcmd); 4032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger continue; 4042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd->cmdcode == GEN_CMD_CODE(_SetPwrMode)) { 4062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (padapter->pwrctrlpriv.bSleep) { 4072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _enter_pwrlock(&(padapter-> 4082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pwrctrlpriv.lock)); 4092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_set_rpwm(padapter, PS_STATE_S2); 4102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger up(&padapter->pwrctrlpriv.lock); 4112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 414df353f61afb917ff66b2e784b0ffb85d0ebb29a4James A Shackleford if (list_empty(&pcmdpriv->cmd_queue.queue)) { 4152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_unregister_cmd_alive(padapter); 4162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger continue; 4172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else 4182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _next; 4192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else 4202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _next; 4212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger flush_signals_thread(); 4222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* free all cmd_obj resources */ 4242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger do { 4252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pcmd = r8712_dequeue_cmd(&(pcmdpriv->cmd_queue)); 4262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pcmd == NULL) 4272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_cmd_obj(pcmd); 4292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } while (1); 4302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger up(&pcmdpriv->terminate_cmdthread_sema); 4312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger thread_exit(); 4322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 4332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_event_handle(struct _adapter *padapter, uint *peventbuf) 4352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 4362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 evt_code, evt_seq; 4372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u16 evt_sz; 4382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void (*event_callback)(struct _adapter *dev, u8 *pbuf); 4392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct evt_priv *pevt_priv = &(padapter->evtpriv); 4402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (peventbuf == NULL) 4422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger evt_sz = (u16)(le32_to_cpu(*peventbuf) & 0xffff); 4442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger evt_seq = (u8)((le32_to_cpu(*peventbuf) >> 24) & 0x7f); 4452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger evt_code = (u8)((le32_to_cpu(*peventbuf) >> 16) & 0xff); 4462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* checking event sequence... */ 4472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((evt_seq & 0x7f) != pevt_priv->event_seq) { 4482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); 4492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* checking if event code is valid */ 4522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (evt_code >= MAX_C2HEVT) { 4532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = ((evt_seq+1) & 0x7f); 4542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if ((evt_code == GEN_EVT_CODE(_Survey)) && 4562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (evt_sz > sizeof(struct wlan_bssid_ex))) { 4572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = ((evt_seq+1)&0x7f); 4582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* checking if event size match the event parm size */ 4612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((wlanevents[evt_code].parmsize) && 4622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (wlanevents[evt_code].parmsize != evt_sz)) { 4632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = ((evt_seq+1)&0x7f); 4642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if ((evt_sz == 0) && (evt_code != GEN_EVT_CODE(_WPS_PBC))) { 4662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = ((evt_seq+1)&0x7f); 4672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _abort_event_; 4682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq++; /* update evt_seq */ 4702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pevt_priv->event_seq > 127) 4712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->event_seq = 0; 47257b6686ebbf55d3f44d02c72d0d87f5d12032a08Tapasweni Pathak /* move to event content, 8 bytes alignment */ 47357b6686ebbf55d3f44d02c72d0d87f5d12032a08Tapasweni Pathak peventbuf = peventbuf + 2; 474a376932a93961db2024e0def126d3a9c9b6f37feDan Carpenter event_callback = wlanevents[evt_code].event_callback; 475a376932a93961db2024e0def126d3a9c9b6f37feDan Carpenter if (event_callback) 476a376932a93961db2024e0def126d3a9c9b6f37feDan Carpenter event_callback(padapter, (u8 *)peventbuf); 4772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pevt_priv->evt_done_cnt++; 4782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger_abort_event_: 4792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 4802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 481