diff options
author | david woo <xinhua_wu@realsil.com.cn> | 2009-12-22 17:40:36 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-04 00:42:30 (GMT) |
commit | 65a4378471510787e080188f933913315f1afa0c (patch) | |
tree | f28d6d19bf4cdfa0722ef7284365f1b787f52d8a /drivers/staging/rtl8192e/ieee80211 | |
parent | 789d9dbdad5cb24fbf0c0e4fa5c5f1b792e4e81e (diff) | |
download | linux-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.h | 156 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c | 6 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c | 96 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c | 244 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c | 26 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c | 76 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h | 4 | ||||
-rw-r--r-- | drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c | 63 |
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 |