2014-03-24 06:01:06

by Adam Lee

[permalink] [raw]
Subject: [PATCH] rtlwifi: rtl8188ee: enable MSI interrupts support

Some HP notebooks using this rtl8188ee hardware module can't get
AP scan results with pin-based interrupts, enabling MSI interrupts could
fix it.

Signed-off-by: Adam Lee <[email protected]>
---
drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
index 347af1e..1b4101b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
@@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
u8 tid;

rtl8188ee_bt_reg_init(hw);
+ rtlpci->msi_support = true;

rtlpriv->dm.dm_initialgain_enable = 1;
rtlpriv->dm.dm_flag = 0;
--
1.9.1



2014-03-24 06:05:29

by Adam Lee

[permalink] [raw]
Subject: Re: [PATCH] rtlwifi: rtl8188ee: enable MSI interrupts support

On Mon, Mar 24, 2014 at 02:00:41PM +0800, Adam Lee wrote:
> Some HP notebooks using this rtl8188ee hardware module can't get
> AP scan results with pin-based interrupts, enabling MSI interrupts could
> fix it.
>
> Signed-off-by: Adam Lee <[email protected]>
> ---
> drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> index 347af1e..1b4101b 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> @@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
> u8 tid;
>
> rtl8188ee_bt_reg_init(hw);
> + rtlpci->msi_support = true;
>
> rtlpriv->dm.dm_initialgain_enable = 1;
> rtlpriv->dm.dm_flag = 0;
> --
> 1.9.1

Cc: [email protected]

--
Adam Lee

2014-03-24 11:35:01

by Adam Lee

[permalink] [raw]
Subject: [PATCH] rtlwifi: add MSI interrupts support

Add MSI interrupts support, enable it when msi_support flag is true,
also could fallback to pin-based interrupts mode if MSI mode fails.

Signed-off-by: Adam Lee <[email protected]>
---
drivers/net/wireless/rtlwifi/pci.c | 63 ++++++++++++++++++++++++++++++++++++--
1 file changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index f26f4ff..dd8497a 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1853,6 +1853,63 @@ 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 == true) {
+ 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 +2052,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 +2120,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
rtlpci->irq_alloc = 0;
}

+ if (rtlpci->using_msi == true)
+ 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);
--
1.9.1


2014-03-24 06:10:28

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] rtlwifi: rtl8188ee: enable MSI interrupts support

On Mon, Mar 24, 2014 at 02:05:21PM +0800, Adam Lee wrote:
> On Mon, Mar 24, 2014 at 02:00:41PM +0800, Adam Lee wrote:
> > Some HP notebooks using this rtl8188ee hardware module can't get
> > AP scan results with pin-based interrupts, enabling MSI interrupts could
> > fix it.
> >
> > Signed-off-by: Adam Lee <[email protected]>
> > ---
> > drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> > index 347af1e..1b4101b 100644
> > --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> > +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
> > @@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
> > u8 tid;
> >
> > rtl8188ee_bt_reg_init(hw);
> > + rtlpci->msi_support = true;
> >
> > rtlpriv->dm.dm_initialgain_enable = 1;
> > rtlpriv->dm.dm_flag = 0;
> > --
> > 1.9.1
>
> Cc: [email protected]


<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

2014-03-24 15:14:10

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH] rtlwifi: add MSI interrupts support

On 03/24/2014 06:34 AM, Adam Lee wrote:
> Add MSI interrupts support, enable it when msi_support flag is true,
> also could fallback to pin-based interrupts mode if MSI mode fails.
>
> Signed-off-by: Adam Lee <[email protected]>

Your first patch turns on MSI support unconditionally. That implies that there
are no harmful effects for attempting to use MSI on a box where it is not
needed, and/or not implemented. If that is the case, then the msi_support bool
should be eliminated, your first patch dropped, and this one revised
appropriately. Driver rtl8723be added this bool, but never uses it. Once that
driver reaches mainline, a patch can be prepared to remove the variable.

I think this patch should be applied to stable. Applying it back to 3.10+ should
be far enough. That will pick up the initial submission of the RTL8188EE driver.
Boxes that need MSI interrupts are not likely to use any of the older chips.

There are some additional in-line comments below.

> ---
> drivers/net/wireless/rtlwifi/pci.c | 63 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
> index f26f4ff..dd8497a 100644
> --- a/drivers/net/wireless/rtlwifi/pci.c
> +++ b/drivers/net/wireless/rtlwifi/pci.c
> @@ -1853,6 +1853,63 @@ 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;

I like a blank line between the declarations and the code.

> + 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"));

Doesn't checkpatch.pl complain about the alignment here?

> + 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 == true) {

As discussed above, this test is not needed. If it were, the current version of
checkpatch.pl complains about the "== true" part.

> + 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 +2052,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 +2120,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
> rtlpci->irq_alloc = 0;
> }
>
> + if (rtlpci->using_msi == true)

Again "if (rtlpci->using_msi)" is preferred.

> + 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);
>

When you resubmit, use "[PATCH V2]" in the subject, and use the proper CC stable
with [3.10+] following the address.

Larry


2014-03-27 18:45:51

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH v2] rtlwifi: add MSI interrupts support

On 03/27/2014 01:15 PM, John W. Linville wrote:
> I'm confused -- is "rtlwifi: rtl8188ee: enable MSI interrupts support"
> still wanted/needed?

I think so, but Adam needs to resubmit both patches in a V3.

Larry



2014-03-24 11:49:38

by Adam Lee

[permalink] [raw]
Subject: Re: [PATCH] rtlwifi: add MSI interrupts support

On Mon, Mar 24, 2014 at 07:34:44PM +0800, Adam Lee wrote:
> Add MSI interrupts support, enable it when msi_support flag is true,
> also could fallback to pin-based interrupts mode if MSI mode fails.
>
> Signed-off-by: Adam Lee <[email protected]>
> ---
> drivers/net/wireless/rtlwifi/pci.c | 63 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 61 insertions(+), 2 deletions(-)

This is the base of "[PATCH] rtlwifi: rtl8188ee: enable MSI interrupts
support" in thread. We met this issue[1] while enabling some HP
notebooks, whose wifi hardware modules can't get AP scan results with
pin-based interrupts.

Submitting these two patches ahead of RealTek's schedule so we can fix
it sooner for non-preload distro users.

[1] https://bugs.launchpad.net/bugs/1296591

--
Adam Lee

2014-03-25 09:13:30

by Adam Lee

[permalink] [raw]
Subject: Re: [PATCH] rtlwifi: add MSI interrupts support

On Mon, Mar 24, 2014 at 10:14:06AM -0500, Larry Finger wrote:
> On 03/24/2014 06:34 AM, Adam Lee wrote:
> >Add MSI interrupts support, enable it when msi_support flag is true,
> >also could fallback to pin-based interrupts mode if MSI mode fails.
> >
> >Signed-off-by: Adam Lee <[email protected]>
>
> Your first patch turns on MSI support unconditionally. That implies that
> there are no harmful effects for attempting to use MSI on a box where it is
> not needed, and/or not implemented. If that is the case, then the
> msi_support bool should be eliminated, your first patch dropped, and this
> one revised appropriately. Driver rtl8723be added this bool, but never uses
> it. Once that driver reaches mainline, a patch can be prepared to remove the
> variable.

Hi, Larry

Just confirmed with RealTek wireless engineer, their policy is:

> Case 1: if the platform supports both MSI and Pin-based, our driver will use MSI.
> Case 2: if the platform supports MSI only, our driver will use MSI.
> Case 3: if the platform supports Pin-Based only, out driver will use Pin-Based.

I think it's safe enough to apply the first "rtlwifi: rtl8188ee: enable
MSI interrupts support" patch also, and the msi_support bool should not
be eliminated(at least for now) in case some wifi modules don't support
MSI well.

Thanks.

--
Adam Lee

2014-03-28 03:36:31

by Adam Lee

[permalink] [raw]
Subject: [PATCH v3 1/2] 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 <[email protected]>
---
drivers/net/wireless/rtlwifi/pci.c | 65 ++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 7d71170..dae5525 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,
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);
--
1.9.1


2014-03-25 02:49:00

by Adam Lee

[permalink] [raw]
Subject: [PATCH v2] rtlwifi: add MSI interrupts support

Add MSI interrupts support, enable it when msi_support flag is true,
also could fallback to pin-based interrupts mode if MSI mode fails.

Signed-off-by: Adam Lee <[email protected]>
Cc: <[email protected]> [3.10+]
---
drivers/net/wireless/rtlwifi/pci.c | 65 ++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index f26f4ff..155d010 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,
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);
--
1.9.1


2014-03-28 03:36:37

by Adam Lee

[permalink] [raw]
Subject: [PATCH v3 2/2] rtlwifi: rtl8188ee: enable MSI interrupts mode

Some HP notebooks using this rtl8188ee hardware module can't get
AP scan results with pin-based interrupts mode, enabling MSI interrupts
mode could fix it.

As RealTek's testing results, RTL8188EE works well with both MSI mode
and pin-based mode fallback.

Signed-off-by: Adam Lee <[email protected]>
---
drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
index 347af1e..1b4101b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
@@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
u8 tid;

rtl8188ee_bt_reg_init(hw);
+ rtlpci->msi_support = true;

rtlpriv->dm.dm_initialgain_enable = 1;
rtlpriv->dm.dm_flag = 0;
--
1.9.1


2014-03-27 18:30:14

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH v2] rtlwifi: add MSI interrupts support

I'm confused -- is "rtlwifi: rtl8188ee: enable MSI interrupts support"
still wanted/needed?

John

On Tue, Mar 25, 2014 at 10:48:52AM +0800, Adam Lee wrote:
> Add MSI interrupts support, enable it when msi_support flag is true,
> also could fallback to pin-based interrupts mode if MSI mode fails.
>
> Signed-off-by: Adam Lee <[email protected]>
> Cc: <[email protected]> [3.10+]
> ---
> drivers/net/wireless/rtlwifi/pci.c | 65 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
> index f26f4ff..155d010 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,
> 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);
> --
> 1.9.1
>
>

--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.