diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/pci.c')
| -rw-r--r-- | drivers/net/wireless/rtlwifi/pci.c | 609 | 
1 files changed, 391 insertions, 218 deletions
| diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9cd7703c2a30..a40952845436 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -32,6 +32,7 @@  #include "pci.h"  #include "base.h"  #include "ps.h" +#include "efuse.h"  static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {  	INTEL_VENDOR_ID, @@ -40,6 +41,31 @@ static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {  	SIS_VENDOR_ID  }; +static const u8 ac_to_hwq[] = { +	VO_QUEUE, +	VI_QUEUE, +	BE_QUEUE, +	BK_QUEUE +}; + +static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, +		       struct sk_buff *skb) +{ +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	__le16 fc = rtl_get_fc(skb); +	u8 queue_index = skb_get_queue_mapping(skb); + +	if (unlikely(ieee80211_is_beacon(fc))) +		return BEACON_QUEUE; +	if (ieee80211_is_mgmt(fc)) +		return MGNT_QUEUE; +	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) +		if (ieee80211_is_nullfunc(fc)) +			return HIGH_QUEUE; + +	return ac_to_hwq[queue_index]; +} +  /* Update PCI dependent default settings*/  static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)  { @@ -48,6 +74,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; +	u8 init_aspm;  	ppsc->reg_rfps_level = 0;  	ppsc->support_aspm = 0; @@ -125,7 +152,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)  			bool support_backdoor = true;  			ppsc->support_aspm = support_aspm; -			/*if(priv->oem_id == RT_CID_TOSHIBA && +			/*if (priv->oem_id == RT_CID_TOSHIBA &&  			   !priv->ndis_adapter.amd_l1_patch)  			   support_backdoor = false; */ @@ -145,6 +172,13 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)  			 ("switch case not process\n"));  		break;  	} + +	/* toshiba aspm issue, toshiba will set aspm selfly +	 * so we should not set aspm in driver */ +	pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); +	if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && +		init_aspm == 0x43) +		ppsc->support_aspm = false;  }  static bool _rtl_pci_platform_switch_device_pci_aspm( @@ -152,28 +186,28 @@ static bool _rtl_pci_platform_switch_device_pci_aspm(  			u8 value)  {  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -	bool bresult = false; +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -	value |= 0x40; +	if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) +		value |= 0x40;  	pci_write_config_byte(rtlpci->pdev, 0x80, value); -	return bresult; +	return false;  }  /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/  static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value)  {  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -	u8 buffer; -	bool bresult = false; - -	buffer = value; +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));  	pci_write_config_byte(rtlpci->pdev, 0x81, value); -	bresult = true; -	return bresult; +	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) +		udelay(100); + +	return true;  }  /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ @@ -191,6 +225,10 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)  	u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter.  				pcibridge_linkctrlreg;  	u16 aspmlevel = 0; +	u8 tmp_u1b = 0; + +	if (!ppsc->support_aspm) +		return;  	if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {  		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, @@ -204,11 +242,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)  		_rtl_pci_switch_clk_req(hw, 0x0);  	} -	if (1) { -		/*for promising device will in L0 state after an I/O. */ -		u8 tmp_u1b; -		pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); -	} +	/*for promising device will in L0 state after an I/O. */ +	pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b);  	/*Set corresponding value. */  	aspmlevel |= BIT(0) | BIT(1); @@ -224,7 +259,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)  	rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg);  	udelay(50); -  }  /* @@ -249,6 +283,9 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)  	u8 u_pcibridge_aspmsetting;  	u8 u_device_aspmsetting; +	if (!ppsc->support_aspm) +		return; +  	if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {  		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,  			 ("PCI(Bridge) UNKNOWN.\n")); @@ -293,7 +330,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)  					     RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);  		RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ);  	} -	udelay(200); +	udelay(100);  }  static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) @@ -330,13 +367,13 @@ static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)  	u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;  	u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;  	u8 linkctrl_reg; -	u8 num4bBytes; +	u8 num4bbytes; -	num4bBytes = (capabilityoffset + 0x10) / 4; +	num4bbytes = (capabilityoffset + 0x10) / 4;  	/*Read  Link Control Register */  	rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, -				     pcicfg_addrport + (num4bBytes << 2)); +				     pcicfg_addrport + (num4bbytes << 2));  	rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg);  	pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; @@ -369,7 +406,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,  	pci_write_config_byte(pdev, 0x70f, tmp);  } -static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) +static void rtl_pci_init_aspm(struct ieee80211_hw *hw)  {  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -383,52 +420,6 @@ static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw)  } -static void rtl_pci_init_aspm(struct ieee80211_hw *hw) -{ -	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - -	/*close ASPM for AMD defaultly */ -	rtlpci->const_amdpci_aspm = 0; - -	/* -	 * ASPM PS mode. -	 * 0 - Disable ASPM, -	 * 1 - Enable ASPM without Clock Req, -	 * 2 - Enable ASPM with Clock Req, -	 * 3 - Alwyas Enable ASPM with Clock Req, -	 * 4 - Always Enable ASPM without Clock Req. -	 * set defult to RTL8192CE:3 RTL8192E:2 -	 * */ -	rtlpci->const_pci_aspm = 3; - -	/*Setting for PCI-E device */ -	rtlpci->const_devicepci_aspm_setting = 0x03; - -	/*Setting for PCI-E bridge */ -	rtlpci->const_hostpci_aspm_setting = 0x02; - -	/* -	 * In Hw/Sw Radio Off situation. -	 * 0 - Default, -	 * 1 - From ASPM setting without low Mac Pwr, -	 * 2 - From ASPM setting with low Mac Pwr, -	 * 3 - Bus D3 -	 * set default to RTL8192CE:0 RTL8192SE:2 -	 */ -	rtlpci->const_hwsw_rfoff_d3 = 0; - -	/* -	 * This setting works for those device with -	 * backdoor ASPM setting such as EPHY setting. -	 * 0 - Not support ASPM, -	 * 1 - Support ASPM, -	 * 2 - According to chipset. -	 */ -	rtlpci->const_support_pciaspm = 1; - -	_rtl_pci_initialize_adapter_common(hw); -} -  static void _rtl_pci_io_handler_init(struct device *dev,  				     struct ieee80211_hw *hw)  { @@ -450,6 +441,90 @@ static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw)  {  } +static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, +		struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +	u8 additionlen = FCS_LEN; +	struct sk_buff *next_skb; + +	/* here open is 4, wep/tkip is 8, aes is 12*/ +	if (info->control.hw_key) +		additionlen += info->control.hw_key->icv_len; + +	/* The most skb num is 6 */ +	tcb_desc->empkt_num = 0; +	spin_lock_bh(&rtlpriv->locks.waitq_lock); +	skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { +		struct ieee80211_tx_info *next_info; + +		next_info = IEEE80211_SKB_CB(next_skb); +		if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { +			tcb_desc->empkt_len[tcb_desc->empkt_num] = +				next_skb->len + additionlen; +			tcb_desc->empkt_num++; +		} else { +			break; +		} + +		if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], +				      next_skb)) +			break; + +		if (tcb_desc->empkt_num >= 5) +			break; +	} +	spin_unlock_bh(&rtlpriv->locks.waitq_lock); + +	return true; +} + +/* just for early mode now */ +static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct sk_buff *skb = NULL; +	struct ieee80211_tx_info *info = NULL; +	int tid; /* should be int */ + +	if (!rtlpriv->rtlhal.earlymode_enable) +		return; + +	/* we juse use em for BE/BK/VI/VO */ +	for (tid = 7; tid >= 0; tid--) { +		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)]; +		struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; +		while (!mac->act_scanning && +		       rtlpriv->psc.rfpwr_state == ERFON) { +			struct rtl_tcb_desc tcb_desc; +			memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + +			spin_lock_bh(&rtlpriv->locks.waitq_lock); +			if (!skb_queue_empty(&mac->skb_waitq[tid]) && +			   (ring->entries - skb_queue_len(&ring->queue) > 5)) { +				skb = skb_dequeue(&mac->skb_waitq[tid]); +			} else { +				spin_unlock_bh(&rtlpriv->locks.waitq_lock); +				break; +			} +			spin_unlock_bh(&rtlpriv->locks.waitq_lock); + +			/* Some macaddr can't do early mode. like +			 * multicast/broadcast/no_qos data */ +			info = IEEE80211_SKB_CB(skb); +			if (info->flags & IEEE80211_TX_CTL_AMPDU) +				_rtl_update_earlymode_info(hw, skb, +							   &tcb_desc, tid); + +			rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); +		} +	} +} + +  static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -461,6 +536,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  		struct rtl_tx_desc *entry = &ring->desc[ring->idx];  		struct sk_buff *skb;  		struct ieee80211_tx_info *info; +		__le16 fc; +		u8 tid;  		u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true,  							  HW_DESC_OWN); @@ -481,6 +558,10 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  						      HW_DESC_TXBUFF_ADDR),  				 skb->len, PCI_DMA_TODEVICE); +		/* remove early mode header */ +		if (rtlpriv->rtlhal.earlymode_enable) +			skb_pull(skb, EM_HDR_LEN); +  		RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE,  			 ("new ring->idx:%d, "  			  "free: skb_queue_len:%d, free: seq:%x\n", @@ -488,6 +569,30 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  			  skb_queue_len(&ring->queue),  			  *(u16 *) (skb->data + 22))); +		if (prio == TXCMD_QUEUE) { +			dev_kfree_skb(skb); +			goto tx_status_ok; + +		} + +		/* for sw LPS, just after NULL skb send out, we can +		 * sure AP kown we are sleeped, our we should not let +		 * rf to sleep*/ +		fc = rtl_get_fc(skb); +		if (ieee80211_is_nullfunc(fc)) { +			if (ieee80211_has_pm(fc)) { +				rtlpriv->mac80211.offchan_deley = true; +				rtlpriv->psc.state_inap = 1; +			} else { +				rtlpriv->psc.state_inap = 0; +			} +		} + +		/* update tid tx pkt num */ +		tid = rtl_get_tid(skb); +		if (tid <= 7) +			rtlpriv->link_info.tidtx_inperiod[tid]++; +  		info = IEEE80211_SKB_CB(skb);  		ieee80211_tx_info_clear_status(info); @@ -510,7 +615,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  					skb_get_queue_mapping  					(skb));  		} - +tx_status_ok:  		skb = NULL;  	} @@ -582,23 +687,21 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  			 *skb_trim(skb, skb->len - 4);  			 */ -			hdr = (struct ieee80211_hdr *)(skb->data); -			fc = hdr->frame_control; +			hdr = rtl_get_hdr(skb); +			fc = rtl_get_fc(skb); -			if (!stats.crc) { +			if (!stats.crc || !stats.hwerror) {  				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,  				       sizeof(rx_status)); -				if (is_broadcast_ether_addr(hdr->addr1)) +				if (is_broadcast_ether_addr(hdr->addr1)) {  					;/*TODO*/ -				else { -					if (is_multicast_ether_addr(hdr->addr1)) -						;/*TODO*/ -					else { -						unicast = true; -						rtlpriv->stats.rxbytesunicast += -						    skb->len; -					} +				} else if (is_multicast_ether_addr(hdr->addr1)) { +					;/*TODO*/ +				} else { +					unicast = true; +					rtlpriv->stats.rxbytesunicast += +					    skb->len;  				}  				rtl_is_special_data(hw, skb, false); @@ -612,28 +715,38 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  						    num_rx_inperiod++;  				} -				if (unlikely(!rtl_action_proc(hw, skb, -				    false))) { +				/* for sw lps */ +				rtl_swlps_beacon(hw, (void *)skb->data, +						 skb->len); +				rtl_recognize_peer(hw, (void *)skb->data, +						   skb->len); +				if ((rtlpriv->mac80211.opmode == +				     NL80211_IFTYPE_AP) && +				    (rtlpriv->rtlhal.current_bandtype == +				     BAND_ON_2_4G) && +				     (ieee80211_is_beacon(fc) || +				     ieee80211_is_probe_resp(fc))) {  					dev_kfree_skb_any(skb);  				} else { -					struct sk_buff *uskb = NULL; -					u8 *pdata; -					uskb = dev_alloc_skb(skb->len + 128); -					if (!uskb) { -						RT_TRACE(rtlpriv, -							(COMP_INTR | COMP_RECV), -							DBG_EMERG, -							("can't alloc rx skb\n")); -						goto done; +					if (unlikely(!rtl_action_proc(hw, skb, +					    false))) { +						dev_kfree_skb_any(skb); +					} else { +						struct sk_buff *uskb = NULL; +						u8 *pdata; +						uskb = dev_alloc_skb(skb->len +								     + 128); +						memcpy(IEEE80211_SKB_RXCB(uskb), +						       &rx_status, +						       sizeof(rx_status)); +						pdata = (u8 *)skb_put(uskb, +							skb->len); +						memcpy(pdata, skb->data, +						       skb->len); +						dev_kfree_skb_any(skb); + +						ieee80211_rx_irqsafe(hw, uskb);  					} -					memcpy(IEEE80211_SKB_RXCB(uskb), -							&rx_status, -							sizeof(rx_status)); -					pdata = (u8 *)skb_put(uskb, skb->len); -					memcpy(pdata, skb->data, skb->len); -					dev_kfree_skb_any(skb); - -					ieee80211_rx_irqsafe(hw, uskb);  				}  			} else {  				dev_kfree_skb_any(skb); @@ -648,7 +761,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  			new_skb = dev_alloc_skb(rtlpci->rxbuffersize);  			if (unlikely(!new_skb)) {  				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), -					 DBG_EMERG, +					 DBG_DMESG,  					 ("can't alloc skb for rx\n"));  				goto done;  			} @@ -666,7 +779,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  		}  done: -		bufferaddress = (u32)(*((dma_addr_t *) skb->cb)); +		bufferaddress = (*((dma_addr_t *)skb->cb));  		tmp_one = 1;  		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,  					    HW_DESC_RXBUFF_ADDR, @@ -695,6 +808,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)  	struct ieee80211_hw *hw = dev_id;  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));  	unsigned long flags;  	u32 inta = 0;  	u32 intb = 0; @@ -781,23 +895,36 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)  		_rtl_pci_tx_isr(hw, VO_QUEUE);  	} +	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { +		if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { +			rtlpriv->link_info.num_tx_inperiod++; + +			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, +					("CMD TX OK interrupt!\n")); +			_rtl_pci_tx_isr(hw, TXCMD_QUEUE); +		} +	} +  	/*<2> Rx related */  	if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) {  		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); -		tasklet_schedule(&rtlpriv->works.irq_tasklet); +		_rtl_pci_rx_interrupt(hw);  	}  	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) {  		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,  			 ("rx descriptor unavailable!\n")); -		tasklet_schedule(&rtlpriv->works.irq_tasklet); +		_rtl_pci_rx_interrupt(hw);  	}  	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) {  		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); -		tasklet_schedule(&rtlpriv->works.irq_tasklet); +		_rtl_pci_rx_interrupt(hw);  	} +	if (rtlpriv->rtlhal.earlymode_enable) +		tasklet_schedule(&rtlpriv->works.irq_tasklet); +  	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);  	return IRQ_HANDLED; @@ -808,7 +935,7 @@ done:  static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)  { -	_rtl_pci_rx_interrupt(hw); +	_rtl_pci_tx_chk_waitq(hw);  }  static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) @@ -816,14 +943,15 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; +	struct rtl8192_tx_ring *ring = NULL;  	struct ieee80211_hdr *hdr = NULL;  	struct ieee80211_tx_info *info = NULL;  	struct sk_buff *pskb = NULL;  	struct rtl_tx_desc *pdesc = NULL; -	unsigned int queue_index; +	struct rtl_tcb_desc tcb_desc;  	u8 temp_one = 1; +	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));  	ring = &rtlpci->tx_ring[BEACON_QUEUE];  	pskb = __skb_dequeue(&ring->queue);  	if (pskb) @@ -833,14 +961,11 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)  	pskb = ieee80211_beacon_get(hw, mac->vif);  	if (pskb == NULL)  		return; -	hdr = (struct ieee80211_hdr *)(pskb->data); +	hdr = rtl_get_hdr(pskb);  	info = IEEE80211_SKB_CB(pskb); - -	queue_index = BEACON_QUEUE; -  	pdesc = &ring->desc[0];  	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, -					info, pskb, queue_index); +		info, pskb, BEACON_QUEUE, &tcb_desc);  	__skb_queue_tail(&ring->queue, pskb); @@ -882,7 +1007,6 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	rtlpci->up_first_time = true;  	rtlpci->being_init_adapter = false; @@ -890,31 +1014,20 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,  	rtlhal->hw = hw;  	rtlpci->pdev = pdev; -	ppsc->inactiveps = false; -	ppsc->leisure_ps = true; -	ppsc->fwctrl_lps = true; -	ppsc->reg_fwctrl_lps = 3; -	ppsc->reg_max_lps_awakeintvl = 5; - -	if (ppsc->reg_fwctrl_lps == 1) -		ppsc->fwctrl_psmode = FW_PS_MIN_MODE; -	else if (ppsc->reg_fwctrl_lps == 2) -		ppsc->fwctrl_psmode = FW_PS_MAX_MODE; -	else if (ppsc->reg_fwctrl_lps == 3) -		ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; -  	/*Tx/Rx related var */  	_rtl_pci_init_trx_var(hw); -	 /*IBSS*/ mac->beacon_interval = 100; +	/*IBSS*/ mac->beacon_interval = 100; -	 /*AMPDU*/ mac->min_space_cfg = 0; +	/*AMPDU*/ +	mac->min_space_cfg = 0;  	mac->max_mss_density = 0;  	/*set sane AMPDU defaults */  	mac->current_ampdu_density = 7;  	mac->current_ampdu_factor = 3; -	 /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; +	/*QOS*/ +	rtlpci->acm_method = eAcmWay2_SW;  	/*task */  	tasklet_init(&rtlpriv->works.irq_tasklet, @@ -955,7 +1068,8 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,  		 ("queue:%d, ring_addr:%p\n", prio, ring));  	for (i = 0; i < entries; i++) { -		nextdescaddress = (u32) dma + ((i + 1) % entries) * +		nextdescaddress = (u32) dma + +					      ((i + 1) % entries) *  					      sizeof(*ring);  		rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), @@ -1020,7 +1134,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)  					   rtlpci->rxbuffersize,  					   PCI_DMA_FROMDEVICE); -			bufferaddress = (u32)(*((dma_addr_t *)skb->cb)); +			bufferaddress = (*((dma_addr_t *)skb->cb));  			rtlpriv->cfg->ops->set_desc((u8 *)entry, false,  						    HW_DESC_RXBUFF_ADDR,  						    (u8 *)&bufferaddress); @@ -1203,72 +1317,73 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)  	return 0;  } -static unsigned int _rtl_mac_to_hwqueue(__le16 fc, -		unsigned int mac80211_queue_index) +static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, +					struct sk_buff *skb)  { -	unsigned int hw_queue_index; - -	if (unlikely(ieee80211_is_beacon(fc))) { -		hw_queue_index = BEACON_QUEUE; -		goto out; -	} - -	if (ieee80211_is_mgmt(fc)) { -		hw_queue_index = MGNT_QUEUE; -		goto out; -	} - -	switch (mac80211_queue_index) { -	case 0: -		hw_queue_index = VO_QUEUE; -		break; -	case 1: -		hw_queue_index = VI_QUEUE; -		break; -	case 2: -		hw_queue_index = BE_QUEUE;; -		break; -	case 3: -		hw_queue_index = BK_QUEUE; -		break; -	default: -		hw_queue_index = BE_QUEUE; -		RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", -				  mac80211_queue_index)); -		break; -	} +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +	struct ieee80211_sta *sta = info->control.sta; +	struct rtl_sta_info *sta_entry = NULL; +	u8 tid = rtl_get_tid(skb); + +	if (!sta) +		return false; +	sta_entry = (struct rtl_sta_info *)sta->drv_priv; + +	if (!rtlpriv->rtlhal.earlymode_enable) +		return false; +	if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) +		return false; +	if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) +		return false; +	if (tid > 7) +		return false; + +	/* maybe every tid should be checked */ +	if (!rtlpriv->link_info.higher_busytxtraffic[tid]) +		return false; + +	spin_lock_bh(&rtlpriv->locks.waitq_lock); +	skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); +	spin_unlock_bh(&rtlpriv->locks.waitq_lock); -out: -	return hw_queue_index; +	return true;  } -static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, +		struct rtl_tcb_desc *ptcb_desc)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); -	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_sta_info *sta_entry = NULL;  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +	struct ieee80211_sta *sta = info->control.sta;  	struct rtl8192_tx_ring *ring;  	struct rtl_tx_desc *pdesc;  	u8 idx; -	unsigned int queue_index, hw_queue; +	u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb);  	unsigned long flags; -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); -	__le16 fc = hdr->frame_control; +	struct ieee80211_hdr *hdr = rtl_get_hdr(skb); +	__le16 fc = rtl_get_fc(skb);  	u8 *pda_addr = hdr->addr1;  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	/*ssn */ -	u8 *qc = NULL;  	u8 tid = 0;  	u16 seq_number = 0;  	u8 own;  	u8 temp_one = 1; -	if (ieee80211_is_mgmt(fc)) -		rtl_tx_mgmt_proc(hw, skb); -	rtl_action_proc(hw, skb, true); +	if (ieee80211_is_auth(fc)) { +		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); +		rtl_ips_nic_on(hw); +	} + +	if (rtlpriv->psc.sw_ps_enabled) { +		if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && +			!ieee80211_has_pm(fc)) +			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); +	} -	queue_index = skb_get_queue_mapping(skb); -	hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); +	rtl_action_proc(hw, skb, true);  	if (is_multicast_ether_addr(pda_addr))  		rtlpriv->stats.txbytesmulticast += skb->len; @@ -1278,7 +1393,6 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  		rtlpriv->stats.txbytesunicast += skb->len;  	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); -  	ring = &rtlpci->tx_ring[hw_queue];  	if (hw_queue != BEACON_QUEUE)  		idx = (ring->idx + skb_queue_len(&ring->queue)) % @@ -1301,43 +1415,30 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  		return skb->len;  	} -	/* -	 *if(ieee80211_is_nullfunc(fc)) { -	 *      spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -	 *      return 1; -	 *} -	 */ -  	if (ieee80211_is_data_qos(fc)) { -		qc = ieee80211_get_qos_ctl(hdr); -		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - -		seq_number = mac->tids[tid].seq_number; -		seq_number &= IEEE80211_SCTL_SEQ; -		/* -		 *hdr->seq_ctrl = hdr->seq_ctrl & -		 *cpu_to_le16(IEEE80211_SCTL_FRAG); -		 *hdr->seq_ctrl |= cpu_to_le16(seq_number); -		 */ - -		seq_number += 1; +		tid = rtl_get_tid(skb); +		if (sta) { +			sta_entry = (struct rtl_sta_info *)sta->drv_priv; +			seq_number = (le16_to_cpu(hdr->seq_ctrl) & +				      IEEE80211_SCTL_SEQ) >> 4; +			seq_number += 1; + +			if (!ieee80211_has_morefrags(hdr->frame_control)) +				sta_entry->tids[tid].seq_number = seq_number; +		}  	}  	if (ieee80211_is_data(fc))  		rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); -	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, -					info, skb, hw_queue); +	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, +			info, skb, hw_queue, ptcb_desc);  	__skb_queue_tail(&ring->queue, skb); -	rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, +	rtlpriv->cfg->ops->set_desc((u8 *)pdesc, true,  				    HW_DESC_OWN, (u8 *)&temp_one); -	if (!ieee80211_has_morefrags(hdr->frame_control)) { -		if (qc) -			mac->tids[tid].seq_number = seq_number; -	}  	if ((ring->entries - skb_queue_len(&ring->queue)) < 2 &&  	    hw_queue != BEACON_QUEUE) { @@ -1359,6 +1460,35 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	return 0;  } +static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u16 i = 0; +	int queue_id; +	struct rtl8192_tx_ring *ring; + +	for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { +		u32 queue_len; +		ring = &pcipriv->dev.tx_ring[queue_id]; +		queue_len = skb_queue_len(&ring->queue); +		if (queue_len == 0 || queue_id == BEACON_QUEUE || +			queue_id == TXCMD_QUEUE) { +			queue_id--; +			continue; +		} else { +			msleep(20); +			i++; +		} + +		/* we just wait 1s for all queues */ +		if (rtlpriv->psc.rfpwr_state == ERFOFF || +			is_hal_stop(rtlhal) || i >= 200) +			return; +	} +} +  static void rtl_pci_deinit(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1477,11 +1607,14 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  	struct pci_dev *bridge_pdev = pdev->bus->self;  	u16 venderid;  	u16 deviceid; +	u8 revisionid;  	u16 irqline;  	u8 tmp; +	pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN;  	venderid = pdev->vendor;  	deviceid = pdev->device; +	pci_read_config_byte(pdev, 0x8, &revisionid);  	pci_read_config_word(pdev, 0x3C, &irqline);  	if (deviceid == RTL_PCI_8192_DID || @@ -1492,7 +1625,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  	    deviceid == RTL_PCI_8173_DID ||  	    deviceid == RTL_PCI_8172_DID ||  	    deviceid == RTL_PCI_8171_DID) { -		switch (pdev->revision) { +		switch (revisionid) {  		case RTL_PCI_REVISION_ID_8192PCIE:  			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,  				 ("8192 PCI-E is found - " @@ -1521,6 +1654,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,  			 ("8192C PCI-E is found - "  			  "vid/did=%x/%x\n", venderid, deviceid)); +	} else if (deviceid == RTL_PCI_8192DE_DID || +		   deviceid == RTL_PCI_8192DE_DID2) { +		rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, +			 ("8192D PCI-E is found - " +			  "vid/did=%x/%x\n", venderid, deviceid));  	} else {  		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,  			 ("Err: Unknown device -" @@ -1529,6 +1668,25 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  		rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE;  	} +	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { +		if (revisionid == 0 || revisionid == 1) { +			if (revisionid == 0) { +				RT_TRACE(rtlpriv, COMP_INIT, +					 DBG_LOUD, ("Find 92DE MAC0.\n")); +				rtlhal->interfaceindex = 0; +			} else if (revisionid == 1) { +				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +					("Find 92DE MAC1.\n")); +				rtlhal->interfaceindex = 1; +			} +		} else { +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				("Unknown device - " +				"VendorID/DeviceID=%x/%x, Revision=%x\n", +				venderid, deviceid, revisionid)); +			rtlhal->interfaceindex = 0; +		} +	}  	/*find bus info */  	pcipriv->ndis_adapter.busnumber = pdev->bus->number;  	pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); @@ -1554,12 +1712,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  		    PCI_SLOT(bridge_pdev->devfn);  		pcipriv->ndis_adapter.pcibridge_funcnum =  		    PCI_FUNC(bridge_pdev->devfn); -		pcipriv->ndis_adapter.pcibridge_pciehdr_offset = -		    pci_pcie_cap(bridge_pdev);  		pcipriv->ndis_adapter.pcicfg_addrport =  		    (pcipriv->ndis_adapter.pcibridge_busnum << 16) |  		    (pcipriv->ndis_adapter.pcibridge_devnum << 11) |  		    (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); +		pcipriv->ndis_adapter.pcibridge_pciehdr_offset = +		    pci_pcie_cap(bridge_pdev);  		pcipriv->ndis_adapter.num4bytes =  		    (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; @@ -1642,6 +1800,11 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,  	pcipriv = (void *)rtlpriv->priv;  	pcipriv->dev.pdev = pdev; +	/* init cfg & intf_ops */ +	rtlpriv->rtlhal.interface = INTF_PCI; +	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); +	rtlpriv->intf_ops = &rtl_pci_ops; +  	/*  	 *init dbgp flags before all  	 *other functions, because we will @@ -1659,13 +1822,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,  		return err;  	} -	pmem_start = pci_resource_start(pdev, 2); -	pmem_len = pci_resource_len(pdev, 2); -	pmem_flags = pci_resource_flags(pdev, 2); +	pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); +	pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); +	pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id);  	/*shared mem start */  	rtlpriv->io.pci_mem_start = -			(unsigned long)pci_iomap(pdev, 2, pmem_len); +			(unsigned long)pci_iomap(pdev, +			rtlpriv->cfg->bar_id, pmem_len);  	if (rtlpriv->io.pci_mem_start == 0) {  		RT_ASSERT(false, ("Can't map PCI mem\n"));  		goto fail2; @@ -1684,11 +1848,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,  	pci_write_config_byte(pdev, 0x04, 0x06);  	pci_write_config_byte(pdev, 0x04, 0x07); -	/* init cfg & intf_ops */ -	rtlpriv->rtlhal.interface = INTF_PCI; -	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); -	rtlpriv->intf_ops = &rtl_pci_ops; -  	/* find adapter */  	_rtl_pci_find_adapter(pdev, hw); @@ -1806,7 +1965,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev)  	rtl_pci_deinit(hw);  	rtl_deinit_core(hw); -	rtlpriv->cfg->ops->deinit_sw_leds(hw);  	_rtl_pci_io_handler_release(hw);  	rtlpriv->cfg->ops->deinit_sw_vars(hw); @@ -1821,6 +1979,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev)  	}  	pci_disable_device(pdev); + +	rtl_pci_disable_aspm(hw); +  	pci_set_drvdata(pdev, NULL);  	ieee80211_free_hw(hw); @@ -1844,10 +2005,15 @@ no need to call hw_disable here.  ****************************************/  int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state)  { +	struct ieee80211_hw *hw = pci_get_drvdata(pdev); +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->cfg->ops->hw_suspend(hw); +	rtl_deinit_rfkill(hw); +  	pci_save_state(pdev);  	pci_disable_device(pdev);  	pci_set_power_state(pdev, PCI_D3hot); -  	return 0;  }  EXPORT_SYMBOL(rtl_pci_suspend); @@ -1855,6 +2021,8 @@ EXPORT_SYMBOL(rtl_pci_suspend);  int rtl_pci_resume(struct pci_dev *pdev)  {  	int ret; +	struct ieee80211_hw *hw = pci_get_drvdata(pdev); +	struct rtl_priv *rtlpriv = rtl_priv(hw);  	pci_set_power_state(pdev, PCI_D0);  	ret = pci_enable_device(pdev); @@ -1865,15 +2033,20 @@ int rtl_pci_resume(struct pci_dev *pdev)  	pci_restore_state(pdev); +	rtlpriv->cfg->ops->hw_resume(hw); +	rtl_init_rfkill(hw);  	return 0;  }  EXPORT_SYMBOL(rtl_pci_resume);  struct rtl_intf_ops rtl_pci_ops = { +	.read_efuse_byte = read_efuse_byte,  	.adapter_start = rtl_pci_start,  	.adapter_stop = rtl_pci_stop,  	.adapter_tx = rtl_pci_tx, +	.flush = rtl_pci_flush,  	.reset_trx_ring = rtl_pci_reset_trx_ring, +	.waitq_insert = rtl_pci_tx_chk_waitq_insert,  	.disable_aspm = rtl_pci_disable_aspm,  	.enable_aspm = rtl_pci_enable_aspm, |