|
|
@@ -1853,6 +1853,65 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw)
|
|
|
+{
|
|
|
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
|
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
|
|
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = pci_enable_msi(rtlpci->pdev);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
|
|
|
+ IRQF_SHARED, KBUILD_MODNAME, hw);
|
|
|
+ if (ret < 0) {
|
|
|
+ pci_disable_msi(rtlpci->pdev);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ rtlpci->using_msi = true;
|
|
|
+
|
|
|
+ RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
|
|
|
+ "MSI Interrupt Mode!\n");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw)
|
|
|
+{
|
|
|
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
|
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
|
|
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
|
|
|
+ IRQF_SHARED, KBUILD_MODNAME, hw);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ rtlpci->using_msi = false;
|
|
|
+ RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
|
|
|
+ "Pin-based Interrupt Mode!\n");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtl_pci_intr_mode_decide(struct ieee80211_hw *hw)
|
|
|
+{
|
|
|
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
|
|
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (rtlpci->msi_support) {
|
|
|
+ ret = rtl_pci_intr_mode_msi(hw);
|
|
|
+ if (ret < 0)
|
|
|
+ ret = rtl_pci_intr_mode_legacy(hw);
|
|
|
+ } else {
|
|
|
+ ret = rtl_pci_intr_mode_legacy(hw);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
int rtl_pci_probe(struct pci_dev *pdev,
|
|
|
const struct pci_device_id *id)
|
|
|
{
|
|
|
@@ -1995,8 +2054,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
|
|
|
}
|
|
|
|
|
|
rtlpci = rtl_pcidev(pcipriv);
|
|
|
- err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
|
|
|
- IRQF_SHARED, KBUILD_MODNAME, hw);
|
|
|
+ err = rtl_pci_intr_mode_decide(hw);
|
|
|
if (err) {
|
|
|
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
|
|
|
"%s: failed to register IRQ handler\n",
|
|
|
@@ -2064,6 +2122,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
|
|
|
rtlpci->irq_alloc = 0;
|
|
|
}
|
|
|
|
|
|
+ if (rtlpci->using_msi)
|
|
|
+ pci_disable_msi(rtlpci->pdev);
|
|
|
+
|
|
|
list_del(&rtlpriv->list);
|
|
|
if (rtlpriv->io.pci_mem_start != 0) {
|
|
|
pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
|