Staging: rtl9192e: fix power usage issues
authordavid woo <xinhua_wu@realsil.com.cn>
Tue, 22 Dec 2009 17:40:36 +0000 (09:40 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:42:30 +0000 (16:42 -0800)
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>
18 files changed:
drivers/staging/rtl8192e/Makefile
drivers/staging/rtl8192e/ieee80211/ieee80211.h
drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
drivers/staging/rtl8192e/r8190_rtl8256.c
drivers/staging/rtl8192e/r8192E.h
drivers/staging/rtl8192e/r8192E_core.c
drivers/staging/rtl8192e/r8192E_dm.c
drivers/staging/rtl8192e/r8192E_hw.h
drivers/staging/rtl8192e/r8192E_wx.c
drivers/staging/rtl8192e/r8192E_wx.h
drivers/staging/rtl8192e/r819xE_phy.c
drivers/staging/rtl8192e/r819xE_phyreg.h

index 5e4aa95..e032c3e 100644 (file)
@@ -1,13 +1,15 @@
 NIC_SELECT = RTL8192E
 
-
 EXTRA_CFLAGS += -DRTL8192E
 EXTRA_CFLAGS += -std=gnu89
 EXTRA_CFLAGS += -O2
 EXTRA_CFLAGS += -DTHOMAS_TURBO
 EXTRA_CFLAGS += -DENABLE_DOT11D
 
-r8192_pci-objs :=              \
+EXTRA_CFLAGS += -DENABLE_IPS
+EXTRA_CFLAGS += -DENABLE_LPS
+
+r8192e_pci-objs :=             \
        r8192E_core.o           \
        r8180_93cx6.o           \
        r8192E_wx.o             \
@@ -31,4 +33,5 @@ r8192_pci-objs :=             \
        ieee80211/ieee80211_crypt_ccmp.o        \
        ieee80211/ieee80211_crypt_wep.o
 
-obj-$(CONFIG_RTL8192E) += r8192_pci.o
+obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+
index 9d91ab9..5859f66 100644 (file)
@@ -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 */
index 609c289..70159cf 100644 (file)
@@ -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;
index 7a500ac..ce265ae 100644 (file)
@@ -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:
index 9e923e2..ea96c49 100644 (file)
@@ -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);
index 7c21aaa..1bbd49f 100644 (file)
@@ -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
index 0710d9e..a75f366 100644 (file)
@@ -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);
index 992b718..f968817 100644 (file)
@@ -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_
index 1e39214..c932473 100644 (file)
@@ -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
index 3d67fbb..1bd054d 100644 (file)
@@ -429,11 +429,12 @@ SetRFPowerState8190(
        bool bResult = true;
        //u8 eRFPath;
        u8      i = 0, QueueID = 0;
-       ptx_ring        head=NULL,tail=NULL;
+       //ptx_ring      head=NULL,tail=NULL;
+       struct rtl8192_tx_ring  *ring = NULL;
 
        if(priv->SetRFPowerStateInProgress == true)
                return false;
-       RT_TRACE(COMP_POWER, "===========> SetRFPowerState8190()!\n");
+       //RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
        priv->SetRFPowerStateInProgress = true;
 
        switch(priv->rf_chip)
@@ -442,11 +443,11 @@ SetRFPowerState8190(
                switch( eRFPowerState )
                {
                        case eRfOn:
-                               RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOn !\n");
+                               //RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOn !\n");
                                                //RXTX enable control: On
                                        //for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
-                                       //      PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
-                               #ifdef RTL8190P
+                                       //      PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
+#ifdef RTL8190P
                                if(priv->rf_type == RF_2T4R)
                                {
                                        //enable RF-Chip A/B
@@ -479,36 +480,92 @@ SetRFPowerState8190(
                                        //analog to digital part2 on
                                        rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1800, 0x3); // 0x880[12:11]
                                }
-                               #else
-                               write_nic_byte(dev, ANAPAR, 0x37);//160MHz
-                               write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
-                               mdelay(1);
-                               //enable clock 80/88 MHz
-
-                               priv->bHwRfOffAction = 0;
-                               //}
-
-                               // Baseband reset 2008.09.30 add
-                               write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
-
-                               //2 AFE
-                               // 2008.09.30 add
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
-                               //analog to digital part2 on
-                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);              // 0x880[6:5]
-                               //digital to analog on
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
-                               //analog to digital on
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
-                               //rx antenna on
-                               //PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
-                               //rx antenna on 2008.09.30 mark
-                               //PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
-
-                               //2 RF
-                               //enable RF-Chip A/B
+                               else if(priv->rf_type == RF_1T1R)       //RF-C
+                               {
+                                       //enable RF-Chip C/D
+                                       rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
+                                       //analog to digital on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x400, 0x1);// 0x88c[10]
+                                       //digital to analog on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x80, 0x1); // 0x880[7]
+                                       //rx antenna on
+                                       rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x4, 0x1);// 0xc04[2]
+                                       //rx antenna on
+                                       rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x4, 0x1);// 0xd04[2]
+                                       //analog to digital part2 on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x800, 0x1); // 0x880[11]
+                               }
+
+#elif defined RTL8192E
+                               // turn on RF
+                               if((priv->ieee80211->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+                               { // The current RF state is OFF and the RF OFF level is halting the NIC, re-initialize the NIC.
+                                       bool rtstatus = true;
+                                       u32 InitilizeCount = 3;
+                                       do
+                                       {
+                                               InitilizeCount--;
+                                               priv->RegRfOff = false;
+                                               rtstatus = NicIFEnableNIC(dev);
+                                       }while( (rtstatus != true) &&(InitilizeCount >0) );
+
+                                       if(rtstatus != true)
+                                       {
+                                               RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__);
+                                               priv->SetRFPowerStateInProgress = false;
+                                               return false;
+                                       }
+
+                                       RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+                               } else {
+                                       write_nic_byte(dev, ANAPAR, 0x37);//160MHz
+                                       //write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
+                                       mdelay(1);
+                                       //enable clock 80/88 MHz
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
+                                       priv->bHwRfOffAction = 0;
+                                       //}
+
+                                       //RF-A, RF-B
+                                       //enable RF-Chip A/B
                                        rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);              // 0x860[4]
-                               rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1);              // 0x864[4]
+                                       //analog to digital on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
+                                       //digital to analog on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
+                                       //rx antenna on
+                                       rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+                                       //rx antenna on
+                                       rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+                                       //analog to digital part2 on
+                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);      // 0x880[6:5]
+
+                                       // Baseband reset 2008.09.30 add
+                                       //write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
+
+                               //2     AFE
+                                       // 2008.09.30 add
+                                       //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
+                                       //analog to digital part2 on
+                                       //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);            // 0x880[6:5]
+
+
+                                       //digital to analog on
+                                       //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
+                                       //analog to digital on
+                                       //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
+                                       //rx antenna on
+                                       //PHY_SetBBReg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+                                       //rx antenna on 2008.09.30 mark
+                                       //PHY_SetBBReg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+
+                               //2     RF
+                                       //enable RF-Chip A/B
+                                       //rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);            // 0x860[4]
+                                       //rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1);            // 0x864[4]
+
+                               }
+
                                #endif
                                                break;
 
@@ -517,119 +574,137 @@ SetRFPowerState8190(
                                // By Bruce, 2008-01-16.
                                //
                        case eRfSleep:
-                       case eRfOff:
-                               RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOff/Sleep !\n");
-                               if (pPSC->bLeisurePs)
+                       {
+                               // HW setting had been configured with deeper mode.
+                               if(priv->ieee80211->eRFPowerState == eRfOff)
+                                       break;
+
+                               // Update current RF state variable.
+                               //priv->ieee80211->eRFPowerState = eRFPowerState;
+
+                               //if (pPSC->bLeisurePs)
                                {
                                        for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
                                        {
-                                               switch(QueueID) {
-                                                       case MGNT_QUEUE:
-                                                               tail=priv->txmapringtail;
-                                                               head=priv->txmapringhead;
+                                                       ring = &priv->tx_ring[QueueID];
+
+                                                       if(skb_queue_len(&ring->queue) == 0)
+                                                       {
+                                                               QueueID++;
+                                                               continue;
+                                                       }
+                                                       else
+                                                       {
+                                                               RT_TRACE((COMP_POWER|COMP_RF), "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+                                                               udelay(10);
+                                                               i++;
+                                                       }
+
+                                                       if(i >= MAX_DOZE_WAITING_TIMES_9x)
+                                                       {
+                                                               RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
                                                                break;
+                                                       }
+                                               }
+                               }
 
-                                                       case BK_QUEUE:
-                                                               tail=priv->txbkpringtail;
-                                                               head=priv->txbkpringhead;
+                               //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#ifdef RTL8190P
+                               {
+                                       PHY_SetRtl8190pRfOff(dev);
+                               }
+                               //else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
+                               {
+                                       PHY_SetRtl8192eRfOff(dev);
+                               }
+#endif
+                       }
                                                                break;
 
-                                                       case BE_QUEUE:
-                                                               tail=priv->txbepringtail;
-                                                               head=priv->txbepringhead;
-                                                               break;
+                       case eRfOff:
+                               //RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOff/Sleep !\n");
 
-                                                       case VI_QUEUE:
-                                                               tail=priv->txvipringtail;
-                                                               head=priv->txvipringhead;
-                                                               break;
+                               // Update current RF state variable.
+                               //priv->ieee80211->eRFPowerState = eRFPowerState;
 
-                                                       case VO_QUEUE:
-                                                               tail=priv->txvopringtail;
-                                                               head=priv->txvopringhead;
-                                                               break;
+                               //
+                               // Disconnect with Any AP or STA.
+                               //
+                               for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+                               {
+                                       ring = &priv->tx_ring[QueueID];
 
-                                                       default:
-                                                               tail=head=NULL;
-                                                               break;
-                                               }
-                                               if(tail == head)
+                                       if(skb_queue_len(&ring->queue) == 0)
                                                {
-                                                       //DbgPrint("QueueID = %d", QueueID);
                                                        QueueID++;
                                                        continue;
                                                }
                                                else
                                                {
-                                                       RT_TRACE(COMP_POWER, "eRf Off/Sleep: %d times BusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+                                                       RT_TRACE(COMP_POWER,
+                                                       "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
                                                        udelay(10);
                                                        i++;
                                                }
 
                                                if(i >= MAX_DOZE_WAITING_TIMES_9x)
                                                {
-                                                       RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times BusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
+                                                       RT_TRACE(COMP_POWER, "\n\n\n SetZebraRFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
                                                        break;
                                                }
                                        }
+
+                               //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#if defined RTL8190P
+                               {
+                                       PHY_SetRtl8190pRfOff(dev);
                                }
-                               #ifdef RTL8190P
-                               if(priv->rf_type == RF_2T4R)
+                               //else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
                                {
-                                       //disable RF-Chip A/B
-                                       rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);              // 0x860[4]
+                                       //if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC) && priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
+                                       if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+                                       { // Disable all components.
+                                               //
+                                               // Note:
+                                               //      NicIFSetLinkStatus is a big problem when we indicate the status to OS,
+                                               //      the OS(XP) will reset. But now, we cnnot find why the NIC is hard to receive
+                                               //      packets after RF ON. Just keep this function here and still work to find out the root couse.
+                                               //      By Bruce, 2009-05-01.
+                                               //
+                                               //NicIFSetLinkStatus( Adapter, RT_MEDIA_DISCONNECT );
+                                               //if HW radio of , need to indicate scan complete first for not be reset.
+                                               //if(MgntScanInProgress(pMgntInfo))
+                                               //      MgntResetScanProcess( Adapter );
+
+                                               // <1> Disable Interrupt
+                                               //rtl8192_irq_disable(dev);
+                                               // <2> Stop all timer
+                                               //MgntCancelAllTimer(Adapter);
+                                               // <3> Disable Adapter
+                                               //NicIFHaltAdapter(Adapter, false);
+                                               NicIFDisableNIC(dev);
+                                               RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+                                       }
+                                       else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
+                                       { // Normal case.
+                                               // IPS should go to this.
+                                               PHY_SetRtl8192eRfOff(dev);
+                                       }
+                               }
+#else
+                               else
+                               {
+                                       RT_TRACE(COMP_DBG,DBG_TRACE,("It is not 8190Pci and 8192PciE \n"));
                                }
-                               //disable RF-Chip C/D
-                               rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x0); // 0x868[4]
-                               //analog to digital off, for power save
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-                               //digital to analog off, for power save
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e0, 0x0); // 0x880[8:5]
-                               //rx antenna off
-                               rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
-                               //rx antenna off
-                               rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
-                               //analog to digital part2 off, for power save
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e00, 0x0); // 0x880[12:9]
-#else //8192E
-                                       //2 RF
-                               //disable RF-Chip A/B
-                               rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);              // 0x860[4]
-                                       rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x0);              // 0x864[4]
-                                       //2 AFE
-                               //analog to digital off, for power save
-                                       //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0x0); //  2008.09.30 Modify
-                               //digital to analog off, for power save
-                                       //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x18, 0x0); // 0x880[4:3]
-                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x0); // 0x880 2008.09.30 Modify
-                                       //rx antenna off  2008.09.30 mark
-                                       //PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
-                                       //rx antenna off  2008.09.30 mark
-                                       //PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
-                               //analog to digital part2 off, for power save
-                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);              // 0x880[6:5]
-                                       // 2008.09.30 add
-                                       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x0); // 0x884
-
-
-                                       //disable clock 80/88 MHz 2008.09.30 mark
-                                       //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x4, 0x0); // 0x880[2]
-                                       //2 BB
-                                       // Baseband reset 2008.09.30 add
-                                       write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0)); // 0x101
-                                       //MAC: off
-                                       write_nic_byte(dev, MacBlkCtrl, 0x0); // 0x403
-                                       //slow down cpu/lbus clock from 160MHz to Lower
-                                       write_nic_byte(dev, ANAPAR, 0x07); // 0x 17 40MHz
-                               priv->bHwRfOffAction = 0;
-                               //}
                                #endif
+
                                        break;
 
                        default:
                                        bResult = false;
-                                       RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n", eRFPowerState);
+                                       RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
                                        break;
                }
 
@@ -644,64 +719,11 @@ SetRFPowerState8190(
        {
                // Update current RF state variable.
                priv->ieee80211->eRFPowerState = eRFPowerState;
-
-               switch(priv->rf_chip )
-               {
-                       case RF_8256:
-                       switch(priv->ieee80211->eRFPowerState)
-                       {
-                               case eRfOff:
-                               //
-                               //If Rf off reason is from IPS, Led should blink with no link, by Maddest 071015
-                               //
-                                       if(priv->ieee80211->RfOffReason==RF_CHANGE_BY_IPS )
-                                       {
-                                               #ifdef TO_DO
-                                               Adapter->HalFunc.LedControlHandler(Adapter,LED_CTL_NO_LINK);
-                                               #endif
-                                       }
-                                       else
-                                       {
-                                       // Turn off LED if RF is not ON.
-                                               #ifdef TO_DO
-                                               Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF);
-                                               #endif
-                                       }
-                                       break;
-
-                               case eRfOn:
-                               // Turn on RF we are still linked, which might happen when
-                               // we quickly turn off and on HW RF. 2006.05.12, by rcnjko.
-                                       if( priv->ieee80211->state == IEEE80211_LINKED)
-                                       {
-                                               #ifdef TO_DO
-                                               Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK);
-                                               #endif
-                                       }
-                                       else
-                                       {
-                                       // Turn off LED if RF is not ON.
-                                               #ifdef TO_DO
-                                               Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK);
-                                               #endif
-                                       }
-                                       break;
-
-                               default:
-                       // do nothing.
-                                       break;
-                       }// Switch RF state
-
-                       break;
-
-                       default:
-                               RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown RF type\n");
-                               break;
-               }// Switch RFChipID
        }
 
+       //printk("%s()priv->ieee80211->eRFPowerState:%s\n" ,__func__,priv->ieee80211->eRFPowerState == eRfOn ? "On" : "Off");
        priv->SetRFPowerStateInProgress = false;
-       RT_TRACE(COMP_POWER, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
+       //RT_TRACE(COMP_PS, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
        return bResult;
 }
 
index 61b6f25..f4be9cc 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/random.h>
 #include <linux/version.h>
 #include <asm/io.h>
-#include "ieee80211.h"
+#include "ieee80211/ieee80211.h"
 
 
 
@@ -1003,6 +1003,11 @@ typedef struct r8192_priv
        int irq;
        short irq_enabled;
        struct ieee80211_device *ieee80211;
+#ifdef ENABLE_LPS
+       bool ps_force;
+       bool force_lps;
+       bool bdisable_nic;
+#endif
        bool being_init_adapter;
        u8 Rf_Mode;
        short card_8192; /* O: rtl8192, 1:rtl8185 V B/C, 2:rtl8185 V D */
@@ -1477,7 +1482,7 @@ void write_nic_word(struct net_device *dev, int x,u16 y);
 void write_nic_dword(struct net_device *dev, int x,u32 y);
 void force_pci_posting(struct net_device *dev);
 
-void rtl8192_rtx_disable(struct net_device *);
+void rtl8192_halt_adapter(struct net_device *dev, bool reset);
 void rtl8192_rx_enable(struct net_device *);
 void rtl8192_tx_enable(struct net_device *);
 
@@ -1512,5 +1517,19 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev);
 #ifdef ENABLE_IPS
 void IPSEnter(struct net_device *dev);
 void IPSLeave(struct net_device *dev);
+void InactivePsWorkItemCallback(struct net_device *dev);
+void IPSLeave_wq(void *data);
+void ieee80211_ips_leave_wq(struct net_device *dev);
+void ieee80211_ips_leave(struct net_device *dev);
+#endif
+#ifdef ENABLE_LPS
+void LeisurePSEnter(struct net_device *dev);
+void LeisurePSLeave(struct net_device *dev);
 #endif
+
+bool NicIFEnableNIC(struct net_device* dev);
+bool NicIFDisableNIC(struct net_device* dev);
+
+void rtl8192_irq_disable(struct net_device *dev);
+void PHY_SetRtl8192eRfOff(struct net_device* dev);
 #endif
index 0f69548..6622319 100644 (file)
@@ -66,7 +66,7 @@
 #endif
 
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 
 //set here to open your trace code. //WB
@@ -75,7 +75,7 @@ u32 rt_global_debug_component = \
                        //      COMP_EPROM      |
                //              COMP_PHY        |
                //              COMP_RF         |
-                               COMP_FIRMWARE   |
+//                             COMP_FIRMWARE   |
                        //      COMP_TRACE      |
                //              COMP_DOWN       |
                //              COMP_SWBW       |
@@ -343,6 +343,141 @@ void write_nic_word(struct net_device *dev, int x,u16 y)
 
 #endif /* RTL_IO_MAP */
 
+u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
+{
+       //struct r8192_priv* priv = ieee80211_priv(dev);
+       //struct ieee80211_device *ieee = priv->ieee80211;
+
+       static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
+       static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+       int wpa_ie_len= ieee->wpa_ie_len;
+       struct ieee80211_crypt_data* crypt;
+       int encrypt;
+
+       crypt = ieee->crypt[ieee->tx_keyidx];
+
+       encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\
+                 (ieee->host_encrypt && crypt && crypt->ops && \
+                  (0 == strcmp(crypt->ops->name,"WEP")));
+
+       /* simply judge  */
+       if(encrypt && (wpa_ie_len == 0)) {
+               // wep encryption, no N mode setting */
+               return SEC_ALG_WEP;
+       } else if((wpa_ie_len != 0)) {
+               // parse pairwise key type */
+               if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) ||
+                               ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
+                       return SEC_ALG_CCMP;
+               else
+                       return SEC_ALG_TKIP;
+       } else {
+               return SEC_ALG_NONE;
+       }
+}
+
+void
+rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
+{
+       struct r8192_priv* priv = ieee80211_priv(dev);
+
+       switch(variable)
+       {
+
+               case HW_VAR_BSSID:
+                       write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
+                       write_nic_word(dev, BSSIDR+2, ((u16*)(val+2))[0]);
+               break;
+
+               case HW_VAR_MEDIA_STATUS:
+               {
+                       RT_OP_MODE      OpMode = *((RT_OP_MODE *)(val));
+                       //LED_CTL_MODE  LedAction = LED_CTL_NO_LINK;
+                       u8              btMsr = read_nic_byte(dev, MSR);
+
+                       btMsr &= 0xfc;
+
+                       switch(OpMode)
+                       {
+                       case RT_OP_MODE_INFRASTRUCTURE:
+                               btMsr |= MSR_INFRA;
+                               //LedAction = LED_CTL_LINK;
+                               break;
+
+                       case RT_OP_MODE_IBSS:
+                               btMsr |= MSR_ADHOC;
+                               // led link set seperate
+                               break;
+
+                       case RT_OP_MODE_AP:
+                               btMsr |= MSR_AP;
+                               //LedAction = LED_CTL_LINK;
+                               break;
+
+                       default:
+                               btMsr |= MSR_NOLINK;
+                               break;
+                       }
+
+                       write_nic_byte(dev, MSR, btMsr);
+
+                       //priv->ieee80211->LedControlHandler(dev, LedAction);
+               }
+               break;
+
+               case HW_VAR_CECHK_BSSID:
+               {
+                       u32     RegRCR, Type;
+
+                       Type = ((u8*)(val))[0];
+                       //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR));
+                       RegRCR = read_nic_dword(dev,RCR);
+                       priv->ReceiveConfig = RegRCR;
+
+                       if (Type == true)
+                               RegRCR |= (RCR_CBSSID);
+                       else if (Type == false)
+                               RegRCR &= (~RCR_CBSSID);
+
+                       //priv->ieee80211->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) );
+                       write_nic_dword(dev, RCR,RegRCR);
+                       priv->ReceiveConfig = RegRCR;
+
+               }
+               break;
+
+               case HW_VAR_SLOT_TIME:
+               {
+                       //PSTA_QOS      pStaQos = Adapter->MgntInfo.pStaQos;
+                       //AC_CODING     eACI;
+
+                       priv->slot_time = val[0];
+                       write_nic_byte(dev, SLOT_TIME, val[0]);
+
+               }
+               break;
+
+               case HW_VAR_ACK_PREAMBLE:
+               {
+                       u32 regTmp = 0;
+                       priv->short_preamble = (bool)(*(u8*)val );
+                       regTmp = priv->basic_rate;
+                       if (priv->short_preamble)
+                               regTmp |= BRSR_AckShortPmb;
+                       write_nic_dword(dev, RRSR, regTmp);
+               }
+               break;
+
+               case HW_VAR_CPU_RST:
+                       write_nic_dword(dev, CPU_GEN, ((u32*)(val))[0]);
+               break;
+
+               default:
+               break;
+       }
+
+}
+
 
 ///////////////////////////////////////////////////////////
 
@@ -365,11 +500,6 @@ void rtl8192_restart(struct work_struct *work);
 //void rtl8192_rq_tx_ack(struct work_struct *work);
 
 void watch_dog_timer_callback(unsigned long data);
-#ifdef ENABLE_IPS
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-void InactivePsWorkItemCallback(struct net_device *dev);
-#endif
 /****************************************************************************
    -----------------------------PROCFS STUFF-------------------------
 *****************************************************************************/
@@ -707,7 +837,7 @@ static void rtl8192_irq_enable(struct net_device *dev)
 }
 
 
-static void rtl8192_irq_disable(struct net_device *dev)
+void rtl8192_irq_disable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
@@ -717,6 +847,7 @@ static void rtl8192_irq_disable(struct net_device *dev)
 }
 
 
+#if 0
 static void rtl8192_set_mode(struct net_device *dev,int mode)
 {
        u8 ecmd;
@@ -727,7 +858,7 @@ static void rtl8192_set_mode(struct net_device *dev,int mode)
        ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
        write_nic_byte(dev, EPROM_CMD, ecmd);
 }
-
+#endif
 
 void rtl8192_update_msr(struct net_device *dev)
 {
@@ -861,7 +992,7 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
     ring->desc = NULL;
 }
 
-
+#if 0
 static void rtl8192_beacon_disable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
@@ -873,38 +1004,116 @@ static void rtl8192_beacon_disable(struct net_device *dev)
        reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
        write_nic_dword(priv->ieee80211->dev, INTA_MASK, reg);
 }
+#endif
+
+void PHY_SetRtl8192eRfOff(struct net_device* dev       )
+{
+       //struct r8192_priv *priv = ieee80211_priv(dev);
+
+       //disable RF-Chip A/B
+       rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+       //analog to digital off, for power save
+       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+       //digital to analog off, for power save
+       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+       //rx antenna off
+       rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+       //rx antenna off
+       rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+       //analog to digital part2 off, for power save
+       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+       // Analog parameter!!Change bias and Lbus control.
+       write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+
+}
 
-void rtl8192_rtx_disable(struct net_device *dev)
+void rtl8192_halt_adapter(struct net_device *dev, bool reset)
 {
-       u8 cmd;
+       //u8    cmd;
        struct r8192_priv *priv = ieee80211_priv(dev);
-        int i;
+       int i;
+       u8      OpMode;
+       u8      u1bTmp;
+       u32     ulRegRead;
+
+       OpMode = RT_OP_MODE_NO_LINK;
+       priv->ieee80211->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
 
+#if 1
+       if(!priv->ieee80211->bSupportRemoteWakeUp)
+       {
+               u1bTmp = 0x0;   // disable tx/rx. In 8185 we write 0x10 (Reset bit), but here we make reference to WMAC and wirte 0x0. 2006.11.21 Emily
+               //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_COMMAND, &u1bTmp );      // Using HW_VAR_COMMAND instead of writing CMDR directly. Rewrited by Annie, 2006-04-07.
+               write_nic_byte(dev, CMDR, u1bTmp);
+       }
+#else
        cmd=read_nic_byte(dev,CMDR);
-//     if(!priv->ieee80211->bSupportRemoteWakeUp) {
-               write_nic_byte(dev, CMDR, cmd &~ \
-                               (CR_TE|CR_RE));
-//     }
-       force_pci_posting(dev);
-       mdelay(30);
+       write_nic_byte(dev, CMDR, cmd &~ (CR_TE|CR_RE));
+#endif
 
-        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
-                skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
-        }
-        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
-                skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
-        }
+       mdelay(20);
 
+       if(!reset)
+       {
+               //PlatformStallExecution(150000);
+               mdelay(150);
+
+#ifdef RTL8192E
+                       priv->bHwRfOffAction = 2;
+#endif
+
+               //
+               // Call MgntActSet_RF_State instead to prevent RF config race condition.
+               // By Bruce, 2008-01-17.
+               //
+               if(!priv->ieee80211->bSupportRemoteWakeUp)
+               {
+                       //MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_INIT);
+                       //MgntActSet_RF_State(Adapter, eRfOff, Adapter->MgntInfo.RfOffReason);
+                       //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+
+                       PHY_SetRtl8192eRfOff(dev);
+
+                       // 2006.11.30. System reset bit
+                       //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_CPU_RST, (u32*)(&ulRegRead) );
+                       ulRegRead = read_nic_dword(dev,CPU_GEN);
+                       ulRegRead|=CPU_GEN_SYSTEM_RESET;
+                       //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_CPU_RST, &ulRegRead);
+                       write_nic_dword(dev,CPU_GEN, ulRegRead);
+               }
+               else
+               {
+                       //2008.06.03 for WOL
+                       write_nic_dword(dev, WFCRC0, 0xffffffff);
+                       write_nic_dword(dev, WFCRC1, 0xffffffff);
+                       write_nic_dword(dev, WFCRC2, 0xffffffff);
+
+                       //Write PMR register
+                       write_nic_byte(dev, PMR, 0x5);
+                       //Disable tx, enanble rx
+                       write_nic_byte(dev, MacBlkCtrl, 0xa);
+               }
+       }
+
+       for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+               skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
+       }
+       for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+               skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
+       }
 
        skb_queue_purge(&priv->skb_queue);
        return;
 }
 
+#if 0
 static void rtl8192_reset(struct net_device *dev)
 {
     rtl8192_irq_disable(dev);
     printk("This is RTL819xP Reset procedure\n");
 }
+#endif
 
 static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
 inline u16 rtl8192_rate2rate(short rate)
@@ -954,6 +1163,12 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
        /* shall not be referred by command packet */
        assert(queue_index != TXCMD_QUEUE);
 
+       if((priv->bHwRadioOff == true)||(!priv->up))
+       {
+               kfree_skb(skb);
+               return;
+       }
+
        //spin_lock_irqsave(&priv->tx_lock,flags);
 
         memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
@@ -996,6 +1211,13 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
         cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
         u8 queue_index = tcb_desc->queue_index;
 
+        if(queue_index != TXCMD_QUEUE){
+               if((priv->bHwRadioOff == true)||(!priv->up))
+               {
+                               kfree_skb(skb);
+                       return 0;
+               }
+        }
 
        //spin_lock_irqsave(&priv->tx_lock,flags);
 
@@ -1379,6 +1601,15 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
     u8*   pda_addr = NULL;
     int   idx;
 
+    if(priv->bdisable_nic){
+               RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index);
+               return skb->len;
+    }
+
+#ifdef ENABLE_LPS
+       priv->ieee80211->bAwakePktSent = true;
+#endif
+
     mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
     /* collect the tx packets statitcs */
     pda_addr = ((u8*)skb->data) + sizeof(TX_FWINFO_8190PCI);
@@ -1481,6 +1712,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
     if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
            RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d,%x", \
                            tcb_desc->queue_index,ring->idx, idx,skb->len);
+           spin_unlock_irqrestore(&priv->irq_th_lock,flags);
            return skb->len;
     }
 
@@ -1779,7 +2011,7 @@ static void rtl8192_qos_activate(struct work_struct * work)
                                (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
                                (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
                                ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
-               printk("===>u4bAcParam:%x, ", u4bAcParam);
+               //printk("===>u4bAcParam:%x, ", u4bAcParam);
                write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
                //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
        }
@@ -1964,11 +2196,24 @@ void rtl8192_update_ratr_table(struct net_device* dev)
        write_nic_byte(dev, UFWP, 1);
 }
 
+#if 0
 static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
 static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+#endif
+
 static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
 {
 #if 1
+
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       struct ieee80211_device *ieee = priv->ieee80211;
+       if (ieee->rtllib_ap_sec_type &&
+          (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
+               return false;
+       } else {
+               return true;
+       }
+#else
        struct r8192_priv* priv = ieee80211_priv(dev);
        struct ieee80211_device* ieee = priv->ieee80211;
         int wpa_ie_len= ieee->wpa_ie_len;
@@ -1995,18 +2240,6 @@ static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
                return true;
        }
 
-#if 0
-        //In here we discuss with SD4 David. He think we still can send TKIP in broadcast group key in MCS rate.
-        //We can't force in G mode if Pairwie key is AES and group key is TKIP
-        if((pSecInfo->GroupEncAlgorithm == WEP104_Encryption) || (pSecInfo->GroupEncAlgorithm == WEP40_Encryption)  ||
-           (pSecInfo->PairwiseEncAlgorithm == WEP104_Encryption) ||
-           (pSecInfo->PairwiseEncAlgorithm == WEP40_Encryption) || (pSecInfo->PairwiseEncAlgorithm == TKIP_Encryption))
-        {
-                return  false;
-        }
-        else
-                return true;
-#endif
        return true;
 #endif
 }
@@ -2127,7 +2360,19 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev)
 }
 static void rtl8192_hw_sleep_down(struct net_device *dev)
 {
-       RT_TRACE(COMP_POWER, "%s()============>come to sleep down\n", __FUNCTION__);
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&priv->rf_ps_lock,flags);
+       if (priv->RFChangeInProgress) {
+               spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+               RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
+               printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
+               return;
+       }
+       spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+       //RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__);
+
        MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
 }
 static void rtl8192_hw_sleep_wq (struct work_struct *work)
@@ -2138,21 +2383,29 @@ static void rtl8192_hw_sleep_wq (struct work_struct *work)
         struct delayed_work *dwork = container_of(work,struct delayed_work,work);
         struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_sleep_wq);
         struct net_device *dev = ieee->dev;
-       //printk("=========>%s()\n", __FUNCTION__);
+
         rtl8192_hw_sleep_down(dev);
 }
-//     printk("dev is %d\n",dev);
-//     printk("&*&(^*(&(&=========>%s()\n", __FUNCTION__);
+
 static void rtl8192_hw_wakeup(struct net_device* dev)
 {
-//     u32 flags = 0;
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&priv->rf_ps_lock,flags);
+       if (priv->RFChangeInProgress) {
+               spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+               RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
+               printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
+               queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_wakeup_wq,MSECS(10));//PowerSave is not supported if kernel version is below 2.6.20
+               return;
+       }
+       spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
 
-//     spin_lock_irqsave(&priv->ps_lock,flags);
-       RT_TRACE(COMP_POWER, "%s()============>come to wake up\n", __FUNCTION__);
+       //RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__);
        MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
-       //FIXME: will we send package stored while nic is sleep?
-//     spin_unlock_irqrestore(&priv->ps_lock,flags);
 }
+
 void rtl8192_hw_wakeup_wq (struct work_struct *work)
 {
 //     struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
@@ -2169,7 +2422,6 @@ void rtl8192_hw_wakeup_wq (struct work_struct *work)
 #define MAX_SLEEP_TIME 10000
 static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
 {
-
        struct r8192_priv *priv = ieee80211_priv(dev);
 
        u32 rb = jiffies;
@@ -2177,58 +2429,55 @@ static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
 
        spin_lock_irqsave(&priv->ps_lock,flags);
 
-       /* Writing HW register with 0 equals to disable
-        * the timer, that is not really what we want
-        */
-       tl -= MSECS(4+16+7);
-
-       //if(tl == 0) tl = 1;
-
-       /* FIXME HACK FIXME HACK */
-//     force_pci_posting(dev);
-       //mdelay(1);
-
-//     rb = read_nic_dword(dev, TSFTR);
+       // Writing HW register with 0 equals to disable
+       // the timer, that is not really what we want
+       //
+       tl -= MSECS(8+16+7);
 
-       /* If the interval in witch we are requested to sleep is too
-        * short then give up and remain awake
-        */
+       // If the interval in witch we are requested to sleep is too
+       // short then give up and remain awake
+       // when we sleep after send null frame, the timer will be too short to sleep.
+       //
        if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
-               ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
+                       ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
                spin_unlock_irqrestore(&priv->ps_lock,flags);
-               printk("too short to sleep\n");
+               printk("too short to sleep::%x, %x, %lx\n",tl, rb,  MSECS(MIN_SLEEP_TIME));
                return;
        }
 
-//     write_nic_dword(dev, TimerInt, tl);
-//     rb = read_nic_dword(dev, TSFTR);
-       {
-               u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
-       //      if (tl<rb)
-               queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp); //as tl may be less than rb
-       }
-       /* if we suspect the TimerInt is gone beyond tl
-        * while setting it, then give up
-        */
-#if 1
        if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
-               ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
+                       ((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
+                       ((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
                printk("========>too long to sleep:%x, %x, %lx\n", tl, rb,  MSECS(MAX_SLEEP_TIME));
                spin_unlock_irqrestore(&priv->ps_lock,flags);
                return;
        }
-#endif
-//     if(priv->rf_sleep)
-//             priv->rf_sleep(dev);
-
-       //printk("<=========%s()\n", __FUNCTION__);
-       queue_delayed_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq,0);
+       {
+               u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
+               queue_delayed_work(priv->ieee80211->wq,
+                               &priv->ieee80211->hw_wakeup_wq,tmp);
+               //PowerSave not supported when kernel version less 2.6.20
+       }
+       queue_delayed_work(priv->ieee80211->wq,
+                       (void *)&priv->ieee80211->hw_sleep_wq,0);
        spin_unlock_irqrestore(&priv->ps_lock,flags);
+
 }
 static void rtl8192_init_priv_variable(struct net_device* dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
        u8 i;
+       PRT_POWER_SAVE_CONTROL  pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+       // Default Halt the NIC if RF is OFF.
+       pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+       pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
+       pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+       pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
+       pPSC->bLeisurePs = true;
+       pPSC->RegMaxLPSAwakeIntvl = 5;
+       priv->bHwRadioOff = false;
+
        priv->being_init_adapter = false;
        priv->txbuffsize = 1600;//1024;
        priv->txfwbuffersize = 4096;
@@ -2328,6 +2577,17 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
        //added by amy
        priv->ieee80211->InitialGainHandler = InitialGain819xPci;
 
+#ifdef ENABLE_IPS
+       priv->ieee80211->ieee80211_ips_leave_wq = ieee80211_ips_leave_wq;
+       priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;
+#endif
+#ifdef ENABLE_LPS
+        priv->ieee80211->LeisurePSLeave            = LeisurePSLeave;
+#endif//ENABL
+
+       priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
+       priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
+
        priv->card_type = USB;
        {
                priv->ShortRetryLimit = 0x30;
@@ -2400,6 +2660,10 @@ static void rtl8192_init_priv_task(struct net_device* dev)
        priv->priv_wq = create_workqueue(DRV_NAME);
 #endif
 
+#ifdef ENABLE_IPS
+       INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq);
+#endif
+
 //     INIT_WORK(&priv->reset_wq, (void(*)(void*)) rtl8192_restart);
        INIT_WORK(&priv->reset_wq,  rtl8192_restart);
 //     INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
@@ -2926,13 +3190,14 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
                #endif
                        break;
        }
-/*
-       //2008.06.03, for WOL
+
+
        if( priv->eeprom_vid == 0x1186 &&  priv->eeprom_did == 0x3304)
-               priv->ieee80211->bSupportRemoteWakeUp = TRUE;
+               priv->ieee80211->bSupportRemoteWakeUp = true;
        else
-               priv->ieee80211->bSupportRemoteWakeUp = FALSE;
-*/
+               priv->ieee80211->bSupportRemoteWakeUp = false;
+
+
        RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
        RT_TRACE(COMP_INIT, "ChannelPlan = %d \n", priv->ChannelPlan);
        RT_TRACE(COMP_INIT, "LedStrategy = %d \n", priv->LedStrategy);
@@ -4006,12 +4271,19 @@ static void rtl819x_ifsilentreset(struct net_device *dev)
        struct ieee80211_device *ieee = priv->ieee80211;
 
 
+       return;
+
        // 2007.07.20. If we need to check CCK stop, please uncomment this line.
        //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
 
        if(priv->ResetProgress==RESET_TYPE_NORESET)
        {
 RESET_START:
+#ifdef ENABLE_LPS
+                //LZM for PS-Poll AID issue. 090429
+                if(priv->ieee80211->state == IEEE80211_LINKED)
+                    LeisurePSLeave(dev);
+#endif
 
                RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
 
@@ -4051,9 +4323,9 @@ RESET_START:
                }
                else{
                        printk("ieee->state is NOT LINKED\n");
-                       ieee80211_softmac_stop_protocol(priv->ieee80211);
+                       ieee80211_softmac_stop_protocol(priv->ieee80211,true);
                }
-               rtl8192_rtx_disable(dev);
+               rtl8192_halt_adapter(dev, true);
                up(&priv->wx_sem);
                RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
                RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
@@ -4150,6 +4422,128 @@ void InactivePsWorkItemCallback(struct net_device *dev)
        RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <--------- \n");
 }
 
+#ifdef ENABLE_LPS
+//
+// Change current and default preamble mode.
+// 2005.01.06, by rcnjko.
+//
+bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,   u8 rtPsMode)
+{
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       //PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+       //u8 RpwmVal, FwPwrMode;
+
+       // Currently, we do not change power save mode on IBSS mode.
+       if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
+       {
+               return false;
+       }
+
+       //
+       // <RJ_NOTE> If we make HW to fill up the PwrMgt bit for us,
+       // some AP will not response to our mgnt frames with PwrMgt bit set,
+       // e.g. cannot associate the AP.
+       // So I commented out it. 2005.02.16, by rcnjko.
+       //
+//     // Change device's power save mode.
+//     Adapter->HalFunc.SetPSModeHandler( Adapter, rtPsMode );
+
+       // Update power save mode configured.
+       //RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
+       if(!priv->ps_force) {
+               priv->ieee80211->ps = rtPsMode;
+       }
+
+       // Awake immediately
+       if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
+       {
+                unsigned long flags;
+
+               //PlatformSetTimer(Adapter, &(pMgntInfo->AwakeTimer), 0);
+               // Notify the AP we awke.
+               rtl8192_hw_wakeup(dev);
+               priv->ieee80211->sta_sleep = 0;
+
+                spin_lock_irqsave(&(priv->ieee80211->mgmt_tx_lock), flags);
+               printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
+               ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
+                spin_unlock_irqrestore(&(priv->ieee80211->mgmt_tx_lock), flags);
+       }
+
+       return true;
+}
+
+//================================================================================
+// Leisure Power Save in linked state.
+//================================================================================
+
+//
+//     Description:
+//             Enter the leisure power save mode.
+//
+void LeisurePSEnter(struct net_device *dev)
+{
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+       //RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+       //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
+       //      pPSC->bLeisurePs, priv->ieee80211->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
+
+       if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
+               (priv->ieee80211->state == IEEE80211_LINKED)) ||
+               (priv->ieee80211->iw_mode == IW_MODE_ADHOC) ||
+               (priv->ieee80211->iw_mode == IW_MODE_MASTER))
+               return;
+
+       if (pPSC->bLeisurePs)
+       {
+               // Idle for a while if we connect to AP a while ago.
+               if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) //  4 Sec
+               {
+
+                       if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
+                       {
+
+                               //RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+                               MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
+
+                       }
+               }
+               else
+                       pPSC->LpsIdleCount++;
+       }
+}
+
+
+//
+//     Description:
+//             Leave the leisure power save mode.
+//
+void LeisurePSLeave(struct net_device *dev)
+{
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+
+       //RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+       //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
+       //      pPSC->bLeisurePs, priv->ieee80211->ps);
+
+       if (pPSC->bLeisurePs)
+       {
+               if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
+               {
+                       // move to lps_wakecomplete()
+                       //RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+                       MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_DISABLED);
+
+               }
+       }
+}
+#endif
+
+
 //
 //     Description:
 //             Enter the inactive power save mode. RF will be off
@@ -4178,6 +4572,7 @@ IPSEnter(struct net_device *dev)
                        && (priv->ieee80211->state != IEEE80211_LINKED) )
                {
                        RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
+                       //printk("IPSEnter(): Turn off RF.\n");
                        pPSC->eInactivePowerState = eRfOff;
 //                     queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
                        InactivePsWorkItemCallback(dev);
@@ -4203,12 +4598,53 @@ IPSLeave(struct net_device *dev)
                if (rtState != eRfOn  && !pPSC->bSwRfProcessing && priv->ieee80211->RfOffReason <= RF_CHANGE_BY_IPS)
                {
                        RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
+                       //printk("IPSLeave(): Turn on RF.\n");
                        pPSC->eInactivePowerState = eRfOn;
 //                     queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
                        InactivePsWorkItemCallback(dev);
                }
        }
 }
+
+void IPSLeave_wq(void *data)
+{
+       struct ieee80211_device *ieee = container_of(data,struct ieee80211_device,ips_leave_wq);
+       struct net_device *dev = ieee->dev;
+
+       struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+       down(&priv->ieee80211->ips_sem);
+       IPSLeave(dev);
+       up(&priv->ieee80211->ips_sem);
+}
+
+void ieee80211_ips_leave_wq(struct net_device *dev)
+{
+       struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+       RT_RF_POWER_STATE       rtState;
+       rtState = priv->ieee80211->eRFPowerState;
+
+       if(priv->ieee80211->PowerSaveControl.bInactivePs){
+               if(rtState == eRfOff){
+                       if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+                       {
+                               RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+                               return;
+                       }
+                       else{
+                               printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+                               queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq);
+                       }
+               }
+       }
+}
+//added by amy 090331 end
+void ieee80211_ips_leave(struct net_device *dev)
+{
+       struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+       down(&priv->ieee80211->ips_sem);
+       IPSLeave(dev);
+       up(&priv->ieee80211->ips_sem);
+}
 #endif
 
 static void rtl819x_update_rxcounts(
@@ -4244,15 +4680,23 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
        unsigned long flags;
        bool bBusyTraffic = false;
        static u8 last_time = 0;
+       bool bEnterPS = false;
+
+       if((!priv->up) || (priv->bHwRadioOff == true))
+               return;
+
        if(!priv->up)
                return;
        hal_dm_watchdog(dev);
 #ifdef ENABLE_IPS
 //     printk("watch_dog ENABLE_IPS\n");
        if(ieee->actscanning == false){
-               if((ieee->iw_mode != IW_MODE_ADHOC) && (ieee->state == IEEE80211_NOLINK) && (ieee->beinretry == false) && (ieee->eRFPowerState == eRfOn) && !ieee->is_set_key){
+               //printk("%d,%d,%d,%d\n", ieee->eRFPowerState, ieee->is_set_key, ieee->proto_stoppping, ieee->wx_set_enc);
+               if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&\
+                   (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\
+                   (!ieee->proto_stoppping) && !ieee->wx_set_enc){
                        if(ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
-                               printk("====================>haha:IPSEnter()\n");
+                               //printk("====================>haha:IPSEnter()\n");
                                IPSEnter(dev);
                                //ieee80211_stop_scan(priv->ieee80211);
                        }
@@ -4262,14 +4706,49 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
        {//to get busy traffic condition
                if(ieee->state == IEEE80211_LINKED)
                {
-                       if(     ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
-                               ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
+                       if(     ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
+                               ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
                                bBusyTraffic = true;
                        }
 
+#ifdef ENABLE_LPS
+                       //added by amy for Leisure PS
+                       if(     ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+                               (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+                       {
+                               //printk("ieee->LinkDetectInfo.NumRxUnicastOkInPeriod is %d,ieee->LinkDetectInfo.NumTxOkInPeriod is %d\n",
+                               //      ieee->LinkDetectInfo.NumRxUnicastOkInPeriod,ieee->LinkDetectInfo.NumTxOkInPeriod);
+                               bEnterPS= false;
+                       }
+                       else
+                       {
+                               bEnterPS= true;
+                       }
+
+                       //printk("***bEnterPS = %d\n", bEnterPS);
+                       // LeisurePS only work in infra mode.
+                       if(bEnterPS)
+                       {
+                               LeisurePSEnter(dev);
+                       }
+                       else
+                       {
+                               LeisurePSLeave(dev);
+                       }
+#endif
+
+               }
+               else
+               {
+#ifdef ENABLE_LPS
+                       //RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
+                       LeisurePSLeave(dev);
+#endif
                }
+
                ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
                ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+               ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
                ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
        }
 
@@ -4288,14 +4767,14 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
                                if( ieee->eRFPowerState == eRfOff)
                                        RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
                                printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
-               //              Dot11d_Reset(dev);
+                               //              Dot11d_Reset(dev);
                                ieee->state = IEEE80211_ASSOCIATING;
                                notify_wx_assoc_event(priv->ieee80211);
-                                RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
+                               RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
                                ieee->is_roaming = true;
                                ieee->is_set_key = false;
-                             ieee->link_change(dev);
-                                queue_work(ieee->wq, &ieee->associate_procedure_wq);
+                               ieee->link_change(dev);
+                               queue_work(ieee->wq, &ieee->associate_procedure_wq);
                        }
                }
              ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
@@ -4348,6 +4827,7 @@ int _rtl8192_up(struct net_device *dev)
        RT_STATUS init_status = RT_STATUS_SUCCESS;
        priv->up=1;
        priv->ieee80211->ieee_up=1;
+       priv->bdisable_nic = false;  //YJ,add,091111
        RT_TRACE(COMP_INIT, "Bringing up iface");
 
        init_status = rtl8192_adapter_start(dev);
@@ -4422,6 +4902,12 @@ int rtl8192_down(struct net_device *dev)
 #endif
        if (priv->up == 0) return -1;
 
+#ifdef ENABLE_LPS
+       //LZM for PS-Poll AID issue. 090429
+       if(priv->ieee80211->state == IEEE80211_LINKED)
+               LeisurePSLeave(dev);
+#endif
+
        priv->up=0;
        priv->ieee80211->ieee_up = 0;
        RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
@@ -4459,11 +4945,9 @@ int rtl8192_down(struct net_device *dev)
        deinit_hal_dm(dev);
        del_timer_sync(&priv->watch_dog_timer);
 
-       ieee80211_softmac_stop_protocol(priv->ieee80211);
-#ifdef ENABLE_IPS
-       MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
-#endif
-       rtl8192_rtx_disable(dev);
+       ieee80211_softmac_stop_protocol(priv->ieee80211,true);
+
+       rtl8192_halt_adapter(dev,false);
        memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
 
        RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
@@ -4479,10 +4963,10 @@ void rtl8192_commit(struct net_device *dev)
        if (priv->up == 0) return ;
 
 
-       ieee80211_softmac_stop_protocol(priv->ieee80211);
+       ieee80211_softmac_stop_protocol(priv->ieee80211,true);
 
        rtl8192_irq_disable(dev);
-       rtl8192_rtx_disable(dev);
+       rtl8192_halt_adapter(dev,true);
        _rtl8192_up(dev);
 }
 
@@ -6381,11 +6865,13 @@ void setKey(    struct net_device *dev,
                        if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
                        {
                                RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
-                               up(&priv->wx_sem);
+                               //up(&priv->wx_sem);
                                return ;
                        }
                        else{
+                               down(&priv->ieee80211->ips_sem);
                                IPSLeave(dev);
+                               up(&priv->ieee80211->ips_sem);
                        }
                }
        }
@@ -6455,6 +6941,65 @@ void CamPrintDbgReg(struct net_device* dev)
        RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue);
 }
 
+bool NicIFEnableNIC(struct net_device* dev)
+{
+       RT_STATUS init_status = RT_STATUS_SUCCESS;
+       struct r8192_priv* priv = ieee80211_priv(dev);
+       PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+       //YJ,add,091109
+       if (priv->up == 0){
+               RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
+               priv->bdisable_nic = false;  //YJ,add,091111
+               return false;
+       }
+       // <1> Reset memory: descriptor, buffer,..
+       //NicIFResetMemory(Adapter);
+
+       // <2> Enable Adapter
+       //printk("===========>%s()\n",__FUNCTION__);
+       //priv->bfirst_init = true;
+       init_status = rtl8192_adapter_start(dev);
+       if (init_status != RT_STATUS_SUCCESS) {
+               RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+               priv->bdisable_nic = false;  //YJ,add,091111
+               return -1;
+       }
+       //printk("start adapter finished\n");
+       RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+       //priv->bfirst_init = false;
+
+       // <3> Enable Interrupt
+       rtl8192_irq_enable(dev);
+       priv->bdisable_nic = false;
+       //RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__);
+       return (init_status == RT_STATUS_SUCCESS) ? true:false;
+}
+bool NicIFDisableNIC(struct net_device* dev)
+{
+       bool    status = true;
+       struct r8192_priv* priv = ieee80211_priv(dev);
+       u8 tmp_state = 0;
+       // <1> Disable Interrupt
+       //RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__);
+       priv->bdisable_nic = true;      //YJ,move,091109
+       tmp_state = priv->ieee80211->state;
+
+       ieee80211_softmac_stop_protocol(priv->ieee80211, false);
+
+       priv->ieee80211->state = tmp_state;
+       rtl8192_cancel_deferred_work(priv);
+       rtl8192_irq_disable(dev);
+       // <2> Stop all timer
+
+       // <3> Disable Adapter
+       rtl8192_halt_adapter(dev, false);
+//     priv->bdisable_nic = true;
+       //RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__);
+
+       return status;
+}
+
 
 /***************************************************************************
      ------------------- module init / exit stubs ----------------
index 5ffb4f7..a249f00 100644 (file)
@@ -19,26 +19,28 @@ Major Change History:
 #include "r819xE_phy.h"
 #include "r819xE_phyreg.h"
 #include "r8190_rtl8256.h"
+
+#define DRV_NAME "rtl819xE"
 /*---------------------------Define Local Constant---------------------------*/
 //
 // Indicate different AP vendor for IOT issue.
 //
 #ifdef  RTL8190P
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322};
+{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322,       0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322};
+{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322,       0x5e4322};
 #else
 #ifdef RTL8192E
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322};
+{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322,       0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322};
+{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322,       0x5e4322};
 #else
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5ea44f};
+{ 0x5e4322,    0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5ea44f,       0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5ea44f,       0x5ea44f};
+{ 0x5e4322,    0xa44f,         0x5e4322,       0x604322,       0x5ea44f,       0x5ea44f,       0x5e4322};
 #endif
 #endif
 
@@ -275,6 +277,30 @@ void dm_CheckRxAggregation(struct net_device *dev) {
 #endif
 
 
+// call the script file to enable
+void dm_check_ac_dc_power(struct net_device *dev)
+{
+       struct r8192_priv *priv = ieee80211_priv(dev);
+       static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
+       char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
+       static char *envp[] = {"HOME=/",
+                       "TERM=linux",
+                       "PATH=/usr/bin:/bin",
+                        NULL};
+
+       if(priv->ResetProgress == RESET_TYPE_SILENT)
+       {
+               RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+               return;
+       }
+
+       if(priv->ieee80211->state != IEEE80211_LINKED) {
+               return;
+       }
+       call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
+
+       return;
+};
 
 void hal_dm_watchdog(struct net_device *dev)
 {
@@ -282,6 +308,8 @@ void hal_dm_watchdog(struct net_device *dev)
 
        //static u8     previous_bssid[6] ={0};
 
+       dm_check_ac_dc_power(dev);
+
        /*Add by amy 2008/05/15 ,porting from windows code.*/
        dm_check_rate_adaptive(dev);
        dm_dynamic_txpower(dev);
index 388908f..346bfb1 100644 (file)
@@ -808,4 +808,12 @@ enum _RTL8192Pci_HW {
 #define GPI 0x108
 #define GPO 0x109
 #define GPE 0x10a
+
+#define        ANAPAR_FOR_8192PciE                                                     0x17            // Analog parameter register
+
+#define        MSR_NOLINK                                      0x00
+#define        MSR_ADHOC                                       0x01
+#define        MSR_INFRA                                       0x02
+#define        MSR_AP                                          0x03
+
 #endif
index d1eb892..0b0f39c 100644 (file)
@@ -22,7 +22,7 @@
 #include "r8192E_hw.h"
 #include "r8192E_wx.h"
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 
 #define RATE_COUNT 12
@@ -70,6 +70,9 @@ static int r8192_wx_set_rate(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
@@ -87,6 +90,9 @@ static int r8192_wx_set_rts(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
@@ -111,6 +117,9 @@ static int r8192_wx_set_power(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
@@ -290,6 +299,9 @@ static int r8192_wx_set_rawtx(struct net_device *dev,
        struct r8192_priv *priv = ieee80211_priv(dev);
        int ret;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
@@ -325,6 +337,9 @@ static int r8192_wx_set_crcmon(struct net_device *dev,
        int enable = (parms[0] > 0);
        short prev = priv->crcmon;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        if(enable)
@@ -352,6 +367,9 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
        RT_RF_POWER_STATE       rtState;
        int ret;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        rtState = priv->ieee80211->eRFPowerState;
        down(&priv->wx_sem);
 #ifdef ENABLE_IPS
@@ -366,8 +384,10 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
                                        return -1;
                                }
                                else{
-                               printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+                                       RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
+                                       down(&priv->ieee80211->ips_sem);
                                        IPSLeave(dev);
+                                       up(&priv->ieee80211->ips_sem);
                                }
                        }
                }
@@ -425,7 +445,7 @@ static int rtl8180_wx_get_range(struct net_device *dev,
         */
 
        /* ~5 Mb/s real (802.11b) */
-       range->throughput = 5 * 1000 * 1000;
+       range->throughput = 130 * 1000 * 1000;
 
        // TODO: Not used in 802.11b?
 //     range->min_nwid;        /* Minimal NWID we are able to set */
@@ -468,7 +488,7 @@ static int rtl8180_wx_get_range(struct net_device *dev,
        range->pmt_flags = IW_POWER_TIMEOUT;
        range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
        range->we_version_compiled = WIRELESS_EXT;
-       range->we_version_source = 16;
+       range->we_version_source = 18;
 
 //     range->retry_capa;      /* What retry options are supported */
 //     range->retry_flags;     /* How to decode max/min retry limit */
@@ -517,7 +537,12 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
        struct ieee80211_device* ieee = priv->ieee80211;
        RT_RF_POWER_STATE       rtState;
        int ret;
+
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        rtState = priv->ieee80211->eRFPowerState;
+
        if(!priv->up) return -ENETDOWN;
        if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
                return -EAGAIN;
@@ -547,8 +572,10 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
                                        return -1;
                                }
                                else{
-                                       printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+                                       //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
+                                       down(&priv->ieee80211->ips_sem);
                                        IPSLeave(dev);
+                                       up(&priv->ieee80211->ips_sem);
                                }
                        }
                }
@@ -580,6 +607,9 @@ static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
        int ret;
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        if(!priv->up) return -ENETDOWN;
 
        down(&priv->wx_sem);
@@ -599,23 +629,16 @@ static int r8192_wx_set_essid(struct net_device *dev,
        RT_RF_POWER_STATE       rtState;
        int ret;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        rtState = priv->ieee80211->eRFPowerState;
        down(&priv->wx_sem);
+
 #ifdef ENABLE_IPS
-       if(priv->ieee80211->PowerSaveControl.bInactivePs){
-               if(rtState == eRfOff){
-                       if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
-                       {
-                               RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
-                               up(&priv->wx_sem);
-                               return -1;
-                       }
-                       else{
-                               printk("=========>%s(): IPSLeave\n",__FUNCTION__);
-                               IPSLeave(dev);
-                       }
-               }
-       }
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
 #endif
        ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
 
@@ -650,6 +673,9 @@ static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
        int ret;
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
@@ -673,6 +699,9 @@ static int r8192_wx_set_frag(struct net_device *dev,
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        if (wrqu->frag.disabled)
                priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
        else {
@@ -711,8 +740,16 @@ static int r8192_wx_set_wap(struct net_device *dev,
        struct r8192_priv *priv = ieee80211_priv(dev);
 //        struct sockaddr *temp = (struct sockaddr *)awrq;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
        ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
 
        up(&priv->wx_sem);
@@ -753,14 +790,24 @@ static int r8192_wx_set_enc(struct net_device *dev,
        u32 hwkey[4]={0,0,0,0};
        u8 mask=0xff;
        u32 key_idx=0;
-       u8 zero_addr[4][6] ={   {0x00,0x00,0x00,0x00,0x00,0x00},
+       u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
                                {0x00,0x00,0x00,0x00,0x00,0x01},
                                {0x00,0x00,0x00,0x00,0x00,0x02},
                                {0x00,0x00,0x00,0x00,0x00,0x03} };
        int i;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        if(!priv->up) return -ENETDOWN;
 
+        priv->ieee80211->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
+
        down(&priv->wx_sem);
 
        RT_TRACE(COMP_SEC, "Setting SW wep key");
@@ -768,7 +815,6 @@ static int r8192_wx_set_enc(struct net_device *dev,
 
        up(&priv->wx_sem);
 
-
        //sometimes, the length is zero while we do not type key value
        if(wrqu->encoding.length!=0){
 
@@ -868,6 +914,8 @@ static int r8192_wx_set_enc(struct net_device *dev,
        }
 #endif
 
+       priv->ieee80211->wx_set_enc = 0;
+
        return ret;
 }
 
@@ -893,6 +941,9 @@ static int r8192_wx_set_retry(struct net_device *dev,
        struct r8192_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
 
        if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
@@ -985,6 +1036,10 @@ static int r8192_wx_set_sens(struct net_device *dev,
        struct r8192_priv *priv = ieee80211_priv(dev);
 
        short err = 0;
+
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
        //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
        if(priv->rf_set_sens == NULL) {
@@ -1011,7 +1066,19 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
        struct r8192_priv *priv = ieee80211_priv(dev);
        struct ieee80211_device* ieee = priv->ieee80211;
 
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
+
+       priv->ieee80211->wx_set_enc = 1;
+
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
+
        ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
 
        {
@@ -1091,6 +1158,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
        }
 
 end_hw_sec:
+       priv->ieee80211->wx_set_enc = 0;
        up(&priv->wx_sem);
        return ret;
 
@@ -1102,6 +1170,10 @@ static int r8192_wx_set_auth(struct net_device *dev,
        int ret=0;
        //printk("====>%s()\n", __FUNCTION__);
        struct r8192_priv *priv = ieee80211_priv(dev);
+
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
        ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
        up(&priv->wx_sem);
@@ -1116,6 +1188,10 @@ static int r8192_wx_set_mlme(struct net_device *dev,
 
        int ret=0;
        struct r8192_priv *priv = ieee80211_priv(dev);
+
+       if(priv->bHwRadioOff == true)
+               return 0;
+
        down(&priv->wx_sem);
        ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
        up(&priv->wx_sem);
@@ -1129,6 +1205,10 @@ static int r8192_wx_set_gen_ie(struct net_device *dev,
           //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
        int ret=0;
         struct r8192_priv *priv = ieee80211_priv(dev);
+
+       if(priv->bHwRadioOff == true)
+               return 0;
+
         down(&priv->wx_sem);
         ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
         up(&priv->wx_sem);
@@ -1142,6 +1222,42 @@ static int dummy(struct net_device *dev, struct iw_request_info *a,
        return -1;
 }
 
+// check ac/dc status with the help of user space application */
+static int r8192_wx_adapter_power_status(struct net_device *dev,
+               struct iw_request_info *info,
+               union iwreq_data *wrqu, char *extra)
+{
+       struct r8192_priv *priv = ieee80211_priv(dev);
+#ifdef ENABLE_LPS
+       PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+       struct ieee80211_device* ieee = priv->ieee80211;
+#endif
+       down(&priv->wx_sem);
+
+#ifdef ENABLE_LPS
+       RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
+       // ieee->ps shall not be set under DC mode, otherwise it conflict
+       // with Leisure power save mode setting.
+       //
+       if(*extra || priv->force_lps) {
+               priv->ps_force = false;
+               pPSC->bLeisurePs = true;
+       } else {
+               //LZM for PS-Poll AID issue. 090429
+               if(priv->ieee80211->state == IEEE80211_LINKED)
+                       LeisurePSLeave(dev);
+
+               priv->ps_force = true;
+               pPSC->bLeisurePs = false;
+               ieee->ps = *extra;
+       }
+
+#endif
+       up(&priv->wx_sem);
+       return 0;
+
+}
+
 
 static iw_handler r8192_wx_handlers[] =
 {
@@ -1231,72 +1347,28 @@ static const struct iw_priv_args r8192_private_args[] = {
                SIOCIWFIRSTPRIV + 0x2,
                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
        }
-#ifdef JOHN_IOCTL
        ,
        {
                SIOCIWFIRSTPRIV + 0x3,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
+               IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
+
        }
        ,
        {
                SIOCIWFIRSTPRIV + 0x4,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
-       }
-       ,
-       {
-               SIOCIWFIRSTPRIV + 0x5,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
-       }
-       ,
-       {
-               SIOCIWFIRSTPRIV + 0x6,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
-       }
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x7,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
-        }
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x8,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
-        }
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x9,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
-        }
-
-#endif
-       ,
-       {
-               SIOCIWFIRSTPRIV + 0x3,
-               IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
-
+               IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+               "set_power"
        }
 
 };
 
 
 static iw_handler r8192_private_handler[] = {
-//     r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
        r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
-//     r8192_wx_set_forceassociate,
-//     r8192_wx_set_beaconinterval,
-//     r8192_wx_set_monitor_type,
        r8192_wx_set_scan_type,
        r8192_wx_set_rawtx,
-#ifdef JOHN_IOCTL
-       r8192_wx_read_regs,
-       r8192_wx_write_regs,
-       r8192_wx_read_bb,
-       r8192_wx_write_bb,
-        r8192_wx_read_nicb,
-        r8192_wx_write_nicb,
-       r8192_wx_get_ap_status
-#endif
        r8192_wx_force_reset,
+       r8192_wx_adapter_power_status,
 };
 
 //#if WIRELESS_EXT >= 17
index 79ebdb6..047030b 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef R8180_WX_H
 #define R8180_WX_H
 //#include <linux/wireless.h>
-//#include "ieee80211.h"
 extern struct iw_handler_def r8192_wx_handlers_def;
 /* Enable  the rtl819x_core.c to share this function, david 2008.9.22 */
 extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
index c44059a..7bd4fae 100644 (file)
@@ -5,7 +5,7 @@
 #include "r819xE_phy.h"
 #include "r8192E_dm.h"
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
        0,
index 37f0fee..6a26883 100644 (file)
@@ -38,6 +38,8 @@
 #define        MCS_TXAGC                               0x340   // MCS AGC
 #define        CCK_TXAGC                               0x348   // CCK AGC
 
+#define        MacBlkCtrl                              0x403                                   // Mac block on/off control register
+
 //page8
 #define rFPGA0_RFMOD                           0x800  //RF mode & CCK TxSC
 #define rFPGA0_TxInfo                          0x804
 #define        rRTL8256TxBBBW             19
 #define        bRTL8256TxBBBW                  0x18
 
+
 #endif //__INC_HAL8190PCIPHYREG_H