rtlwifi: Add missing DMA buffer unmapping for PCI drivers
[linux-flexiantxendom0.git] / drivers / net / wireless / rtlwifi / pci.c
index cb4e5e8..d44d398 100644 (file)
@@ -27,6 +27,7 @@
  *
  *****************************************************************************/
 
+#include <linux/export.h>
 #include "core.h"
 #include "wifi.h"
 #include "pci.h"
 #include "efuse.h"
 
 static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
-       INTEL_VENDOR_ID,
-       ATI_VENDOR_ID,
-       AMD_VENDOR_ID,
-       SIS_VENDOR_ID
+       PCI_VENDOR_ID_INTEL,
+       PCI_VENDOR_ID_ATI,
+       PCI_VENDOR_ID_AMD,
+       PCI_VENDOR_ID_SI
 };
 
 static const u8 ac_to_hwq[] = {
@@ -218,7 +219,6 @@ static void rtl_pci_disable_aspm(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;
-       u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
        u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
        /*Retrieve original configuration settings. */
        u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
@@ -254,9 +254,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
        udelay(50);
 
        /*4 Disable Pci Bridge ASPM */
-       rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                                    pcicfg_addrport + (num4bytes << 2));
-       rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
+       pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+                             pcibridge_linkctrlreg);
 
        udelay(50);
 }
@@ -277,7 +276,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
        u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum;
        u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum;
        u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
-       u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
        u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
        u16 aspmlevel;
        u8 u_pcibridge_aspmsetting;
@@ -293,8 +291,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
        }
 
        /*4 Enable Pci Bridge ASPM */
-       rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                                    pcicfg_addrport + (num4bytes << 2));
 
        u_pcibridge_aspmsetting =
            pcipriv->ndis_adapter.pcibridge_linkctrlreg |
@@ -303,7 +299,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
        if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
                u_pcibridge_aspmsetting &= ~BIT(0);
 
-       rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting);
+       pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+                             u_pcibridge_aspmsetting);
 
        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
                 ("PlatformEnableASPM():PciBridge busnumber[%x], "
@@ -335,25 +332,18 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
 
 static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
 {
-       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
-       u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
        bool status = false;
        u8 offset_e0;
        unsigned offset_e4;
 
-       rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                       pcicfg_addrport + 0xE0);
-       rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, 0xA0);
+       pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0);
 
-       rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                       pcicfg_addrport + 0xE0);
-       rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &offset_e0);
+       pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0);
 
        if (offset_e0 == 0xA0) {
-               rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                                            pcicfg_addrport + 0xE4);
-               rtl_pci_raw_read_port_ulong(PCI_CONF_DATA, &offset_e4);
+               pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4);
                if (offset_e4 & BIT(23))
                        status = true;
        }
@@ -364,17 +354,15 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
 static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
 {
        struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
        u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
-       u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
        u8 linkctrl_reg;
        u8 num4bbytes;
 
        num4bbytes = (capabilityoffset + 0x10) / 4;
 
        /*Read  Link Control Register */
-       rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
-                                    pcicfg_addrport + (num4bbytes << 2));
-       rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg);
+       pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
 
        pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
 }
@@ -390,7 +378,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
        u8 linkctrl_reg;
 
        /*Link Control Register */
-       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(pdev);
        pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
        pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
 
@@ -488,7 +476,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *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 */
+       int tid;
 
        if (!rtlpriv->rtlhal.earlymode_enable)
                return;
@@ -581,7 +569,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
                fc = rtl_get_fc(skb);
                if (ieee80211_is_nullfunc(fc)) {
                        if (ieee80211_has_pm(fc)) {
-                               rtlpriv->mac80211.offchan_deley = true;
+                               rtlpriv->mac80211.offchan_delay = true;
                                rtlpriv->psc.state_inap = 1;
                        } else {
                                rtlpriv->psc.state_inap = 0;
@@ -669,6 +657,8 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
                return;
 
        uskb = dev_alloc_skb(skb->len + 128);
+       if (!uskb)
+               return;         /* exit if allocation failed */
        memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
        pdata = (u8 *)skb_put(uskb, skb->len);
        memcpy(pdata, skb->data, skb->len);
@@ -788,15 +778,11 @@ 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;
 
-       if (rtlpci->irq_enabled == 0)
-               return IRQ_HANDLED;
-
        spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 
        /*read ISR: 4/8bytes */
@@ -940,8 +926,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
        memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
        ring = &rtlpci->tx_ring[BEACON_QUEUE];
        pskb = __skb_dequeue(&ring->queue);
-       if (pskb)
+       if (pskb) {
+               struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+               pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc(
+                                (u8 *) entry, true, HW_DESC_TXBUFF_ADDR),
+                                pskb->len, PCI_DMA_TODEVICE);
                kfree_skb(pskb);
+       }
 
        /*NB: the beacon data buffer must be 32-bit aligned. */
        pskb = ieee80211_beacon_get(hw, mac->vif);
@@ -1169,10 +1160,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
                ring->idx = (ring->idx + 1) % ring->entries;
        }
 
-       pci_free_consistent(rtlpci->pdev,
-                           sizeof(*ring->desc) * ring->entries,
-                           ring->desc, ring->dma);
-       ring->desc = NULL;
+       if (ring->desc) {
+               pci_free_consistent(rtlpci->pdev,
+                                   sizeof(*ring->desc) * ring->entries,
+                                   ring->desc, ring->dma);
+               ring->desc = NULL;
+       }
 }
 
 static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
@@ -1196,12 +1189,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
                        kfree_skb(skb);
                }
 
-               pci_free_consistent(rtlpci->pdev,
+               if (rtlpci->rx_ring[rx_queue_idx].desc) {
+                       pci_free_consistent(rtlpci->pdev,
                                    sizeof(*rtlpci->rx_ring[rx_queue_idx].
                                           desc) * rtlpci->rxringcount,
                                    rtlpci->rx_ring[rx_queue_idx].desc,
                                    rtlpci->rx_ring[rx_queue_idx].dma);
-               rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+                       rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+               }
        }
 }
 
@@ -1542,7 +1537,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
 
        rtl_init_rx_config(hw);
 
-       /*should after adapter start and interrupt enable. */
+       /*should be after adapter start and interrupt enable. */
        set_hal_start(rtlhal);
 
        RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
@@ -1563,7 +1558,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        u8 RFInProgressTimeOut = 0;
 
        /*
-        *should before disable interrrupt&adapter
+        *should be before disable interrupt&adapter
         *and will do it immediately.
         */
        set_hal_stop(rtlhal);
@@ -1615,6 +1610,16 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
        pci_read_config_byte(pdev, 0x8, &revisionid);
        pci_read_config_word(pdev, 0x3C, &irqline);
 
+       /* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses
+        * r8192e_pci, and RTL8192SE, which uses this driver. If the
+        * revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then
+        * the correct driver is r8192e_pci, thus this routine should
+        * return false.
+        */
+       if (deviceid == RTL_PCI_8192SE_DID &&
+           revisionid == RTL_PCI_REVISION_ID_8192PCIE)
+               return false;
+
        if (deviceid == RTL_PCI_8192_DID ||
            deviceid == RTL_PCI_0044_DID ||
            deviceid == RTL_PCI_0047_DID ||
@@ -1690,15 +1695,17 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
        pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
        pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn);
 
-       /*find bridge info */
-       pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
-       for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
-               if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
-                       pcipriv->ndis_adapter.pcibridge_vendor = tmp;
-                       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-                                ("Pci Bridge Vendor is found index: %d\n",
-                                 tmp));
-                       break;
+       if (bridge_pdev) {
+               /*find bridge info if available */
+               pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
+               for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
+                       if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
+                               pcipriv->ndis_adapter.pcibridge_vendor = tmp;
+                               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+                                        ("Pci Bridge Vendor is found index:"
+                                        " %d\n", tmp));
+                               break;
+                       }
                }
        }
 
@@ -1710,10 +1717,6 @@ 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.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 =
@@ -1847,7 +1850,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
        pci_write_config_byte(pdev, 0x04, 0x07);
 
        /* find adapter */
-       _rtl_pci_find_adapter(pdev, hw);
+       if (!_rtl_pci_find_adapter(pdev, hw))
+               goto fail3;
 
        /* Init IO handler */
        _rtl_pci_io_handler_init(&pdev->dev, hw);
@@ -2001,36 +2005,25 @@ call rtl_mac_stop() from the mac80211
 suspend function first, So there is
 no need to call hw_disable here.
 ****************************************/
-int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int rtl_pci_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        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);
 
-int rtl_pci_resume(struct pci_dev *pdev)
+int rtl_pci_resume(struct device *dev)
 {
-       int ret;
+       struct pci_dev *pdev = to_pci_dev(dev);
        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);
-       if (ret) {
-               RT_ASSERT(false, ("ERR: <======\n"));
-               return ret;
-       }
-
-       pci_restore_state(pdev);
-
        rtlpriv->cfg->ops->hw_resume(hw);
        rtl_init_rfkill(hw);
        return 0;