summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8192e/ieee80211
diff options
context:
space:
mode:
authordavid woo <xinhua_wu@realsil.com.cn>2009-12-22 17:40:36 (GMT)
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-04 00:42:30 (GMT)
commit65a4378471510787e080188f933913315f1afa0c (patch)
treef28d6d19bf4cdfa0722ef7284365f1b787f52d8a /drivers/staging/rtl8192e/ieee80211
parent789d9dbdad5cb24fbf0c0e4fa5c5f1b792e4e81e (diff)
downloadlinux-fsl-qoriq-65a4378471510787e080188f933913315f1afa0c.tar.xz
Staging: rtl9192e: fix power usage issues
This patch should allow the driver to consume a lot less power. Signed-off-by: david woo <xinhua_wu@realsil.com.cn> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rtl8192e/ieee80211')
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h156
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c6
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c96
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c244
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c26
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c76
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h4
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c63
8 files changed, 603 insertions, 68 deletions
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index 9d91ab9..5859f66 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -180,6 +180,8 @@ typedef struct cb_desc {
u8 DrvAggrNum;
u16 pkt_size;
u8 reserved12;
+
+ u8 bdhcp;
}cb_desc, *pcb_desc;
/*--------------------------Define -------------------------------------------*/
@@ -740,6 +742,8 @@ struct ieee80211_snap_hdr {
#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA)
+
#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
@@ -1052,7 +1056,7 @@ struct ieee80211_device;
#define SEC_ALG_NONE 0
#define SEC_ALG_WEP 1
#define SEC_ALG_TKIP 2
-#define SEC_ALG_CCMP 3
+#define SEC_ALG_CCMP 4
#define WEP_KEYS 4
#define WEP_KEY_LEN 13
@@ -1121,6 +1125,14 @@ enum ieee80211_mfie {
/* Minimal header; can be used for passing 802.11 frames with sufficient
* information to determine what type of underlying data type is actually
* stored in the data. */
+ struct ieee80211_pspoll_hdr {
+ __le16 frame_ctl;
+ __le16 aid;
+ u8 bssid[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+ //u8 payload[0];
+} __attribute__ ((packed));
+
struct ieee80211_hdr {
__le16 frame_ctl;
__le16 duration_id;
@@ -1657,6 +1669,7 @@ struct ieee80211_network {
bool ralink_cap_exist;
bool atheros_cap_exist;
bool cisco_cap_exist;
+ bool marvell_cap_exist;
bool unknown_cap_exist;
// u8 berp_info;
bool berp_info_valid;
@@ -1862,6 +1875,19 @@ typedef struct _RT_POWER_SAVE_CONTROL
// Leisre Poswer Save : Disable RF if connected but traffic is not busy
//
bool bLeisurePs;
+ u32 PowerProfile;
+ u8 LpsIdleCount;
+ u8 RegMaxLPSAwakeIntvl;
+ u8 LPSAwakeIntvl;
+
+ u32 CurPsLevel;
+ u32 RegRfPsLevel;
+
+ bool bFwCtrlLPS;
+ u8 FWCtrlPSMode;
+
+ bool LinkReqInIPSRFOffPgs;
+ bool BufConnectinfoBefore;
}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
@@ -1902,14 +1928,121 @@ typedef struct _RT_LINK_DETECT_T{
u32 NumTxOkInPeriod;
u32 NumRxOkInPeriod;
+ u32 NumRxUnicastOkInPeriod;
bool bBusyTraffic;
}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
+//added by amy 090330
+typedef enum _HW_VARIABLES{
+ HW_VAR_ETHER_ADDR,
+ HW_VAR_MULTICAST_REG,
+ HW_VAR_BASIC_RATE,
+ HW_VAR_BSSID,
+ HW_VAR_MEDIA_STATUS,
+ HW_VAR_SECURITY_CONF,
+ HW_VAR_BEACON_INTERVAL,
+ HW_VAR_ATIM_WINDOW,
+ HW_VAR_LISTEN_INTERVAL,
+ HW_VAR_CS_COUNTER,
+ HW_VAR_DEFAULTKEY0,
+ HW_VAR_DEFAULTKEY1,
+ HW_VAR_DEFAULTKEY2,
+ HW_VAR_DEFAULTKEY3,
+ HW_VAR_SIFS,
+ HW_VAR_DIFS,
+ HW_VAR_EIFS,
+ HW_VAR_SLOT_TIME,
+ HW_VAR_ACK_PREAMBLE,
+ HW_VAR_CW_CONFIG,
+ HW_VAR_CW_VALUES,
+ HW_VAR_RATE_FALLBACK_CONTROL,
+ HW_VAR_CONTENTION_WINDOW,
+ HW_VAR_RETRY_COUNT,
+ HW_VAR_TR_SWITCH,
+ HW_VAR_COMMAND, // For Command Register, Annie, 2006-04-07.
+ HW_VAR_WPA_CONFIG, //2004/08/23, kcwu, for 8187 Security config
+ HW_VAR_AMPDU_MIN_SPACE, // The spacing between sub-frame. Roger, 2008.07.04.
+ HW_VAR_SHORTGI_DENSITY, // The density for shortGI. Roger, 2008.07.04.
+ HW_VAR_AMPDU_FACTOR,
+ HW_VAR_MCS_RATE_AVAILABLE,
+ HW_VAR_AC_PARAM, // For AC Parameters, 2005.12.01, by rcnjko.
+ HW_VAR_ACM_CTRL, // For ACM Control, Annie, 2005-12-13.
+ HW_VAR_DIS_Req_Qsize, // For DIS_Reg_Qsize, Joseph
+ HW_VAR_CCX_CHNL_LOAD, // For CCX 2 channel load request, 2006.05.04.
+ HW_VAR_CCX_NOISE_HISTOGRAM, // For CCX 2 noise histogram request, 2006.05.04.
+ HW_VAR_CCX_CLM_NHM, // For CCX 2 parallel channel load request and noise histogram request, 2006.05.12.
+ HW_VAR_TxOPLimit, // For turbo mode related settings, added by Roger, 2006.12.07
+ HW_VAR_TURBO_MODE, // For turbo mode related settings, added by Roger, 2006.12.15.
+ HW_VAR_RF_STATE, // For change or query RF power state, 061214, rcnjko.
+ HW_VAR_RF_OFF_BY_HW, // For UI to query if external HW signal disable RF, 061229, rcnjko.
+ HW_VAR_BUS_SPEED, // In unit of bps. 2006.07.03, by rcnjko.
+ HW_VAR_SET_DEV_POWER, // Set to low power, added by LanHsin, 2007.
+
+ //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //1Attention Please!!!<11n or 8190 specific code should be put below this line>
+ //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ HW_VAR_RCR, //for RCR, David 2006,05,11
+ HW_VAR_RATR_0,
+ HW_VAR_RRSR,
+ HW_VAR_CPU_RST,
+ HW_VAR_CECHK_BSSID,
+ HW_VAR_LBK_MODE, // Set lookback mode, 2008.06.11. added by Roger.
+ // Set HW related setting for 11N AES bug.
+ HW_VAR_AES_11N_FIX,
+ // Set Usb Rx Aggregation
+ HW_VAR_USB_RX_AGGR,
+ HW_VAR_USER_CONTROL_TURBO_MODE,
+ HW_VAR_RETRY_LIMIT,
+#ifndef _RTL8192_EXT_PATCH_
+ HW_VAR_INIT_TX_RATE, //Get Current Tx rate register. 2008.12.10. Added by tynli
+#endif
+ HW_VAR_TX_RATE_REG, //Get Current Tx rate register. 2008.12.10. Added by tynli
+ HW_VAR_EFUSE_USAGE, //Get current EFUSE utilization. 2008.12.19. Added by Roger.
+ HW_VAR_EFUSE_BYTES,
+ HW_VAR_AUTOLOAD_STATUS, //Get current autoload status, 0: autoload success, 1: autoload fail. 2008.12.19. Added by Roger.
+ HW_VAR_RF_2R_DISABLE, // 2R disable
+ HW_VAR_SET_RPWM,
+ HW_VAR_H2C_FW_PWRMODE, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+ HW_VAR_H2C_FW_JOINBSSRPT, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+ HW_VAR_1X1_RECV_COMBINE, // For 1T2R but only 1SS, Add by hpfan 2009.04.16 hpfan
+ HW_VAR_STOP_SEND_BEACON,
+ HW_VAR_TSF_TIMER, // Read from TSF register to get the current TSF timer, by Bruce, 2009-07-22.
+ HW_VAR_IO_CMD,
+ HW_VAR_HANDLE_FW_C2H, //Added by tynli. For handling FW C2H command. 2009.10.07.
+ HW_VAR_DL_FW_RSVD_PAGE, //Added by tynli. Download the packets that FW will use to RSVD page. 2009.10.14.
+ HW_VAR_AID, //Added by tynli.
+ HW_VAR_HW_SEQ_ENABLE, //Added by tynli. 2009.10.20.
+ HW_VAR_UPDATE_TSF, //Added by tynli. 2009.10.22. For Hw count TBTT time.
+ HW_VAR_BCN_VALID, //Added by tynli.
+ HW_VAR_FWLPS_RF_ON //Added by tynli. 2009.11.09. For checking if Fw finishs RF on sequence.
+}HW_VARIABLES;
+
+#define RT_CHECK_FOR_HANG_PERIOD 2
struct ieee80211_device {
struct net_device *dev;
struct ieee80211_security sec;
+ bool need_sw_enc;
+#ifdef ENABLE_LPS
+ bool bAwakePktSent;
+ u8 LPSDelayCnt;
+ bool bIsAggregateFrame;
+ bool polling;
+ void (*LeisurePSLeave)(struct net_device *dev);
+#endif
+
+#ifdef ENABLE_IPS
+ bool proto_stoppping;
+ bool wx_set_enc;
+ struct semaphore ips_sem;
+ struct work_struct ips_leave_wq;
+ void (*ieee80211_ips_leave_wq) (struct net_device *dev);
+ void (*ieee80211_ips_leave)(struct net_device *dev);
+#endif
+ void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+ u8 (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
+
//hw security related
// u8 hwsec_support; //support?
u8 hwsec_active; //hw security active.
@@ -2316,7 +2449,7 @@ struct ieee80211_device {
* stop_send_bacons is NOT guaranteed to be called only
* after start_send_beacons.
*/
- void (*start_send_beacons) (struct net_device *dev,u16 tx_rate);
+ void (*start_send_beacons) (struct net_device *dev);
void (*stop_send_beacons) (struct net_device *dev);
/* power save mode related */
@@ -2370,6 +2503,19 @@ struct ieee80211_device {
u8 priv[0];
};
+#define RT_RF_OFF_LEVL_ASPM BIT0 // PCI ASPM
+#define RT_RF_OFF_LEVL_CLK_REQ BIT1 // PCI clock request
+#define RT_RF_OFF_LEVL_PCI_D3 BIT2 // PCI D3 mode
+#define RT_RF_OFF_LEVL_HALT_NIC BIT3 // NIC halt, re-initialize hw parameters
+#define RT_RF_OFF_LEVL_FREE_FW BIT4 // FW free, re-download the FW
+#define RT_RF_OFF_LEVL_FW_32K BIT5 // FW in 32k
+#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6 // Always enable ASPM and Clock Req in initialization.
+#define RT_RF_LPS_DISALBE_2R BIT30 // When LPS is on, disable 2R if no packet is received or transmittd.
+#define RT_RF_LPS_LEVEL_ASPM BIT31 // LPS with ASPM
+#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
+#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel &= (~(_PS_FLAG)))
+#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG)
+
#define IEEE_A (1<<0)
#define IEEE_B (1<<1)
#define IEEE_G (1<<2)
@@ -2606,9 +2752,9 @@ extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
@@ -2795,5 +2941,7 @@ extern int ieee80211_parse_info_param(struct ieee80211_device *ieee,
struct ieee80211_rx_stats *stats);
void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index);
+void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr);
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee);
#define RT_ASOC_RETRY_LIMIT 5
#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
index 609c289..70159cf 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -361,9 +361,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
- " previous PN %pm received PN %pm\n",
- hdr->addr2, key->rx_pn, pn);
+ //printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+ // " previous PN %pm received PN %pm\n",
+ // hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
index 7a500ac..ce265ae 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -312,6 +312,17 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
if (skb->len < 24)
return 0;
+#if 1
+ if (ieee->hwsec_active)
+ {
+ cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
+ tcb_desc->bHwSec = 1;
+
+ if(ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+ }
+#endif
+
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
@@ -406,6 +417,10 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
{
cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
tcb_desc->bHwSec = 1;
+
+ if(ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
@@ -799,7 +814,7 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
#endif
}
-u8 parse_subframe(struct sk_buff *skb,
+u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats,
struct ieee80211_rxb *rxb,u8* src,u8* dst)
{
@@ -839,6 +854,7 @@ u8 parse_subframe(struct sk_buff *skb,
}
skb_pull(skb, LLCOffset);
+ ieee->bIsAggregateFrame = bIsAggregateFrame;//added by amy for Leisure PS
if(!bIsAggregateFrame) {
rxb->nr_subframes = 1;
@@ -940,6 +956,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
u8 TID = 0;
u16 SeqNum = 0;
PRX_TS_RECORD pTS = NULL;
+ bool unicast_packet = false;
//bool bIsAggregateFrame = false;
//added by amy for reorder
#ifdef NOT_YET
@@ -1215,6 +1232,24 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
goto rx_dropped;
+#ifdef ENABLE_LPS
+ if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == 1)
+ && (ieee->polling)) {
+ if (WLAN_FC_MORE_DATA(fc)) {
+ /* more data bit is set, let's request a new frame from the AP */
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ } else {
+ ieee->polling = false;
+ }
+ }
+#endif
+
+ ieee->need_sw_enc = 0;
+
+ if((!rx_stats->Decrypted)){
+ ieee->need_sw_enc = 1;
+ }
+
/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
@@ -1296,6 +1331,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
ieee->LinkDetectInfo.NumRxOkInPeriod++;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
+ unicast_packet = true;
+
if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
if (/*ieee->ieee802_1x &&*/
ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
@@ -1367,7 +1405,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
}
/* to parse amsdu packets */
/* qos data packets & reserved bit is 1 */
- if(parse_subframe(skb,rx_stats,rxb,src,dst) == 0) {
+ if(parse_subframe(ieee, skb,rx_stats,rxb,src,dst) == 0) {
/* only to free rxb, and not submit the packets to upper layer */
for(i =0; i < rxb->nr_subframes; i++) {
dev_kfree_skb(rxb->subframes[i]);
@@ -1377,6 +1415,32 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
goto rx_dropped;
}
+#ifdef ENABLE_LPS
+ if(unicast_packet)
+ {
+ if (type == IEEE80211_FTYPE_DATA)
+ {
+
+ if(ieee->bIsAggregateFrame)
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
+ else
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
+
+ // 2009.03.03 Leave DC mode immediately when detect high traffic
+ // DbgPrint("ending Seq %d\n", Frame_SeqNum(pduOS));
+ if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+ {
+ if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+ (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+ {
+ if(ieee->LeisurePSLeave)
+ ieee->LeisurePSLeave(dev);
+ }
+ }
+ }
+ }
+#endif
+
ieee->last_rx_ps_time = jiffies;
//added by amy for reorder
if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
@@ -2013,12 +2077,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
info_element->data[1] == 0x13 &&
info_element->data[2] == 0x74))
{
- printk("========>%s(): athros AP is exist\n",__FUNCTION__);
+ //printk("========>%s(): athros AP is exist\n",__FUNCTION__);
network->atheros_cap_exist = true;
}
else
network->atheros_cap_exist = false;
+ if ((info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0x43) )
+ {
+ network->marvell_cap_exist = true;
+ //printk("========>%s(): marvel AP is exist\n",__FUNCTION__);
+ }
+
+
if(info_element->len >= 3 &&
info_element->data[0] == 0x00 &&
info_element->data[1] == 0x40 &&
@@ -2219,7 +2293,8 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
}
if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
- !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation)
+ !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation &&
+ !network->marvell_cap_exist)
{
network->unknown_cap_exist = true;
}
@@ -2333,6 +2408,7 @@ static inline int ieee80211_network_init(
network->broadcom_cap_exist = false;
network->ralink_cap_exist = false;
network->atheros_cap_exist = false;
+ network->marvell_cap_exist = false;
network->cisco_cap_exist = false;
network->unknown_cap_exist = false;
#ifdef THOMAS_TURBO
@@ -2463,6 +2539,7 @@ static inline void update_network(struct ieee80211_network *dst,
dst->broadcom_cap_exist = src->broadcom_cap_exist;
dst->ralink_cap_exist = src->ralink_cap_exist;
dst->atheros_cap_exist = src->atheros_cap_exist;
+ dst->marvell_cap_exist = src->marvell_cap_exist;
dst->cisco_cap_exist = src->cisco_cap_exist;
dst->unknown_cap_exist = src->unknown_cap_exist;
memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
@@ -2761,12 +2838,14 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
struct ieee80211_hdr_4addr *header,
struct ieee80211_rx_stats *stats)
{
+#if 0
if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
ieee->iw_mode == IW_MODE_INFRA &&
ieee->state == IEEE80211_LINKED))
{
tasklet_schedule(&ieee->ps_task);
}
+#endif
if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
@@ -2780,6 +2859,15 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
IEEE80211_DEBUG_SCAN("Beacon\n");
ieee80211_process_probe_response(
ieee, (struct ieee80211_probe_response *)header, stats);
+
+ //printk("----------->%s()\n", __func__);
+ if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
+ ieee->iw_mode == IW_MODE_INFRA &&
+ ieee->state == IEEE80211_LINKED))
+ {
+ tasklet_schedule(&ieee->ps_task);
+ }
+
break;
case IEEE80211_STYPE_PROBE_RESP:
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 9e923e2..ea96c49 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -646,7 +646,7 @@ void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
{
if(ieee->start_send_beacons)
- ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
+ ieee->start_send_beacons(ieee->dev);
if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
ieee80211_beacons_start(ieee);
}
@@ -686,6 +686,11 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
/* called with ieee->lock held */
void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
{
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
+
#ifdef ENABLE_DOT11D
if(IS_DOT11D_ENABLE(ieee) )
{
@@ -1093,6 +1098,40 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
}
+struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
+{
+ struct sk_buff *skb;
+ struct ieee80211_pspoll_hdr* hdr;
+
+#ifdef USB_USE_ALIGNMENT
+ u32 Tmpaddr=0;
+ int alignment=0;
+ skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else
+ skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
+#endif
+ if (!skb)
+ return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+ Tmpaddr = (u32)skb->data;
+ alignment = Tmpaddr & 0x1ff;
+ skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+ skb_reserve(skb, ieee->tx_headroom);
+
+ hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
+
+ memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
+ memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
+
+ hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
+ hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
+
+ return skb;
+
+}
+
void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
{
@@ -1582,6 +1621,11 @@ void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
{
#endif
ieee->sync_scan_hurryup = 1;
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave != NULL)
+ ieee->ieee80211_ips_leave(ieee->dev);
+#endif
+
down(&ieee->wx_sem);
if (ieee->data_hard_stop)
@@ -1592,6 +1636,17 @@ void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
//ieee->set_chan(ieee->dev, ieee->current_network.channel);
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+#ifdef ENABLE_IPS
+ if(ieee->eRFPowerState == eRfOff)
+ {
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+
+ up(&ieee->wx_sem);
+ return;
+ }
+#endif
+
ieee->associate_seq = 1;
ieee80211_associate_step1(ieee);
@@ -1918,43 +1973,92 @@ void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
}
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
+{
+
+ struct sk_buff *buf = ieee80211_pspoll_func(ieee);
+
+ if (buf)
+ softmac_ps_mgmt_xmit(buf, ieee);
+
+}
short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
{
int timeout = ieee->ps_timeout;
u8 dtim;
- /*if(ieee->ps == IEEE80211_PS_DISABLED ||
- ieee->iw_mode != IW_MODE_INFRA ||
- ieee->state != IEEE80211_LINKED)
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
+ if(ieee->LPSDelayCnt)
+ {
+ //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
+ ieee->LPSDelayCnt --;
return 0;
- */
+ }
+
dtim = ieee->current_network.dtim_data;
- //printk("DTIM\n");
+// printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
if(!(dtim & IEEE80211_DTIM_VALID))
return 0;
timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
//printk("VALID\n");
ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
-
- if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
+ /* there's no need to nofity AP that I find you buffered with broadcast packet */
+ if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
return 2;
- if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
+ if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
+// printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
return 0;
-
- if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
+ }
+ if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
+// printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
return 0;
-
+ }
if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
return 0;
if(time_l){
+ if(ieee->bAwakePktSent == true) {
+ pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
+ } else {
+ u8 MaxPeriod = 1;
+
+ if(pPSC->LPSAwakeIntvl == 0)
+ pPSC->LPSAwakeIntvl = 1;
+ //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
+ if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
+ MaxPeriod = 1; // 1 Beacon interval
+ else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
+ MaxPeriod = ieee->current_network.dtim_period;
+ else
+ MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
+ pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
+ }
+ {
+ u8 LPSAwakeIntvl_tmp = 0;
+ u8 period = ieee->current_network.dtim_period;
+ u8 count = ieee->current_network.tim.tim_count;
+ if(count == 0 ) {
+ if(pPSC->LPSAwakeIntvl > period)
+ LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+
+ } else {
+ if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
+ LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
+ }
+ //printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
+
*time_l = ieee->current_network.last_dtim_sta_time[0]
- + (ieee->current_network.beacon_interval);
+ + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
// * ieee->current_network.dtim_period) * 1000;
}
+ }
if(time_h){
*time_h = ieee->current_network.last_dtim_sta_time[1];
@@ -1982,6 +2086,8 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
ieee->state != IEEE80211_LINKED)){
// #warning CHECK_LOCK_HERE
+ printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
+ __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
ieee80211_sta_wakeup(ieee, 1);
@@ -1991,27 +2097,27 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
/* 2 wake, 1 sleep, 0 do nothing */
- if(sleep == 0)
+ if(sleep == 0)//it is not time out or dtim is not valid
+ {
+ //printk("===========>sleep is 0,do nothing\n");
goto out;
-
+ }
if(sleep == 1){
-
- if(ieee->sta_sleep == 1)
+ //printk("===========>sleep is 1,to sleep\n");
+ if(ieee->sta_sleep == 1){
+ //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
ieee->enter_sleep_state(ieee->dev,th,tl);
+ }
else if(ieee->sta_sleep == 0){
// printk("send null 1\n");
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
if(ieee->ps_is_queue_empty(ieee->dev)){
-
-
ieee->sta_sleep = 2;
-
ieee->ack_tx_to_ieee = 1;
-
+ //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
ieee80211_sta_ps_send_null_frame(ieee,1);
-
ieee->ps_th = th;
ieee->ps_tl = tl;
}
@@ -2019,11 +2125,13 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
}
+ ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
}else if(sleep == 2){
-//#warning CHECK_LOCK_HERE
+ //printk("==========>sleep is 2,to wakeup\n");
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+ //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
ieee80211_sta_wakeup(ieee,1);
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
@@ -2038,9 +2146,19 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
{
if(ieee->sta_sleep == 0){
if(nl){
- printk("Warning: driver is probably failing to report TX ps error\n");
- ieee->ack_tx_to_ieee = 1;
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+ //printk("Warning: driver is probably failing to report TX ps error\n");
+ ieee->ack_tx_to_ieee = 1;
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ ieee->ack_tx_to_ieee = 1;
+ //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
}
return;
@@ -2048,12 +2166,27 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
if(ieee->sta_sleep == 1)
ieee->sta_wake_up(ieee->dev);
+ if(nl){
- ieee->sta_sleep = 0;
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+ //printk("Warning: driver is probably failing to report TX ps error\n");
+ ieee->ack_tx_to_ieee = 1;
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ ieee->ack_tx_to_ieee = 1;
+ ieee->polling = true;
+ //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+ //ieee80211_sta_ps_send_null_frame(ieee, 0);
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
- if(nl){
- ieee->ack_tx_to_ieee = 1;
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ } else {
+ ieee->sta_sleep = 0;
+ ieee->polling = false;
}
}
@@ -2067,23 +2200,30 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
/* Null frame with PS bit set */
if(success){
ieee->sta_sleep = 1;
+ //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
}
- /* if the card report not success we can't be sure the AP
- * has not RXed so we can't assume the AP believe us awake
- */
- }
- /* 21112005 - tx again null without PS bit if lost */
- else {
+ } else {/* 21112005 - tx again null without PS bit if lost */
if((ieee->sta_sleep == 0) && !success){
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ //ieee80211_sta_ps_send_null_frame(ieee, 0);
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
}
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
+
void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
{
struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
@@ -2227,7 +2367,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
{
if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
{
- // WEP or TKIP encryption
+ // WEP or TKIP encryption
if(IsHTHalfNmodeAPs(ieee))
{
bSupportNmode = true;
@@ -2238,7 +2378,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
bSupportNmode = false;
bHalfSupportNmode = false;
}
- printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
+ printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
}
}
/* Dummy wirless mode setting to avoid encryption issue */
@@ -2574,6 +2714,7 @@ void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
ieee->ssid_set = 1;
}
+ ieee->state = IEEE80211_NOLINK;
/* check if we have this cell in our network list */
ieee80211_softmac_check_all_nets(ieee);
@@ -2705,6 +2846,10 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->state == IEEE80211_NOLINK){
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
ieee->actscanning = true;
ieee80211_rtl_start_scan(ieee);
}
@@ -2823,21 +2968,23 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
return skb;
}
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
{
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee, shutdown);
up(&ieee->wx_sem);
}
-void ieee80211_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
{
if (!ieee->proto_started)
return;
- ieee->proto_started = 0;
+ if(shutdown)
+ ieee->proto_started = 0;
+ ieee->proto_stoppping = 1;
ieee80211_stop_send_beacons(ieee);
del_timer_sync(&ieee->associate_timer);
@@ -2849,6 +2996,8 @@ void ieee80211_stop_protocol(struct ieee80211_device *ieee)
ieee80211_disassociate(ieee);
RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
+
+ ieee->proto_stoppping = 0;
}
void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
@@ -2894,6 +3043,8 @@ void ieee80211_start_protocol(struct ieee80211_device *ieee)
ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
+ ieee->state = IEEE80211_NOLINK;
+
/* if the user set the MAC of the ad-hoc cell and then
* switch to managed mode, shall we make sure that association
@@ -3013,7 +3164,9 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
#endif
sema_init(&ieee->wx_sem, 1);
sema_init(&ieee->scan_sem, 1);
-
+#ifdef ENABLE_IPS
+ sema_init(&ieee->ips_sem,1);
+#endif
spin_lock_init(&ieee->mgmt_tx_lock);
spin_lock_init(&ieee->beacon_lock);
@@ -3537,5 +3690,6 @@ EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);
#endif
-//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
index 7c21aaa..1bbd49f 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -160,7 +160,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
}
if (ifup)
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee,true);
/* just to avoid to give inconsistent infos in the
* get wx method. not really needed otherwise
@@ -302,7 +302,7 @@ int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info
if (!ieee->proto_started){
ieee->iw_mode = wrqu->mode;
}else{
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee,true);
ieee->iw_mode = wrqu->mode;
ieee80211_start_protocol(ieee);
}
@@ -326,6 +326,17 @@ void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee)
int b40M = 0;
static int count = 0;
chan = ieee->current_network.channel;
+
+#ifdef ENABLE_LPS
+ if (ieee->LeisurePSLeave) {
+ ieee->LeisurePSLeave(ieee->dev);
+ }
+
+ /* notify AP to be in PS mode */
+ ieee80211_sta_ps_send_null_frame(ieee, 1);
+ ieee80211_sta_ps_send_null_frame(ieee, 1);
+#endif
+
netif_carrier_off(ieee->dev);
if (ieee->data_hard_stop)
@@ -360,6 +371,12 @@ void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee)
ieee->InitialGainHandler(ieee->dev,IG_Restore);
ieee->state = IEEE80211_LINKED;
ieee->link_change(ieee->dev);
+
+#ifdef ENABLE_LPS
+ /* Notify AP that I wake up again */
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+#endif
+
// To prevent the immediately calling watch_dog after scan.
if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
{
@@ -429,8 +446,9 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
goto out;
}
- if(proto_started)
- ieee80211_stop_protocol(ieee);
+ if(proto_started){
+ ieee80211_stop_protocol(ieee,true);
+ }
/* this is just to be sure that the GET wx callback
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
index 0710d9e..a75f366 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -334,6 +334,13 @@ void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* s
if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
return;
#endif
+
+ if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
+ {
+ return;
+ }
+
+
#if 1
if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
{
@@ -628,6 +635,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
int qos_actived = ieee->current_network.qos_data.active;
struct ieee80211_crypt_data* crypt;
+ bool bdhcp =false;
cb_desc *tcb_desc;
@@ -672,6 +680,55 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
}
#endif
+ // The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
+ // to prevent DHCP protocol fail
+ if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
+ if (ETH_P_IP == ether_type) {// IP header
+ const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
+ if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
+ struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
+ //if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) ||
+ /// ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) {
+ if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
+ ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
+ // 68 : UDP BOOTP client
+ // 67 : UDP BOOTP server
+ printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
+ // Use low rate to send DHCP packet.
+ //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+ //{
+ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = false;
+ //}
+ //else
+ //pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate;
+ //RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+ bdhcp = true;
+#ifdef _RTL8192_EXT_PATCH_
+ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
+#else
+ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
+#endif
+ }
+ }
+ }else if(ETH_P_ARP == ether_type){// IP ARP packet
+ printk("=================>DHCP Protocol start tx ARP pkt!!\n");
+ bdhcp = true;
+ ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
+
+ //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+ //{
+ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = FALSE;
+ //}
+ //else
+ // tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate;
+ //RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+ }
+ }
+
/* Save source and destination addresses */
memcpy(&dest, skb->data, ETH_ALEN);
memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
@@ -895,6 +952,25 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
else
//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
+
+ if(bdhcp == true){
+ // Use low rate to send DHCP packet.
+ //if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
+ // tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = false;
+ //}
+ //else
+ {
+ tcb_desc->data_rate = MGN_1M;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ }
+
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ tcb_desc->bdhcp = 1;
+ }
+
+
ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
ieee80211_query_HTCapShortGI(ieee, tcb_desc);
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
index 992b718..f968817 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
@@ -458,7 +458,8 @@ typedef enum _HT_IOT_PEER
HT_IOT_PEER_RALINK = 3,
HT_IOT_PEER_ATHEROS = 4,
HT_IOT_PEER_CISCO= 5,
- HT_IOT_PEER_MAX = 6
+ HT_IOT_PEER_MARVELL=6,
+ HT_IOT_PEER_MAX = 7
}HT_IOT_PEER_E, *PHTIOT_PEER_E;
//
@@ -475,6 +476,7 @@ typedef enum _HT_IOT_ACTION{
HT_IOT_ACT_CDD_FSYNC = 0x00000080,
HT_IOT_ACT_PURE_N_MODE = 0x00000100,
HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
#endif //_RTL819XU_HTTYPE_H_
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
index 1e39214..c932473 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -32,7 +32,7 @@ u16 MCS_DATA_RATE[2][2][77] =
static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
-static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
+//static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; //cosa 03202008
static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
@@ -40,6 +40,7 @@ static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
// code in other place??
@@ -349,12 +350,12 @@ bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
bool retValue = false;
struct ieee80211_network* net = &ieee->current_network;
#if 0
- if(pMgntInfo->bHalfNMode == false)
+ if(ieee->bHalfNMode == false)
retValue = false;
else
#endif
if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
- (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
+ (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
(memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
(memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
@@ -363,7 +364,7 @@ bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
(memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
- (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
+ //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
(net->broadcom_cap_exist))
retValue = true;
else if(net->bssht.bdRT2RTAggregation)
@@ -387,13 +388,15 @@ void HTIOTPeerDetermine(struct ieee80211_device* ieee)
struct ieee80211_network* net = &ieee->current_network;
if(net->bssht.bdRT2RTAggregation)
pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
- else if(net->broadcom_cap_exist)
+ else if(net->broadcom_cap_exist){
pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ }
else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
- (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
- (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) )
+ (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)){//||
+ //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ){
pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ }
else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
(memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
@@ -405,6 +408,10 @@ void HTIOTPeerDetermine(struct ieee80211_device* ieee)
pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0)
pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
+ else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
+ net->marvell_cap_exist){
+ pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
+ }
else
pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
@@ -442,6 +449,18 @@ u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr)
return ret;
}
+u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_network *network)
+{
+ u8 retValue = 0;
+ //if(network->marvell_cap_exist)
+ if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+ {
+ retValue = 1;
+ }
+
+ return retValue;
+}
+
/**
* Function: HTIOTActIsDisableMCS15
@@ -578,6 +597,23 @@ u8 HTIOTActIsCCDFsync(u8* PeerMacAddr)
return retValue;
}
+//
+// Send null data for to tell AP that we are awake.
+//
+bool
+HTIOTActIsNullDataPowerSaving(struct ieee80211_device* ieee,struct ieee80211_network *network)
+{
+ bool retValue = false;
+
+ PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+ {
+ if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) // ||(pBssDesc->Vender == HT_IOT_PEER_ATHEROS && pBssDesc->SubTypeOfVender == HT_IOT_PEER_ATHEROS_DIR635))
+ return true;
+
+ }
+ return retValue;
+}
+
void HTResetIOTSetting(
PRT_HIGH_THROUGHPUT pHTInfo
)
@@ -1071,6 +1107,13 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
// Config and configure A-MSDU setting
//
pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+ if (ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
+ if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
+ (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
+ pHTInfo->bCurrentAMPDUEnable = false;
+ }
+
nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
@@ -1515,6 +1558,9 @@ void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80
bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
if(bIOTAction)
pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
+ bIOTAction = HTIOTActIsForcedCTS2Self(ieee, pNetwork);
+ if(bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
bIOTAction = HTIOTActIsDisableMCS15(ieee);
if(bIOTAction)
@@ -1537,6 +1583,9 @@ void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80
if(bIOTAction)
pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
+ bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
+ if(bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
}
else