aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtlwifi
diff options
context:
space:
mode:
authorAdam Lee <adam.lee@canonical.com>2014-03-27 23:36:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-03-31 13:47:41 -0400
commit94010fa0dd07e8b904e7c6b6589f15573008ab15 (patch)
treed26c0bd3391c7b1dec8f371f4901c681eaf8ab4a /drivers/net/wireless/rtlwifi
parent52250cbee7f62400140295a632e0ffbbe5b083ca (diff)
rtlwifi: add MSI interrupts mode support
Add MSI interrupts mode support, enable it when submodules' msi_support flag is true, also could fallback to pin-based interrupts mode if MSI interrupts mode fails. RealTek's policy(on modules which work well with MSI interrupts mode) is: > If the platform supports both MSI and pin-based, use MSI. > If the platform supports MSI only, use MSI. > If the platform supports pin-based only, use pin-based. Also as RealTek's testing results, RTL8188EE and RTL8723BE work well with both MSI mode and pin-based mode fallback. Signed-off-by: Adam Lee <adam.lee@canonical.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi')
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 7d711708d2f3..dae55257f0e8 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1853,6 +1853,65 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
1853 return true; 1853 return true;
1854} 1854}
1855 1855
1856static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw)
1857{
1858 struct rtl_priv *rtlpriv = rtl_priv(hw);
1859 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
1860 struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
1861 int ret;
1862
1863 ret = pci_enable_msi(rtlpci->pdev);
1864 if (ret < 0)
1865 return ret;
1866
1867 ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
1868 IRQF_SHARED, KBUILD_MODNAME, hw);
1869 if (ret < 0) {
1870 pci_disable_msi(rtlpci->pdev);
1871 return ret;
1872 }
1873
1874 rtlpci->using_msi = true;
1875
1876 RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
1877 "MSI Interrupt Mode!\n");
1878 return 0;
1879}
1880
1881static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw)
1882{
1883 struct rtl_priv *rtlpriv = rtl_priv(hw);
1884 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
1885 struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
1886 int ret;
1887
1888 ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
1889 IRQF_SHARED, KBUILD_MODNAME, hw);
1890 if (ret < 0)
1891 return ret;
1892
1893 rtlpci->using_msi = false;
1894 RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
1895 "Pin-based Interrupt Mode!\n");
1896 return 0;
1897}
1898
1899static int rtl_pci_intr_mode_decide(struct ieee80211_hw *hw)
1900{
1901 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
1902 struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
1903 int ret;
1904
1905 if (rtlpci->msi_support) {
1906 ret = rtl_pci_intr_mode_msi(hw);
1907 if (ret < 0)
1908 ret = rtl_pci_intr_mode_legacy(hw);
1909 } else {
1910 ret = rtl_pci_intr_mode_legacy(hw);
1911 }
1912 return ret;
1913}
1914
1856int rtl_pci_probe(struct pci_dev *pdev, 1915int rtl_pci_probe(struct pci_dev *pdev,
1857 const struct pci_device_id *id) 1916 const struct pci_device_id *id)
1858{ 1917{
@@ -1995,8 +2054,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
1995 } 2054 }
1996 2055
1997 rtlpci = rtl_pcidev(pcipriv); 2056 rtlpci = rtl_pcidev(pcipriv);
1998 err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, 2057 err = rtl_pci_intr_mode_decide(hw);
1999 IRQF_SHARED, KBUILD_MODNAME, hw);
2000 if (err) { 2058 if (err) {
2001 RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, 2059 RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
2002 "%s: failed to register IRQ handler\n", 2060 "%s: failed to register IRQ handler\n",
@@ -2064,6 +2122,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
2064 rtlpci->irq_alloc = 0; 2122 rtlpci->irq_alloc = 0;
2065 } 2123 }
2066 2124
2125 if (rtlpci->using_msi)
2126 pci_disable_msi(rtlpci->pdev);
2127
2067 list_del(&rtlpriv->list); 2128 list_del(&rtlpriv->list);
2068 if (rtlpriv->io.pci_mem_start != 0) { 2129 if (rtlpriv->io.pci_mem_start != 0) {
2069 pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); 2130 pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);