summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtlwifi/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtlwifi/pci.c')
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c609
1 files changed, 391 insertions, 218 deletions
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 5938f6ee21e4..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 - Always 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,