* Re: [PATCH v2 6/8] ath10k: implement ath10k_pci_soc_read/write32()
From: Michal Kazior @ 2013-10-16 15:38 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <20131016134611.25095.80204.stgit@localhost6.localdomain6>
On 16 October 2013 06:46, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> To make it easier to access SOC registers. No functional
> changes.
>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath10k/pci.c | 3 +--
> drivers/net/wireless/ath/ath10k/pci.h | 10 ++++++++++
> 2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
> index d09f8a2..5c78383 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -2454,8 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
> return ret;
> }
>
> - chip_id = ath10k_pci_read32(ar,
> - RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS);
> + chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
>
> ath10k_do_pci_sleep(ar);
>
> diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
> index 52fb7b9..a304c33 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.h
> +++ b/drivers/net/wireless/ath/ath10k/pci.h
> @@ -318,6 +318,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
> return ioread32(ar_pci->mem + offset);
> }
>
> +static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
> +{
> + return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
> +}
> +
> +static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
> +{
> + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
> +}
> +
I'm not entirely sure about this. There are a couple of soc address
groups (RTC_SOC, RTC_WMAC, SOC_PCIE, SOC_CORE, ..).
I'd rather use just raw ioread/iowrite than have all those wrappers. I
think the reason for having ath10k_pci_{read,write}32 was the HW v1
workaround. Do we really need to keep it?
Michał
^ permalink raw reply
* Re: [PATCH v2 7/8] ath10k: fix device initialization routine
From: Michal Kazior @ 2013-10-16 15:44 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <20131016134617.25095.10581.stgit@localhost6.localdomain6>
On 16 October 2013 06:46, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> From: Michal Kazior <michal.kazior@tieto.com>
>
> Hardware revision 2 does not support cold reset
> correctly. As such it would sometimes lead to host
> machine freeze or data bus errors.
>
> The patch introduces warm reset function which is
> used instead of the cold reset one. It also moves
> the reset before interrupts are being set up to
> prevent any kind of spurious interrupts from being
> handled.
>
> kvalo: use ath10k_pci_write32() style wrappers, fix long
> lines
>
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
> ---
[...]
> @@ -1825,16 +1824,78 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
> ath10k_pci_sleep(ar);
> }
>
> -static int ath10k_pci_hif_power_up(struct ath10k *ar)
> +static int ath10k_pci_warm_reset(struct ath10k *ar)
> {
> struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
> int ret;
> + u32 val;
>
> - ret = ath10k_pci_start_intr(ar);
> - if (ret) {
> - ath10k_err("could not start interrupt handling (%d)\n", ret);
> - goto err;
> - }
> + ath10k_dbg(ATH10K_DBG_BOOT, "performing warm chip reset\n");
> +
> + ret = ath10k_do_pci_wake(ar);
> + if (ret)
> + return ret;
> +
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "pci intr cause 0x%08x cpu intr 0x%08x (before)\n",
> + ath10k_pci_core_read32(ar, PCIE_INTR_CAUSE_ADDRESS),
> + ath10k_pci_core_read32(ar, CPU_INTR_ADDRESS));
> +
> + /* disable pending irqs */
> + ath10k_pci_core_write32(ar, PCIE_INTR_ENABLE_ADDRESS, 0);
> + ath10k_pci_core_write32(ar, PCIE_INTR_CLR_ADDRESS, ~0);
These use SOC_CORE_BASE_ADDRESS as the suffix, not the RTC_SOC_BASE_ADDRESS.
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "pci intr cause 0x%08x cpu intr 0x%08x (after)\n",
> + ath10k_pci_core_read32(ar, PCIE_INTR_CAUSE_ADDRESS),
> + ath10k_pci_core_read32(ar, CPU_INTR_ADDRESS));
Ditto. These are in SOC_CORE_BASE_ADDRESS group.
Michał
^ permalink raw reply
* Re: [PATCH v2 6/8] ath10k: implement ath10k_pci_soc_read/write32()
From: Kalle Valo @ 2013-10-16 15:55 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQmP14xuXP=D4mEsJiWOXvtg0iJ4=BmUb=89QgA_AX5edA@mail.gmail.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> On 16 October 2013 06:46, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>> To make it easier to access SOC registers. No functional
>> changes.
>>
>> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
>> ---
>> drivers/net/wireless/ath/ath10k/pci.c | 3 +--
>> drivers/net/wireless/ath/ath10k/pci.h | 10 ++++++++++
>> 2 files changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
>> index d09f8a2..5c78383 100644
>> --- a/drivers/net/wireless/ath/ath10k/pci.c
>> +++ b/drivers/net/wireless/ath/ath10k/pci.c
>> @@ -2454,8 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
>> return ret;
>> }
>>
>> - chip_id = ath10k_pci_read32(ar,
>> - RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS);
>> + chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
>>
>> ath10k_do_pci_sleep(ar);
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
>> index 52fb7b9..a304c33 100644
>> --- a/drivers/net/wireless/ath/ath10k/pci.h
>> +++ b/drivers/net/wireless/ath/ath10k/pci.h
>> @@ -318,6 +318,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
>> return ioread32(ar_pci->mem + offset);
>> }
>>
>> +static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
>> +{
>> + return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
>> +}
>> +
>> +static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
>> +{
>> + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
>> +}
>> +
>
> I'm not entirely sure about this. There are a couple of soc address
> groups (RTC_SOC, RTC_WMAC, SOC_PCIE, SOC_CORE, ..).
And then we can have different functions for each group.
> I'd rather use just raw ioread/iowrite than have all those wrappers.
Well, I again would prefer to have clean interfaces instead of doing
address arithmetic in every call :)
> I think the reason for having ath10k_pci_{read,write}32 was the HW v1
> workaround.
No, it was also to make the code simple.
> Do we really need to keep it?
In my opinion yes. What is the negative side of keeping them? Why don't
you like these wrappers?
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2 7/8] ath10k: fix device initialization routine
From: Kalle Valo @ 2013-10-16 15:57 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQkqkuf-=a4giyJHeYdXZ2T3deU7nmuQOxpFcKSzWjGb3Q@mail.gmail.com>
Michal Kazior <michal.kazior@tieto.com> writes:
>> + /* disable pending irqs */
>> + ath10k_pci_core_write32(ar, PCIE_INTR_ENABLE_ADDRESS, 0);
>> + ath10k_pci_core_write32(ar, PCIE_INTR_CLR_ADDRESS, ~0);
>
> These use SOC_CORE_BASE_ADDRESS as the suffix, not the RTC_SOC_BASE_ADDRESS.
But I am using SOC_CORE_BASE_ADDRESS, right?
static inline u32 ath10k_pci_core_read32(struct ath10k *ar, u32 addr)
{
return ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + addr);
}
static inline void ath10k_pci_core_write32(struct ath10k *ar, u32 addr, u32 val)
{
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + addr, val);
}
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2 7/8] ath10k: fix device initialization routine
From: Michal Kazior @ 2013-10-16 16:01 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <87ppr55hun.fsf@kamboji.qca.qualcomm.com>
On 16 October 2013 08:57, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior@tieto.com> writes:
>
>>> + /* disable pending irqs */
>>> + ath10k_pci_core_write32(ar, PCIE_INTR_ENABLE_ADDRESS, 0);
>>> + ath10k_pci_core_write32(ar, PCIE_INTR_CLR_ADDRESS, ~0);
>>
>> These use SOC_CORE_BASE_ADDRESS as the suffix, not the RTC_SOC_BASE_ADDRESS.
>
> But I am using SOC_CORE_BASE_ADDRESS, right?
Ah, right. Sorry. My eyesight failed me :) Those function names seem a
little confusing (_core_ for SOC_CORE and _soc_ for RTC_SOC)
Michał
^ permalink raw reply
* Re: [PATCH 0/5] rfkill-gpio: ACPI support
From: Rhyland Klein @ 2013-10-16 16:13 UTC (permalink / raw)
To: Heikki Krogerus
Cc: John W. Linville, Johannes Berg, Rafael J. Wysocki,
linux-acpi@vger.kernel.org, linux-wireless@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <1381920823-15403-1-git-send-email-heikki.krogerus@linux.intel.com>
On 10/16/2013 6:53 AM, Heikki Krogerus wrote:
> Hi,
>
> The first patches prepare the driver for the support. The last patch
> can then add the support quite easily. With these patches, adding DT
> support later will be quite straight forward if someone needs it.
>
>
> Heikki Krogerus (5):
> net: rfkill: gpio: convert to resource managed allocation
> net: rfkill: gpio: clean up clock handling
> net: rfkill: gpio: spinlock-safe GPIO access
> net: rfkill: gpio: prepare for DT and ACPI support
> net: rfkill: gpio: add ACPI support
>
> net/rfkill/Kconfig | 2 +-
> net/rfkill/rfkill-gpio.c | 211 ++++++++++++++++++++++-------------------------
> 2 files changed, 99 insertions(+), 114 deletions(-)
>
Strictly speaking, duplicating the pdata fields into the
rfkill_gpio_data structure isn't really necessary. Many drivers simply
have the dt parsing or in this case ACPI parsing generate a
platform_data structure which would then be saved in the
rfkill_gpio_data structure.
In this case, since it is only a few fields, I am not too worried and I
am fine either way.
Acked-by: Rhyland Klein <rklein@nvidia.com>
--
nvpublic
^ permalink raw reply
* Re: p54usb raspberry pi no wlan0 device
From: Andrey @ 2013-10-16 16:35 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <trinity-4366d417-bdc3-4e3b-a613-25b1af7a51a7-1379880343916@3capp-gmx-bs34>
<the_force@...> writes:
>
>
> Hi Folks,
>
> i want to use an Corega WLUSB2GTST USB adapter on my Raspberry Pi linux
device. I used fwextract utility with
> the driver file (Windows 2000 driver, nobyteswap option). So i got these
2 files:
>
> cgwlusb200.arm
> cgwlusb201.arm
>
> I have copied these files (i tried cgwlusb200.arm also cgwlusb201.arm) to
the following location on my
> Raspberry Pi:
>
> /lib/firmware/isl3887usb
> /lib/modules/3.6.11+/kernel/drivers/net/wireless/isl3887usb
>
> After doing a modprobe p54usb, the module seems to load fine:
>
> root <at> pinulldrei:/lib/firmware# lsmod
> ModuleSize Used by
> p54usb 11627 0
> p54common 30229 1 p54usb
> crc_ccitt 1530 1 p54common
> mac80211 273979 2 p54common,p54usb
> cfg80211 184390 2 mac80211,p54common
> rfkill 18298 1 cfg80211
> tun 14995 2
> snd_bcm2835 16432 0
> snd_pcm 77728 1 snd_bcm2835
> snd_seq 53482 0
> snd_timer 20110 2 snd_pcm,snd_seq
> snd_seq_device 6462 1 snd_seq
> snd 58744 5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
> snd_page_alloc 5169 1 snd_pcm
> leds_gpio 2243 0
> led_class 3570 2 leds_gpio,p54common
> root <at> pinulldrei:/lib/firmware#
>
> dmesg says:
> [1031466.099404] usb 1-1.2.1: new high-speed USB device number 10 using
dwc_otg
> [1031466.202908] usb 1-1.2.1: New USB device found, idVendor=07aa,
idProduct=0020
> [1031466.202939] usb 1-1.2.1: New USB device strings: Mfr=1, Product=2,
SerialNumber=3
> [1031554.700433] cfg80211: Calling CRDA to update world regulatory domain
> [1031554.755865] usbcore: registered new interface driver p54usb
>
> /var/log/messages says:
> Sep 22 21:33:08 pinulldrei kernel: [1031466.099404] usb 1-1.2.1: new high-
speed USB device number 10
> using dwc_otg
> Sep 22 21:33:09 pinulldrei kernel: [1031466.202908] usb 1-1.2.1: New USB
device found, idVendor=07aa, idProduct=0020
> Sep 22 21:33:09 pinulldrei kernel: [1031466.202939] usb 1-1.2.1: New USB
device strings: Mfr=1,
> Product=2, SerialNumber=3
> Sep 22 21:34:37 pinulldrei kernel: [1031554.700433] cfg80211: Calling
CRDA to update world regulatory domain
> Sep 22 21:34:37 pinulldrei kernel: [1031554.755865] usbcore: registered
new interface driver p54usb
>
> Everything looks fine - but no wlan0 device will be created The led on
the stick will not turn on, so i think
> i have a driver problem.
>
> How can i debug / solve this problem?!?
>
> Greetings from Germany,
> Jörg
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless"
in
> the body of a message to majordomo@...
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
The same shit, it seems like p54usb doesn't provide support for this Corega
wi-fi stick. If you'd have done modinfo p54usb you could see that there's
no corega's vendor and device code among available aliases, the only one
Corega device listed is 07aa:001C (your Corega WLUSB2GTST has device id
07aa:0020), but it uses different ISL chip.
^ permalink raw reply
* Re: [PATCH 2/2] staging: vt6656: rxtx change u32 [4] aWTxKey to u8[16] tx_key
From: Greg KH @ 2013-10-16 19:46 UTC (permalink / raw)
To: Malcolm Priestley; +Cc: linux-wireless
In-Reply-To: <1381870009.5100.45.camel@canaries32-MCP7A>
On Tue, Oct 15, 2013 at 09:46:49PM +0100, Malcolm Priestley wrote:
> Replace 4 x u32 aWTxKey with u8 array of 16 bytes tx_key.
>
> Replaces pbyBuf in s_vFillTxKey and connects pbyTxBufferAddr
> directly to tx_key without a cast elsewhere in structure.
>
> Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
This patch causes a bunch of compiler warnings to get spit out by the
compiler, so I can't take it.
Please fix them up and resend.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 5/5] net: rfkill: gpio: add ACPI support
From: Rafael J. Wysocki @ 2013-10-16 20:55 UTC (permalink / raw)
To: Heikki Krogerus
Cc: John W. Linville, Johannes Berg, Rhyland Klein, linux-acpi,
linux-wireless, netdev, Mika Westerberg
In-Reply-To: <1381920823-15403-6-git-send-email-heikki.krogerus@linux.intel.com>
On Wednesday, October 16, 2013 01:53:43 PM Heikki Krogerus wrote:
> Including ACPI ID for Broadcom GPS receiver BCM4752.
>
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> net/rfkill/rfkill-gpio.c | 31 ++++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
> index 2dd78c6..5620d3c 100644
> --- a/net/rfkill/rfkill-gpio.c
> +++ b/net/rfkill/rfkill-gpio.c
> @@ -24,6 +24,8 @@
> #include <linux/platform_device.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> +#include <linux/acpi.h>
> +#include <linux/acpi_gpio.h>
>
> #include <linux/rfkill-gpio.h>
>
> @@ -70,6 +72,23 @@ static const struct rfkill_ops rfkill_gpio_ops = {
> .set_block = rfkill_gpio_set_power,
> };
>
> +static int rfkill_gpio_acpi_probe(struct device *dev,
> + struct rfkill_gpio_data *rfkill)
> +{
> + const struct acpi_device_id *id;
> +
> + id = acpi_match_device(dev->driver->acpi_match_table, dev);
> + if (!id)
> + return -ENODEV;
> +
> + rfkill->name = dev_name(dev);
> + rfkill->type = (unsigned)id->driver_data;
> + rfkill->reset_gpio = acpi_get_gpio_by_index(dev, 0, NULL);
> + rfkill->shutdown_gpio = acpi_get_gpio_by_index(dev, 1, NULL);
> +
> + return 0;
> +}
> +
> static int rfkill_gpio_probe(struct platform_device *pdev)
> {
> struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
> @@ -82,7 +101,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
> if (!rfkill)
> return -ENOMEM;
>
> - if (pdata) {
> + if (ACPI_HANDLE(&pdev->dev)) {
> + ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
> + if (ret)
> + return ret;
> + } else if (pdata) {
> clk_name = pdata->power_clk_name;
> rfkill->name = pdata->name;
> rfkill->type = pdata->type;
> @@ -170,12 +193,18 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static const struct acpi_device_id rfkill_acpi_match[] = {
> + { "BCM4752", RFKILL_TYPE_GPS },
> + { },
> +};
> +
> static struct platform_driver rfkill_gpio_driver = {
> .probe = rfkill_gpio_probe,
> .remove = rfkill_gpio_remove,
> .driver = {
> .name = "rfkill_gpio",
> .owner = THIS_MODULE,
> + .acpi_match_table = ACPI_PTR(rfkill_acpi_match),
> },
> };
Looks good to me.
Has Mika seen this?
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply
* Re: [PATCH 2/2] staging: vt6656: rxtx change u32 [4] aWTxKey to u8[16] tx_key
From: Malcolm @ 2013-10-16 21:25 UTC (permalink / raw)
To: Greg KH; +Cc: linux-wireless
In-Reply-To: <20131016194638.GA25749@kroah.com>
On 16/10/13 20:46, Greg KH wrote:
> On Tue, Oct 15, 2013 at 09:46:49PM +0100, Malcolm Priestley wrote:
>> Replace 4 x u32 aWTxKey with u8 array of 16 bytes tx_key.
>>
>> Replaces pbyBuf in s_vFillTxKey and connects pbyTxBufferAddr
>> directly to tx_key without a cast elsewhere in structure.
>>
>> Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
> This patch causes a bunch of compiler warnings to get spit out by the
> compiler, so I can't take it.
>
> Please fix them up and resend.
hmm for some reason I am not getting them on gcc 4.8.1
Anyway, I will drop this patch for now. It requires changes elsewhere.
Malcolm
^ permalink raw reply
* [PATCH] drivers: net: wireless: b43: Fix possible NULL ptr dereference
From: Felipe Pena @ 2013-10-17 0:40 UTC (permalink / raw)
To: Stefano Brivio, John W. Linville
Cc: linux-wireless, b43-dev, netdev, linux-kernel, Felipe Pena
On the ternary expression the 'e' variable could be NULL dereferenced,
when b43_nphy_get_rf_ctl_over_rev7 function returns NULL.
Signed-off-by: Felipe Pena <felipensp@gmail.com>
---
drivers/net/wireless/b43/phy_n.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 7c970d3..05ee7f1 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -164,7 +164,8 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
}
en_addr = en_addrs[override][i];
- val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
+ if (e)
+ val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
if (off) {
b43_phy_mask(dev, en_addr, ~en_mask);
--
1.7.10.4
^ permalink raw reply related
* Re: ath9k AR9287 status?
From: Sujith Manoharan @ 2013-10-17 2:08 UTC (permalink / raw)
To: Bruno Randolf; +Cc: Oleksij Rempel, linux-wireless, nbd, Ingo Randolf
In-Reply-To: <524DA3DC.6060806@einfach.org>
Bruno Randolf wrote:
> I just tried current wireless-testing (3.12.0-rc3-wl) and it shows the
> same problems.
>
> For reference:
>
> Card: Unex DNXA-97 (AR9287) http://unex.com.tw/product/dnxa-97
> Board: Advantech MIO-2261N (Atom N260)
>
> ASPM is disabled in the BIOS and by pcie_aspm=off. Scanning seems to
> work, but when I start up hostapd (v2.0, simple AP config) nothing
> happens (no AP is found by clients). When I stop hostapd the system
> freezes with "BUG: soft lockup - CPU#3 stuck for 23s! (hostapd:2250)"
Can you post the kernel log with latest wireless-testing ?
Please load the driver with debug=0x8f49.
Sujith
^ permalink raw reply
* [PATCH] cfg80211/nl80211: Add support to report unsafe frequency ranges(s)
From: Rajesh Chauhan @ 2013-10-17 4:57 UTC (permalink / raw)
To: johannes, linux-wireless, rodrigue, jouni; +Cc: rajeshc
Add support for WLAN driver to report unsafe frequency range(s). User
space should move SAP/P2P-GO out of those unsafe frequency range(s).
User space may decide to continue operation on unsafe frequency but in
such case there might be impact on performance because of interference.
Signed-off-by: Rajesh Chauhan <rajeshc@qca.qualcomm.com>
---
include/net/cfg80211.h | 30 +++++++++++++++++++
include/uapi/linux/nl80211.h | 31 ++++++++++++++++++++
net/wireless/nl80211.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 129 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 45f6bf5..25b54dc 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1933,6 +1933,24 @@ struct cfg80211_update_ft_ies_params {
};
/**
+ * struct cfg80211_avoid_frequency_range - frequency range(s) to avoid
+ *
+ * This structure provides frequency range(s) that should be avoided
+ *
+ * @start_freq: start of frequency (KHz)
+ * @end_freq: end of frequency (KHz)
+ */
+struct cfg80211_avoid_frequency_range {
+ unsigned int start_freq;
+ unsigned int end_freq;
+};
+
+struct cfg80211_avoid_frequency_list {
+ unsigned int n_freq_ranges;
+ struct cfg80211_avoid_frequency_range *freq_range[0];
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -4340,6 +4358,18 @@ void cfg80211_ft_event(struct net_device *netdev,
struct cfg80211_ft_event_params *ft_event);
/**
+ * cfg80211_avoid_frequency_event - notify userspace about frequency range(s)
+ * @netdev: network device
+ * @freq_list: frequency range(s) information
+ * @gfp: allocation flags
+ *
+ * WLAN driver calls this function to notify userspace about frequency
+ * range(s) that should be avoided.
+ */
+void cfg80211_avoid_frequency_event(struct net_device *netdev,
+ struct cfg80211_avoid_frequency_list *freq_list, gfp_t gfp);
+
+/**
* cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
* @ies: the input IE buffer
* @len: the input length
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index fde2c02..457fd67 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -686,6 +686,13 @@
* other station that transmission must be blocked until the channel
* switch is complete.
*
+ * @NL80211_CMD_AVOID_FREQUENCIES_EVENT: Send range(s) of frequencies that
+ * should be avoided, from the WLAN driver to the user space. WLAN driver
+ * may send unsafe frequencies to avoid interference. User space should
+ * move SAP/P2P-GO out of those unsafe frequency ranges. User space may
+ * decide to continue operation on unsafe frequency but in such case,
+ * performance might get impact.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -853,6 +860,8 @@ enum nl80211_commands {
NL80211_CMD_CHANNEL_SWITCH,
+ NL80211_CMD_AVOID_FREQUENCIES_EVENT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1496,6 +1505,8 @@ enum nl80211_commands {
* @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
* As specified in the &enum nl80211_rxmgmt_flags.
*
+ * @NL80211_ATTR_AVOID_FREQUENCIES: Avoid frequencies container information
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1806,6 +1817,8 @@ enum nl80211_attrs {
NL80211_ATTR_RXMGMT_FLAGS,
+ NL80211_ATTR_AVOID_FREQUENCIES,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2255,6 +2268,24 @@ enum nl80211_frequency_attr {
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
/**
+ * enum nl80211_avoid_frequency_attr - avoid frequency attributes
+ * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_AVOID_FREQUENCY_ATTR_START_FREQ: Start of frequency (KHz) range
+ * @NL80211_AVOID_FREQUENCY_ATTR_END_FREQ: End of frequency (KHz) range
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_avoid_frequency_attr {
+ __NL80211_AVOID_FREQUENCY_ATTR_INVALID,
+ NL80211_AVOID_FREQUENCY_ATTR_START_FREQ,
+ NL80211_AVOID_FREQUENCY_ATTR_END_FREQ,
+
+ /* keep last */
+ __NL80211_AVOID_FREQUENCY_ATTR_AFTER_LAST,
+ NL80211_AVOID_FREQUENCY_ATTR_MAX =
+ __NL80211_AVOID_FREQUENCY_ATTR_AFTER_LAST - 1
+};
+
+/**
* enum nl80211_bitrate_attr - bitrate attributes
* @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved
* @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cbbef88..dc3443a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -354,6 +354,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
+ [NL80211_ATTR_AVOID_FREQUENCIES] = { .type = NLA_NESTED },
};
/* policy for the key attributes */
@@ -11234,6 +11235,73 @@ void cfg80211_ft_event(struct net_device *netdev,
}
EXPORT_SYMBOL(cfg80211_ft_event);
+void cfg80211_avoid_frequency_event(struct net_device *netdev,
+ struct cfg80211_avoid_frequency_list *freq_list, gfp_t gfp)
+{
+ struct wiphy *wiphy;
+ struct cfg80211_registered_device *rdev;
+ struct sk_buff *msg;
+ void *hdr;
+ struct nlattr *nl_ranges, *nl_range;
+ int err = -EINVAL;
+ unsigned int i;
+
+ if (!netdev || !netdev->ieee80211_ptr ||
+ !netdev->ieee80211_ptr->wiphy || !freq_list)
+ return;
+
+ wiphy = netdev->ieee80211_ptr->wiphy;
+ rdev = wiphy_to_dev(wiphy);
+
+ if (!rdev)
+ return;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_AVOID_FREQUENCIES_EVENT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+ goto nla_put_failure;
+
+ nl_ranges = nla_nest_start(msg, NL80211_ATTR_AVOID_FREQUENCIES);
+ if (!nl_ranges)
+ goto nla_put_failure;
+
+ for (i = 0; i < freq_list->n_freq_ranges; i++) {
+ nl_range = nla_nest_start(msg, i);
+ if (!nl_range)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_AVOID_FREQUENCY_ATTR_START_FREQ,
+ freq_list->freq_range[i]->start_freq) ||
+ nla_put_u32(msg, NL80211_AVOID_FREQUENCY_ATTR_END_FREQ,
+ freq_list->freq_range[i]->end_freq))
+ goto nla_put_failure;
+ nla_nest_end(msg, nl_range);
+ }
+ nla_nest_end(msg, nl_ranges);
+
+ err = genlmsg_end(msg, hdr);
+ if (err < 0)
+ goto nla_put_failure;
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_avoid_frequency_event);
+
void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
{
struct cfg80211_registered_device *rdev;
--
1.8.4
^ permalink raw reply related
* Re: [PATCH v2 7/8] ath10k: fix device initialization routine
From: Kalle Valo @ 2013-10-17 5:33 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQ=9cEwB7PY8VMGv1SmEPsH6WGmDEBgujmo9G=Cby82uyg@mail.gmail.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> On 16 October 2013 08:57, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior@tieto.com> writes:
>>
>>>> + /* disable pending irqs */
>>>> + ath10k_pci_core_write32(ar, PCIE_INTR_ENABLE_ADDRESS, 0);
>>>> + ath10k_pci_core_write32(ar, PCIE_INTR_CLR_ADDRESS, ~0);
>>>
>>> These use SOC_CORE_BASE_ADDRESS as the suffix, not the RTC_SOC_BASE_ADDRESS.
>>
>> But I am using SOC_CORE_BASE_ADDRESS, right?
>
> Ah, right. Sorry. My eyesight failed me :) Those function names seem a
> little confusing (_core_ for SOC_CORE and _soc_ for RTC_SOC)
Yeah, I agree. I didn't research what RTC_SOC stands for, I just assumed
it contains registers for controlling the whole SOC state. That's why I
used "_soc_" here. And CORE registers control just one part of SOC.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 5/5] net: rfkill: gpio: add ACPI support
From: Mika Westerberg @ 2013-10-17 7:44 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Heikki Krogerus, John W. Linville, Johannes Berg, Rhyland Klein,
linux-acpi, linux-wireless, netdev
In-Reply-To: <2878506.7lf24R85t6@vostro.rjw.lan>
On Wed, Oct 16, 2013 at 10:55:01PM +0200, Rafael J. Wysocki wrote:
> On Wednesday, October 16, 2013 01:53:43 PM Heikki Krogerus wrote:
> > Including ACPI ID for Broadcom GPS receiver BCM4752.
> >
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > ---
> > net/rfkill/rfkill-gpio.c | 31 ++++++++++++++++++++++++++++++-
> > 1 file changed, 30 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
> > index 2dd78c6..5620d3c 100644
> > --- a/net/rfkill/rfkill-gpio.c
> > +++ b/net/rfkill/rfkill-gpio.c
> > @@ -24,6 +24,8 @@
> > #include <linux/platform_device.h>
> > #include <linux/clk.h>
> > #include <linux/slab.h>
> > +#include <linux/acpi.h>
> > +#include <linux/acpi_gpio.h>
> >
> > #include <linux/rfkill-gpio.h>
> >
> > @@ -70,6 +72,23 @@ static const struct rfkill_ops rfkill_gpio_ops = {
> > .set_block = rfkill_gpio_set_power,
> > };
> >
> > +static int rfkill_gpio_acpi_probe(struct device *dev,
> > + struct rfkill_gpio_data *rfkill)
> > +{
> > + const struct acpi_device_id *id;
> > +
> > + id = acpi_match_device(dev->driver->acpi_match_table, dev);
> > + if (!id)
> > + return -ENODEV;
> > +
> > + rfkill->name = dev_name(dev);
> > + rfkill->type = (unsigned)id->driver_data;
> > + rfkill->reset_gpio = acpi_get_gpio_by_index(dev, 0, NULL);
> > + rfkill->shutdown_gpio = acpi_get_gpio_by_index(dev, 1, NULL);
> > +
> > + return 0;
> > +}
> > +
> > static int rfkill_gpio_probe(struct platform_device *pdev)
> > {
> > struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
> > @@ -82,7 +101,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
> > if (!rfkill)
> > return -ENOMEM;
> >
> > - if (pdata) {
> > + if (ACPI_HANDLE(&pdev->dev)) {
> > + ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
> > + if (ret)
> > + return ret;
> > + } else if (pdata) {
> > clk_name = pdata->power_clk_name;
> > rfkill->name = pdata->name;
> > rfkill->type = pdata->type;
> > @@ -170,12 +193,18 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static const struct acpi_device_id rfkill_acpi_match[] = {
> > + { "BCM4752", RFKILL_TYPE_GPS },
> > + { },
> > +};
> > +
> > static struct platform_driver rfkill_gpio_driver = {
> > .probe = rfkill_gpio_probe,
> > .remove = rfkill_gpio_remove,
> > .driver = {
> > .name = "rfkill_gpio",
> > .owner = THIS_MODULE,
> > + .acpi_match_table = ACPI_PTR(rfkill_acpi_match),
> > },
> > };
>
> Looks good to me.
>
> Has Mika seen this?
Yes, saw it now and looks good to me as well.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
for the whole series, for what it's worth.
^ permalink raw reply
* [PATCH 04/21] rt2x00: rt2800pci: use rt2800mmio prefix for RX control handler functions
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
The functions are used for devices with memory
mapped I/O and contain no PCI specific code at
all. Use rt2800mmio prefix instead of rt2800pci
in the function names to reflect that.
The patch contains no functional changes.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index b2e2b09..37ac888 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -630,8 +630,8 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* RX control handlers
*/
-static void rt2800pci_fill_rxdone(struct queue_entry *entry,
- struct rxdone_entry_desc *rxdesc)
+static void rt2800mmio_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
{
struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
@@ -1119,7 +1119,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.clear_beacon = rt2800_clear_beacon,
- .fill_rxdone = rt2800pci_fill_rxdone,
+ .fill_rxdone = rt2800mmio_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
.config_pairwise_key = rt2800_config_pairwise_key,
.config_filter = rt2800_config_filter,
--
1.7.10
^ permalink raw reply related
* [PATCH 00/21] rt2x00: separate rt2800 PCI and SoC driver
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
The rt2800pci driver supports both PCI and SoC device. To achieve
this, the code uses several ifdef statements which makes the code
quite ugly. The patch set introduces a shared module, and moves the
SoC driver into a separate module to get rid of the mess.
Gabor Juhos (21):
rt2x00: create a new module for rt2800 MMIO code
rt2x00: rt2800pci: use rt2800mmio prefix for TX descriptor functions
rt2x00: rt2800pci: move TX descriptor functions to the rt2800mmio module
rt2x00: rt2800pci: use rt2800mmio prefix for RX control handler functions
rt2x00: rt2800pci: move RX control handler functions to the rt2800mmio module
rt2x00: rt2800pci: use rt2800mmio prefix for interrupt functions
rt2x00: rt2800pci: move interrupt functions to the rt2800mmio module
rt2x00: rt2800pci: use rt2800mmio prefix for queue functions
rt2x00: rt2800pci: move queue functions to the rt2800mmio module
rt2x00: rt2800pci: use rt2800mmio prefix for initialization functions
rt2x00: rt2800pci: move initialization functions to the rt2800mmio module
rt2x00: rt2800pci: use separate ops for the SoC driver
rt2x00: rt2800pci: use separate read_eeprom callback for SoC devices
rt2x00: rt2800pci: use separate firmware callbacks for SoC devices
rt2x00: rt2800pci: use separate set_state callback for SoC devices
rt2x00: rt2800pci: rename rt2800pci_disable_radio function
rt2x00: rt2800pci: split rt2800pci_enable_radio function
rt2x00: rt2800pci: move rt2800mmio_enable_radio function to another module
rt2x00: rt2800pci: use separate hwcrypt_disabled callback for SoC devices
rt2x00: rt2800pci: move SoC specific code into a separate module
rt2x00: rt2800pci: use module_pci_driver macro
drivers/net/wireless/rt2x00/Kconfig | 27 +-
drivers/net/wireless/rt2x00/Makefile | 2 +
drivers/net/wireless/rt2x00/rt2800mmio.c | 873 +++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.h | 165 ++++++
drivers/net/wireless/rt2x00/rt2800pci.c | 951 +-----------------------------
drivers/net/wireless/rt2x00/rt2800pci.h | 97 ---
drivers/net/wireless/rt2x00/rt2800soc.c | 263 +++++++++
7 files changed, 1348 insertions(+), 1030 deletions(-)
create mode 100644 drivers/net/wireless/rt2x00/rt2800mmio.c
create mode 100644 drivers/net/wireless/rt2x00/rt2800mmio.h
create mode 100644 drivers/net/wireless/rt2x00/rt2800soc.c
--
1.7.10
^ permalink raw reply
* [PATCH 01/21] rt2x00: create a new module for rt2800 MMIO code
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
Create a new module for common code which can be used
for rt2800 device with memory mapped I/O. It is an empty
module for now, but it will be populated by subsequent
patches.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/Kconfig | 4 +++
drivers/net/wireless/rt2x00/Makefile | 1 +
drivers/net/wireless/rt2x00/rt2800mmio.c | 39 ++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.h | 34 ++++++++++++++++++++++++++
4 files changed, 78 insertions(+)
create mode 100644 drivers/net/wireless/rt2x00/rt2800mmio.c
create mode 100644 drivers/net/wireless/rt2x00/rt2800mmio.h
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index a18b005..2232b11 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -60,6 +60,7 @@ config RT2800PCI
tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
depends on PCI || SOC_RT288X || SOC_RT305X
select RT2800_LIB
+ select RT2800_LIB_MMIO
select RT2X00_LIB_MMIO
select RT2X00_LIB_PCI if PCI
select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
@@ -202,6 +203,9 @@ endif
config RT2800_LIB
tristate
+config RT2800_LIB_MMIO
+ tristate
+
config RT2X00_LIB_MMIO
tristate
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index f069d8b..d11e356 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o
obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
obj-$(CONFIG_RT2800_LIB) += rt2800lib.o
+obj-$(CONFIG_RT2800_LIB_MMIO) += rt2800mmio.o
obj-$(CONFIG_RT2400PCI) += rt2400pci.o
obj-$(CONFIG_RT2500PCI) += rt2500pci.o
obj-$(CONFIG_RT61PCI) += rt61pci.o
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c
new file mode 100644
index 0000000..a2b9848
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+ * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+ * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+ * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+ * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+ * <http://rt2x00.serialmonkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Module: rt2800mmio
+ * Abstract: rt2800 MMIO device routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2800 MMIO library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h
new file mode 100644
index 0000000..32f9dcd
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+ * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+ * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+ * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+ * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+ * <http://rt2x00.serialmonkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Module: rt2800mmio
+ * Abstract: forward declarations for the rt2800mmio module.
+ */
+
+#ifndef RT2800MMIO_H
+#define RT2800MMIO_H
+
+#endif /* RT2800MMIO_H */
--
1.7.10
^ permalink raw reply related
* [PATCH 03/21] rt2x00: rt2800pci: move TX descriptor functions to the rt2800mmio module
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
Move the functions into a separate module, in order
to make those usable from other modules. Also move
the TX descriptor related defines from rt2800pci.h
into rt2800mmio.h.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/Kconfig | 1 +
drivers/net/wireless/rt2x00/rt2800mmio.c | 68 ++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.h | 47 +++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800pci.c | 62 +--------------------------
drivers/net/wireless/rt2x00/rt2800pci.h | 37 ----------------
5 files changed, 117 insertions(+), 98 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 2232b11..535ad3a 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -205,6 +205,7 @@ config RT2800_LIB
config RT2800_LIB_MMIO
tristate
+ select RT2X00_LIB_MMIO
config RT2X00_LIB_MMIO
tristate
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c
index a2b9848..d2ebb68 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -30,6 +30,74 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/export.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2800mmio.h"
+
+/*
+ * TX descriptor initialization
+ */
+__le32 *rt2800mmio_get_txwi(struct queue_entry *entry)
+{
+ return (__le32 *) entry->skb->data;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi);
+
+void rt2800mmio_write_tx_desc(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
+{
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+ __le32 *txd = entry_priv->desc;
+ u32 word;
+ const unsigned int txwi_size = entry->queue->winfo_size;
+
+ /*
+ * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1
+ * must contains a TXWI structure + 802.11 header + padding + 802.11
+ * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and
+ * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11
+ * data. It means that LAST_SEC0 is always 0.
+ */
+
+ /*
+ * Initialize TX descriptor
+ */
+ word = 0;
+ rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
+ rt2x00_desc_write(txd, 0, word);
+
+ word = 0;
+ rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
+ rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
+ !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W1_BURST,
+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size);
+ rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
+ rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
+ rt2x00_desc_write(txd, 1, word);
+
+ word = 0;
+ rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
+ skbdesc->skb_dma + txwi_size);
+ rt2x00_desc_write(txd, 2, word);
+
+ word = 0;
+ rt2x00_set_field32(&word, TXD_W3_WIV,
+ !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
+ rt2x00_desc_write(txd, 3, word);
+
+ /*
+ * Register descriptor details in skb frame descriptor.
+ */
+ skbdesc->desc = txd;
+ skbdesc->desc_len = TXD_DESC_SIZE;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc);
#include "rt2x00.h"
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h
index 32f9dcd..0266640 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
@@ -31,4 +31,51 @@
#ifndef RT2800MMIO_H
#define RT2800MMIO_H
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE (4 * sizeof(__le32))
+
+/*
+ * TX descriptor format for TX, PRIO and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_SD_PTR0 FIELD32(0xffffffff)
+
+/*
+ * Word1
+ */
+#define TXD_W1_SD_LEN1 FIELD32(0x00003fff)
+#define TXD_W1_LAST_SEC1 FIELD32(0x00004000)
+#define TXD_W1_BURST FIELD32(0x00008000)
+#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000)
+#define TXD_W1_LAST_SEC0 FIELD32(0x40000000)
+#define TXD_W1_DMA_DONE FIELD32(0x80000000)
+
+/*
+ * Word2
+ */
+#define TXD_W2_SD_PTR1 FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
+ * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
+ * 0:MGMT, 1:HCCA 2:EDCA
+ */
+#define TXD_W3_WIV FIELD32(0x01000000)
+#define TXD_W3_QSEL FIELD32(0x06000000)
+#define TXD_W3_TCO FIELD32(0x20000000)
+#define TXD_W3_UCO FIELD32(0x40000000)
+#define TXD_W3_ICO FIELD32(0x80000000)
+
+
+/* TX descriptor initialization */
+__le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
+void rt2800mmio_write_tx_desc(struct queue_entry *entry,
+ struct txentry_desc *txdesc);
+
#endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index ddc6a42..b2e2b09 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -45,6 +45,7 @@
#include "rt2x00pci.h"
#include "rt2x00soc.h"
#include "rt2800lib.h"
+#include "rt2800mmio.h"
#include "rt2800.h"
#include "rt2800pci.h"
@@ -627,67 +628,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
/*
- * TX descriptor initialization
- */
-static __le32 *rt2800mmio_get_txwi(struct queue_entry *entry)
-{
- return (__le32 *) entry->skb->data;
-}
-
-static void rt2800mmio_write_tx_desc(struct queue_entry *entry,
- struct txentry_desc *txdesc)
-{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
- __le32 *txd = entry_priv->desc;
- u32 word;
- const unsigned int txwi_size = entry->queue->winfo_size;
-
- /*
- * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1
- * must contains a TXWI structure + 802.11 header + padding + 802.11
- * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and
- * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11
- * data. It means that LAST_SEC0 is always 0.
- */
-
- /*
- * Initialize TX descriptor
- */
- word = 0;
- rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
- rt2x00_desc_write(txd, 0, word);
-
- word = 0;
- rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
- rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
- !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W1_BURST,
- test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size);
- rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
- rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
- rt2x00_desc_write(txd, 1, word);
-
- word = 0;
- rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
- skbdesc->skb_dma + txwi_size);
- rt2x00_desc_write(txd, 2, word);
-
- word = 0;
- rt2x00_set_field32(&word, TXD_W3_WIV,
- !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
- rt2x00_desc_write(txd, 3, word);
-
- /*
- * Register descriptor details in skb frame descriptor.
- */
- skbdesc->desc = txd;
- skbdesc->desc_len = TXD_DESC_SIZE;
-}
-
-/*
* RX control handlers
*/
static void rt2800pci_fill_rxdone(struct queue_entry *entry,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index ab22a08..ecd154e 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -53,46 +53,9 @@
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE (4 * sizeof(__le32))
#define RXD_DESC_SIZE (4 * sizeof(__le32))
/*
- * TX descriptor format for TX, PRIO and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_SD_PTR0 FIELD32(0xffffffff)
-
-/*
- * Word1
- */
-#define TXD_W1_SD_LEN1 FIELD32(0x00003fff)
-#define TXD_W1_LAST_SEC1 FIELD32(0x00004000)
-#define TXD_W1_BURST FIELD32(0x00008000)
-#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000)
-#define TXD_W1_LAST_SEC0 FIELD32(0x40000000)
-#define TXD_W1_DMA_DONE FIELD32(0x80000000)
-
-/*
- * Word2
- */
-#define TXD_W2_SD_PTR1 FIELD32(0xffffffff)
-
-/*
- * Word3
- * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
- * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
- * 0:MGMT, 1:HCCA 2:EDCA
- */
-#define TXD_W3_WIV FIELD32(0x01000000)
-#define TXD_W3_QSEL FIELD32(0x06000000)
-#define TXD_W3_TCO FIELD32(0x20000000)
-#define TXD_W3_UCO FIELD32(0x40000000)
-#define TXD_W3_ICO FIELD32(0x80000000)
-
-/*
* RX descriptor format for RX Ring.
*/
--
1.7.10
^ permalink raw reply related
* [PATCH 02/21] rt2x00: rt2800pci: use rt2800mmio prefix for TX descriptor functions
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
The functions are used for devices with memory
mapped I/O and contain no PCI specific code at
all. Use rt2800mmio prefix instead of rt2800pci
in the function names to reflect that.
The patch contains no functional changes.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index f8f2abb..ddc6a42 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -629,13 +629,13 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static __le32 *rt2800pci_get_txwi(struct queue_entry *entry)
+static __le32 *rt2800mmio_get_txwi(struct queue_entry *entry)
{
return (__le32 *) entry->skb->data;
}
-static void rt2800pci_write_tx_desc(struct queue_entry *entry,
- struct txentry_desc *txdesc)
+static void rt2800mmio_write_tx_desc(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
@@ -826,7 +826,7 @@ static bool rt2800pci_txdone_release_entries(struct queue_entry *entry,
{
if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
rt2800_txdone_entry(entry, entry->status,
- rt2800pci_get_txwi(entry));
+ rt2800mmio_get_txwi(entry));
return false;
}
@@ -1146,7 +1146,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800pci_init_registers,
- .drv_get_txwi = rt2800pci_get_txwi,
+ .drv_get_txwi = rt2800mmio_get_txwi,
};
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
@@ -1175,7 +1175,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.kick_queue = rt2800pci_kick_queue,
.stop_queue = rt2800pci_stop_queue,
.flush_queue = rt2x00mmio_flush_queue,
- .write_tx_desc = rt2800pci_write_tx_desc,
+ .write_tx_desc = rt2800mmio_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.clear_beacon = rt2800_clear_beacon,
--
1.7.10
^ permalink raw reply related
* [PATCH 06/21] rt2x00: rt2800pci: use rt2800mmio prefix for interrupt functions
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
The functions are used for devices with memory
mapped I/O and contain no PCI specific code at
all. Use rt2800mmio prefix instead of rt2800pci
in the function names to reflect that.
The patch contains no functional changes.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 73 ++++++++++++++++---------------
1 file changed, 37 insertions(+), 36 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 2cbaaac..a829ce5 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -448,8 +448,8 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
-static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
- enum dev_state state)
+static void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
+ enum dev_state state)
{
u32 reg;
unsigned long flags;
@@ -607,7 +607,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_OFF:
- rt2800pci_toggle_irq(rt2x00dev, state);
+ rt2800mmio_toggle_irq(rt2x00dev, state);
break;
case STATE_DEEP_SLEEP:
case STATE_SLEEP:
@@ -630,7 +630,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* Interrupt functions.
*/
-static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
+static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev)
{
struct ieee80211_conf conf = { .flags = 0 };
struct rt2x00lib_conf libconf = { .conf = &conf };
@@ -638,7 +638,7 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}
-static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status)
+static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
{
__le32 *txwi;
u32 word;
@@ -653,7 +653,7 @@ static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status)
return (tx_wcid == wcid);
}
-static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data)
+static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
{
u32 status = *(u32 *)data;
@@ -670,7 +670,7 @@ static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data)
* To mitigate this effect, associate the tx status to the first frame
* in the tx queue with a matching wcid.
*/
- if (rt2800pci_txdone_entry_check(entry, status) &&
+ if (rt2800mmio_txdone_entry_check(entry, status) &&
!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
/*
* Got a matching frame, associate the tx status with
@@ -685,7 +685,7 @@ static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data)
return false;
}
-static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data)
+static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
{
u32 status = *(u32 *)data;
@@ -706,8 +706,8 @@ static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data)
/* Check the next frame */
return false;
}
-static bool rt2800pci_txdone_release_entries(struct queue_entry *entry,
- void *data)
+static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
+ void *data)
{
if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
rt2800_txdone_entry(entry, entry->status,
@@ -719,7 +719,7 @@ static bool rt2800pci_txdone_release_entries(struct queue_entry *entry,
return true;
}
-static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
+static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
u32 status;
@@ -765,14 +765,14 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
*/
if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
Q_INDEX, &status,
- rt2800pci_txdone_find_entry)) {
+ rt2800mmio_txdone_find_entry)) {
/*
* We cannot match the tx status to any frame, so just
* use the first one.
*/
if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
Q_INDEX, &status,
- rt2800pci_txdone_match_first)) {
+ rt2800mmio_txdone_match_first)) {
rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
qid);
break;
@@ -784,7 +784,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
*/
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
Q_INDEX, NULL,
- rt2800pci_txdone_release_entries);
+ rt2800mmio_txdone_release_entries);
if (--max_tx_done == 0)
break;
@@ -793,8 +793,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
return !max_tx_done;
}
-static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
+static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
{
u32 reg;
@@ -809,10 +809,10 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
-static void rt2800pci_txstatus_tasklet(unsigned long data)
+static void rt2800mmio_txstatus_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2800pci_txdone(rt2x00dev))
+ if (rt2800mmio_txdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->txstatus_tasklet);
/*
@@ -822,15 +822,15 @@ static void rt2800pci_txstatus_tasklet(unsigned long data)
*/
}
-static void rt2800pci_pretbtt_tasklet(unsigned long data)
+static void rt2800mmio_pretbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_pretbtt(rt2x00dev);
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
}
-static void rt2800pci_tbtt_tasklet(unsigned long data)
+static void rt2800mmio_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -861,27 +861,28 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
}
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
}
-static void rt2800pci_rxdone_tasklet(unsigned long data)
+static void rt2800mmio_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
}
-static void rt2800pci_autowake_tasklet(unsigned long data)
+static void rt2800mmio_autowake_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2800pci_wakeup(rt2x00dev);
+ rt2800mmio_wakeup(rt2x00dev);
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
+ rt2800mmio_enable_interrupt(rt2x00dev,
+ INT_MASK_CSR_AUTO_WAKEUP);
}
-static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
{
u32 status;
int i;
@@ -920,7 +921,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
tasklet_schedule(&rt2x00dev->txstatus_tasklet);
}
-static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg, mask;
@@ -943,7 +944,7 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
mask = ~reg;
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
- rt2800pci_txstatus_interrupt(rt2x00dev);
+ rt2800mmio_txstatus_interrupt(rt2x00dev);
/*
* Never disable the TX_FIFO_STATUS interrupt.
*/
@@ -1035,12 +1036,12 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
};
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
- .irq_handler = rt2800pci_interrupt,
- .txstatus_tasklet = rt2800pci_txstatus_tasklet,
- .pretbtt_tasklet = rt2800pci_pretbtt_tasklet,
- .tbtt_tasklet = rt2800pci_tbtt_tasklet,
- .rxdone_tasklet = rt2800pci_rxdone_tasklet,
- .autowake_tasklet = rt2800pci_autowake_tasklet,
+ .irq_handler = rt2800mmio_interrupt,
+ .txstatus_tasklet = rt2800mmio_txstatus_tasklet,
+ .pretbtt_tasklet = rt2800mmio_pretbtt_tasklet,
+ .tbtt_tasklet = rt2800mmio_tbtt_tasklet,
+ .rxdone_tasklet = rt2800mmio_rxdone_tasklet,
+ .autowake_tasklet = rt2800mmio_autowake_tasklet,
.probe_hw = rt2800_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
--
1.7.10
^ permalink raw reply related
* [PATCH 05/21] rt2x00: rt2800pci: move RX control handler functions to the rt2800mmio module
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
Move the functions into a separate module, in order
to make those usable from other modules. Also move
the RX descriptor related defines from rt2800pci.h
into rt2800mmio.h
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/Kconfig | 1 +
drivers/net/wireless/rt2x00/rt2800mmio.c | 57 +++++++++++++++++++++++++++++-
drivers/net/wireless/rt2x00/rt2800mmio.h | 51 ++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800pci.c | 55 ----------------------------
drivers/net/wireless/rt2x00/rt2800pci.h | 51 --------------------------
5 files changed, 108 insertions(+), 107 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 535ad3a..e863249 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -206,6 +206,7 @@ config RT2800_LIB
config RT2800_LIB_MMIO
tristate
select RT2X00_LIB_MMIO
+ select RT2800_LIB
config RT2X00_LIB_MMIO
tristate
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c
index d2ebb68..32b8e50 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -34,6 +34,7 @@
#include "rt2x00.h"
#include "rt2x00mmio.h"
+#include "rt2800lib.h"
#include "rt2800mmio.h"
/*
@@ -99,7 +100,61 @@ void rt2800mmio_write_tx_desc(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc);
-#include "rt2x00.h"
+/*
+ * RX control handlers
+ */
+void rt2800mmio_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
+{
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+ __le32 *rxd = entry_priv->desc;
+ u32 word;
+
+ rt2x00_desc_read(rxd, 3, &word);
+
+ if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+ /*
+ * Unfortunately we don't know the cipher type used during
+ * decryption. This prevents us from correct providing
+ * correct statistics through debugfs.
+ */
+ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
+
+ if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
+ /*
+ * Hardware has stripped IV/EIV data from 802.11 frame during
+ * decryption. Unfortunately the descriptor doesn't contain
+ * any fields with the EIV/IV data either, so they can't
+ * be restored by rt2x00lib.
+ */
+ rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+ /*
+ * The hardware has already checked the Michael Mic and has
+ * stripped it from the frame. Signal this to mac80211.
+ */
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+ if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+ rxdesc->flags |= RX_FLAG_DECRYPTED;
+ else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+ rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+ }
+
+ if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
+ rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+ if (rt2x00_get_field32(word, RXD_W3_L2PAD))
+ rxdesc->dev_flags |= RXDONE_L2PAD;
+
+ /*
+ * Process the RXWI structure that is at the start of the buffer.
+ */
+ rt2800_process_rxwi(entry, rxdesc);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone);
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h
index 0266640..71e3d22 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
@@ -35,6 +35,7 @@
* DMA descriptor defines.
*/
#define TXD_DESC_SIZE (4 * sizeof(__le32))
+#define RXD_DESC_SIZE (4 * sizeof(__le32))
/*
* TX descriptor format for TX, PRIO and Beacon Ring.
@@ -72,10 +73,60 @@
#define TXD_W3_UCO FIELD32(0x40000000)
#define TXD_W3_ICO FIELD32(0x80000000)
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ */
+#define RXD_W0_SDP0 FIELD32(0xffffffff)
+
+/*
+ * Word1
+ */
+#define RXD_W1_SDL1 FIELD32(0x00003fff)
+#define RXD_W1_SDL0 FIELD32(0x3fff0000)
+#define RXD_W1_LS0 FIELD32(0x40000000)
+#define RXD_W1_DMA_DONE FIELD32(0x80000000)
+
+/*
+ * Word2
+ */
+#define RXD_W2_SDP1 FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * AMSDU: RX with 802.3 header, not 802.11 header.
+ * DECRYPTED: This frame is being decrypted.
+ */
+#define RXD_W3_BA FIELD32(0x00000001)
+#define RXD_W3_DATA FIELD32(0x00000002)
+#define RXD_W3_NULLDATA FIELD32(0x00000004)
+#define RXD_W3_FRAG FIELD32(0x00000008)
+#define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010)
+#define RXD_W3_MULTICAST FIELD32(0x00000020)
+#define RXD_W3_BROADCAST FIELD32(0x00000040)
+#define RXD_W3_MY_BSS FIELD32(0x00000080)
+#define RXD_W3_CRC_ERROR FIELD32(0x00000100)
+#define RXD_W3_CIPHER_ERROR FIELD32(0x00000600)
+#define RXD_W3_AMSDU FIELD32(0x00000800)
+#define RXD_W3_HTC FIELD32(0x00001000)
+#define RXD_W3_RSSI FIELD32(0x00002000)
+#define RXD_W3_L2PAD FIELD32(0x00004000)
+#define RXD_W3_AMPDU FIELD32(0x00008000)
+#define RXD_W3_DECRYPTED FIELD32(0x00010000)
+#define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000)
+#define RXD_W3_PLCP_RSSI FIELD32(0x00040000)
/* TX descriptor initialization */
__le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
void rt2800mmio_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc);
+/* RX control handlers */
+void rt2800mmio_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc);
+
+
#endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 37ac888..2cbaaac 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -628,61 +628,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
/*
- * RX control handlers
- */
-static void rt2800mmio_fill_rxdone(struct queue_entry *entry,
- struct rxdone_entry_desc *rxdesc)
-{
- struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
- __le32 *rxd = entry_priv->desc;
- u32 word;
-
- rt2x00_desc_read(rxd, 3, &word);
-
- if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
- rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
- /*
- * Unfortunately we don't know the cipher type used during
- * decryption. This prevents us from correct providing
- * correct statistics through debugfs.
- */
- rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
-
- if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
- /*
- * Hardware has stripped IV/EIV data from 802.11 frame during
- * decryption. Unfortunately the descriptor doesn't contain
- * any fields with the EIV/IV data either, so they can't
- * be restored by rt2x00lib.
- */
- rxdesc->flags |= RX_FLAG_IV_STRIPPED;
-
- /*
- * The hardware has already checked the Michael Mic and has
- * stripped it from the frame. Signal this to mac80211.
- */
- rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-
- if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
- rxdesc->flags |= RX_FLAG_DECRYPTED;
- else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
- rxdesc->flags |= RX_FLAG_MMIC_ERROR;
- }
-
- if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
- rxdesc->dev_flags |= RXDONE_MY_BSS;
-
- if (rt2x00_get_field32(word, RXD_W3_L2PAD))
- rxdesc->dev_flags |= RXDONE_L2PAD;
-
- /*
- * Process the RXWI structure that is at the start of the buffer.
- */
- rt2800_process_rxwi(entry, rxdesc);
-}
-
-/*
* Interrupt functions.
*/
static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index ecd154e..0e55159 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -50,55 +50,4 @@
#define FIRMWARE_RT3290 "rt3290.bin"
#define FIRMWARE_IMAGE_BASE 0x2000
-/*
- * DMA descriptor defines.
- */
-#define RXD_DESC_SIZE (4 * sizeof(__le32))
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- */
-#define RXD_W0_SDP0 FIELD32(0xffffffff)
-
-/*
- * Word1
- */
-#define RXD_W1_SDL1 FIELD32(0x00003fff)
-#define RXD_W1_SDL0 FIELD32(0x3fff0000)
-#define RXD_W1_LS0 FIELD32(0x40000000)
-#define RXD_W1_DMA_DONE FIELD32(0x80000000)
-
-/*
- * Word2
- */
-#define RXD_W2_SDP1 FIELD32(0xffffffff)
-
-/*
- * Word3
- * AMSDU: RX with 802.3 header, not 802.11 header.
- * DECRYPTED: This frame is being decrypted.
- */
-#define RXD_W3_BA FIELD32(0x00000001)
-#define RXD_W3_DATA FIELD32(0x00000002)
-#define RXD_W3_NULLDATA FIELD32(0x00000004)
-#define RXD_W3_FRAG FIELD32(0x00000008)
-#define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010)
-#define RXD_W3_MULTICAST FIELD32(0x00000020)
-#define RXD_W3_BROADCAST FIELD32(0x00000040)
-#define RXD_W3_MY_BSS FIELD32(0x00000080)
-#define RXD_W3_CRC_ERROR FIELD32(0x00000100)
-#define RXD_W3_CIPHER_ERROR FIELD32(0x00000600)
-#define RXD_W3_AMSDU FIELD32(0x00000800)
-#define RXD_W3_HTC FIELD32(0x00001000)
-#define RXD_W3_RSSI FIELD32(0x00002000)
-#define RXD_W3_L2PAD FIELD32(0x00004000)
-#define RXD_W3_AMPDU FIELD32(0x00008000)
-#define RXD_W3_DECRYPTED FIELD32(0x00010000)
-#define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000)
-#define RXD_W3_PLCP_RSSI FIELD32(0x00040000)
-
#endif /* RT2800PCI_H */
--
1.7.10
^ permalink raw reply related
* [PATCH 08/21] rt2x00: rt2800pci: use rt2800mmio prefix for queue functions
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
The functions are used for devices with memory
mapped I/O and contain no PCI specific code at
all. Use rt2800mmio prefix instead of rt2800pci
in the function names to reflect that.
The patch contains no functional changes.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 12454b0..118f2d5 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -204,7 +204,7 @@ static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
/*
* Queue handlers.
*/
-static void rt2800pci_start_queue(struct data_queue *queue)
+static void rt2800mmio_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
@@ -231,7 +231,7 @@ static void rt2800pci_start_queue(struct data_queue *queue)
}
}
-static void rt2800pci_kick_queue(struct data_queue *queue)
+static void rt2800mmio_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry *entry;
@@ -255,7 +255,7 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
}
}
-static void rt2800pci_stop_queue(struct data_queue *queue)
+static void rt2800mmio_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
@@ -669,9 +669,9 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.link_tuner = rt2800_link_tuner,
.gain_calibration = rt2800_gain_calibration,
.vco_calibration = rt2800_vco_calibration,
- .start_queue = rt2800pci_start_queue,
- .kick_queue = rt2800pci_kick_queue,
- .stop_queue = rt2800pci_stop_queue,
+ .start_queue = rt2800mmio_start_queue,
+ .kick_queue = rt2800mmio_kick_queue,
+ .stop_queue = rt2800mmio_stop_queue,
.flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2800mmio_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
@@ -689,7 +689,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.sta_remove = rt2800_sta_remove,
};
-static void rt2800pci_queue_init(struct data_queue *queue)
+static void rt2800mmio_queue_init(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short txwi_size, rxwi_size;
@@ -739,7 +739,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.tx_queues = NUM_TX_QUEUES,
- .queue_init = rt2800pci_queue_init,
+ .queue_init = rt2800mmio_queue_init,
.lib = &rt2800pci_rt2x00_ops,
.drv = &rt2800pci_rt2800_ops,
.hw = &rt2800pci_mac80211_ops,
--
1.7.10
^ permalink raw reply related
* [PATCH 07/21] rt2x00: rt2800pci: move interrupt functions to the rt2800mmio module
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
Move the functions into a separate module, in order
to make those usable from other modules.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800mmio.c | 396 ++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.h | 9 +
drivers/net/wireless/rt2x00/rt2800pci.c | 388 -----------------------------
3 files changed, 405 insertions(+), 388 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c
index 32b8e50..bfae4f0 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -34,6 +34,7 @@
#include "rt2x00.h"
#include "rt2x00mmio.h"
+#include "rt2800.h"
#include "rt2800lib.h"
#include "rt2800mmio.h"
@@ -156,6 +157,401 @@ void rt2800mmio_fill_rxdone(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone);
+/*
+ * Interrupt functions.
+ */
+static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev)
+{
+ struct ieee80211_conf conf = { .flags = 0 };
+ struct rt2x00lib_conf libconf = { .conf = &conf };
+
+ rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+}
+
+static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
+{
+ __le32 *txwi;
+ u32 word;
+ int wcid, tx_wcid;
+
+ wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
+
+ txwi = rt2800_drv_get_txwi(entry);
+ rt2x00_desc_read(txwi, 1, &word);
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+
+ return (tx_wcid == wcid);
+}
+
+static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
+{
+ u32 status = *(u32 *)data;
+
+ /*
+ * rt2800pci hardware might reorder frames when exchanging traffic
+ * with multiple BA enabled STAs.
+ *
+ * For example, a tx queue
+ * [ STA1 | STA2 | STA1 | STA2 ]
+ * can result in tx status reports
+ * [ STA1 | STA1 | STA2 | STA2 ]
+ * when the hw decides to aggregate the frames for STA1 into one AMPDU.
+ *
+ * To mitigate this effect, associate the tx status to the first frame
+ * in the tx queue with a matching wcid.
+ */
+ if (rt2800mmio_txdone_entry_check(entry, status) &&
+ !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+ /*
+ * Got a matching frame, associate the tx status with
+ * the frame
+ */
+ entry->status = status;
+ set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+ return true;
+ }
+
+ /* Check the next frame */
+ return false;
+}
+
+static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
+{
+ u32 status = *(u32 *)data;
+
+ /*
+ * Find the first frame without tx status and assign this status to it
+ * regardless if it matches or not.
+ */
+ if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+ /*
+ * Got a matching frame, associate the tx status with
+ * the frame
+ */
+ entry->status = status;
+ set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+ return true;
+ }
+
+ /* Check the next frame */
+ return false;
+}
+static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
+ void *data)
+{
+ if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+ rt2800_txdone_entry(entry, entry->status,
+ rt2800mmio_get_txwi(entry));
+ return false;
+ }
+
+ /* No more frames to release */
+ return true;
+}
+
+static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ u32 status;
+ u8 qid;
+ int max_tx_done = 16;
+
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
+ qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
+ if (unlikely(qid >= QID_RX)) {
+ /*
+ * Unknown queue, this shouldn't happen. Just drop
+ * this tx status.
+ */
+ rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
+ qid);
+ break;
+ }
+
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+ if (unlikely(queue == NULL)) {
+ /*
+ * The queue is NULL, this shouldn't happen. Stop
+ * processing here and drop the tx status
+ */
+ rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
+ qid);
+ break;
+ }
+
+ if (unlikely(rt2x00queue_empty(queue))) {
+ /*
+ * The queue is empty. Stop processing here
+ * and drop the tx status.
+ */
+ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ qid);
+ break;
+ }
+
+ /*
+ * Let's associate this tx status with the first
+ * matching frame.
+ */
+ if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+ Q_INDEX, &status,
+ rt2800mmio_txdone_find_entry)) {
+ /*
+ * We cannot match the tx status to any frame, so just
+ * use the first one.
+ */
+ if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+ Q_INDEX, &status,
+ rt2800mmio_txdone_match_first)) {
+ rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
+ qid);
+ break;
+ }
+ }
+
+ /*
+ * Release all frames with a valid tx status.
+ */
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+ Q_INDEX, NULL,
+ rt2800mmio_txdone_release_entries);
+
+ if (--max_tx_done == 0)
+ break;
+ }
+
+ return !max_tx_done;
+}
+
+static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
+{
+ u32 reg;
+
+ /*
+ * Enable a single interrupt. The interrupt mask register
+ * access needs locking.
+ */
+ spin_lock_irq(&rt2x00dev->irqmask_lock);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®);
+ rt2x00_set_field32(®, irq_field, 1);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+void rt2800mmio_txstatus_tasklet(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ if (rt2800mmio_txdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+
+ /*
+ * No need to enable the tx status interrupt here as we always
+ * leave it enabled to minimize the possibility of a tx status
+ * register overflow. See comment in interrupt handler.
+ */
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
+
+void rt2800mmio_pretbtt_tasklet(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ rt2x00lib_pretbtt(rt2x00dev);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet);
+
+void rt2800mmio_tbtt_tasklet(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u32 reg;
+
+ rt2x00lib_beacondone(rt2x00dev);
+
+ if (rt2x00dev->intf_ap_count) {
+ /*
+ * The rt2800pci hardware tbtt timer is off by 1us per tbtt
+ * causing beacon skew and as a result causing problems with
+ * some powersaving clients over time. Shorten the beacon
+ * interval every 64 beacons by 64us to mitigate this effect.
+ */
+ if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®);
+ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL,
+ (rt2x00dev->beacon_int * 16) - 1);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®);
+ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL,
+ (rt2x00dev->beacon_int * 16));
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ }
+ drv_data->tbtt_tick++;
+ drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
+ }
+
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet);
+
+void rt2800mmio_rxdone_tasklet(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ if (rt2x00mmio_rxdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet);
+
+void rt2800mmio_autowake_tasklet(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ rt2800mmio_wakeup(rt2x00dev);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800mmio_enable_interrupt(rt2x00dev,
+ INT_MASK_CSR_AUTO_WAKEUP);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+
+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+{
+ u32 status;
+ int i;
+
+ /*
+ * The TX_FIFO_STATUS interrupt needs special care. We should
+ * read TX_STA_FIFO but we should do it immediately as otherwise
+ * the register can overflow and we would lose status reports.
+ *
+ * Hence, read the TX_STA_FIFO register and copy all tx status
+ * reports into a kernel FIFO which is handled in the txstatus
+ * tasklet. We use a tasklet to process the tx status reports
+ * because we can schedule the tasklet multiple times (when the
+ * interrupt fires again during tx status processing).
+ *
+ * Furthermore we don't disable the TX_FIFO_STATUS
+ * interrupt here but leave it enabled so that the TX_STA_FIFO
+ * can also be read while the tx status tasklet gets executed.
+ *
+ * Since we have only one producer and one consumer we don't
+ * need to lock the kfifo.
+ */
+ for (i = 0; i < rt2x00dev->tx->limit; i++) {
+ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+
+ if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+ break;
+
+ if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
+ rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
+ break;
+ }
+ }
+
+ /* Schedule the tasklet for processing the tx status. */
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+}
+
+irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
+{
+ struct rt2x00_dev *rt2x00dev = dev_instance;
+ u32 reg, mask;
+
+ /* Read status and ACK all interrupts */
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+ if (!reg)
+ return IRQ_NONE;
+
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return IRQ_HANDLED;
+
+ /*
+ * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+ * for interrupts and interrupt masks we can just use the value of
+ * INT_SOURCE_CSR to create the interrupt mask.
+ */
+ mask = ~reg;
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+ rt2800mmio_txstatus_interrupt(rt2x00dev);
+ /*
+ * Never disable the TX_FIFO_STATUS interrupt.
+ */
+ rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ }
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+ tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+ tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
+ tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+ /*
+ * Disable all interrupts for which a tasklet was scheduled right now,
+ * the tasklet will reenable the appropriate interrupts.
+ */
+ spin_lock(&rt2x00dev->irqmask_lock);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®);
+ reg &= mask;
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ spin_unlock(&rt2x00dev->irqmask_lock);
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_interrupt);
+
+void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
+ enum dev_state state)
+{
+ u32 reg;
+ unsigned long flags;
+
+ /*
+ * When interrupts are being enabled, the interrupt registers
+ * should clear the register to assure a clean state.
+ */
+ if (state == STATE_RADIO_IRQ_ON) {
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ }
+
+ spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+ reg = 0;
+ if (state == STATE_RADIO_IRQ_ON) {
+ rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1);
+ rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1);
+ rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1);
+ rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1);
+ }
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+ if (state == STATE_RADIO_IRQ_OFF) {
+ /*
+ * Wait for possibly running tasklets to finish.
+ */
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+ }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq);
+
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("rt2800 MMIO library");
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h
index 71e3d22..30e66ab 100644
--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
@@ -128,5 +128,14 @@ void rt2800mmio_write_tx_desc(struct queue_entry *entry,
void rt2800mmio_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc);
+/* Interrupt functions */
+void rt2800mmio_txstatus_tasklet(unsigned long data);
+void rt2800mmio_pretbtt_tasklet(unsigned long data);
+void rt2800mmio_tbtt_tasklet(unsigned long data);
+void rt2800mmio_rxdone_tasklet(unsigned long data);
+void rt2800mmio_autowake_tasklet(unsigned long data);
+irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance);
+void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
+ enum dev_state state);
#endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index a829ce5..12454b0 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -448,45 +448,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
-static void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
- enum dev_state state)
-{
- u32 reg;
- unsigned long flags;
-
- /*
- * When interrupts are being enabled, the interrupt registers
- * should clear the register to assure a clean state.
- */
- if (state == STATE_RADIO_IRQ_ON) {
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
- rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
- }
-
- spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- reg = 0;
- if (state == STATE_RADIO_IRQ_ON) {
- rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1);
- rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1);
- rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1);
- rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1);
- rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1);
- }
- rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
-
- if (state == STATE_RADIO_IRQ_OFF) {
- /*
- * Wait for possibly running tasklets to finish.
- */
- tasklet_kill(&rt2x00dev->txstatus_tasklet);
- tasklet_kill(&rt2x00dev->rxdone_tasklet);
- tasklet_kill(&rt2x00dev->autowake_tasklet);
- tasklet_kill(&rt2x00dev->tbtt_tasklet);
- tasklet_kill(&rt2x00dev->pretbtt_tasklet);
- }
-}
-
static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -628,355 +589,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
/*
- * Interrupt functions.
- */
-static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev)
-{
- struct ieee80211_conf conf = { .flags = 0 };
- struct rt2x00lib_conf libconf = { .conf = &conf };
-
- rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
-}
-
-static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
-{
- __le32 *txwi;
- u32 word;
- int wcid, tx_wcid;
-
- wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
-
- txwi = rt2800_drv_get_txwi(entry);
- rt2x00_desc_read(txwi, 1, &word);
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-
- return (tx_wcid == wcid);
-}
-
-static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
-{
- u32 status = *(u32 *)data;
-
- /*
- * rt2800pci hardware might reorder frames when exchanging traffic
- * with multiple BA enabled STAs.
- *
- * For example, a tx queue
- * [ STA1 | STA2 | STA1 | STA2 ]
- * can result in tx status reports
- * [ STA1 | STA1 | STA2 | STA2 ]
- * when the hw decides to aggregate the frames for STA1 into one AMPDU.
- *
- * To mitigate this effect, associate the tx status to the first frame
- * in the tx queue with a matching wcid.
- */
- if (rt2800mmio_txdone_entry_check(entry, status) &&
- !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
- /*
- * Got a matching frame, associate the tx status with
- * the frame
- */
- entry->status = status;
- set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
- return true;
- }
-
- /* Check the next frame */
- return false;
-}
-
-static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
-{
- u32 status = *(u32 *)data;
-
- /*
- * Find the first frame without tx status and assign this status to it
- * regardless if it matches or not.
- */
- if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
- /*
- * Got a matching frame, associate the tx status with
- * the frame
- */
- entry->status = status;
- set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
- return true;
- }
-
- /* Check the next frame */
- return false;
-}
-static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
- void *data)
-{
- if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
- rt2800_txdone_entry(entry, entry->status,
- rt2800mmio_get_txwi(entry));
- return false;
- }
-
- /* No more frames to release */
- return true;
-}
-
-static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
- u32 status;
- u8 qid;
- int max_tx_done = 16;
-
- while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
- qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
- if (unlikely(qid >= QID_RX)) {
- /*
- * Unknown queue, this shouldn't happen. Just drop
- * this tx status.
- */
- rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
- qid);
- break;
- }
-
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- if (unlikely(queue == NULL)) {
- /*
- * The queue is NULL, this shouldn't happen. Stop
- * processing here and drop the tx status
- */
- rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
- qid);
- break;
- }
-
- if (unlikely(rt2x00queue_empty(queue))) {
- /*
- * The queue is empty. Stop processing here
- * and drop the tx status.
- */
- rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
- qid);
- break;
- }
-
- /*
- * Let's associate this tx status with the first
- * matching frame.
- */
- if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
- Q_INDEX, &status,
- rt2800mmio_txdone_find_entry)) {
- /*
- * We cannot match the tx status to any frame, so just
- * use the first one.
- */
- if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
- Q_INDEX, &status,
- rt2800mmio_txdone_match_first)) {
- rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
- qid);
- break;
- }
- }
-
- /*
- * Release all frames with a valid tx status.
- */
- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
- Q_INDEX, NULL,
- rt2800mmio_txdone_release_entries);
-
- if (--max_tx_done == 0)
- break;
- }
-
- return !max_tx_done;
-}
-
-static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
-{
- u32 reg;
-
- /*
- * Enable a single interrupt. The interrupt mask register
- * access needs locking.
- */
- spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®);
- rt2x00_set_field32(®, irq_field, 1);
- rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-static void rt2800mmio_txstatus_tasklet(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2800mmio_txdone(rt2x00dev))
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-
- /*
- * No need to enable the tx status interrupt here as we always
- * leave it enabled to minimize the possibility of a tx status
- * register overflow. See comment in interrupt handler.
- */
-}
-
-static void rt2800mmio_pretbtt_tasklet(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2x00lib_pretbtt(rt2x00dev);
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
-}
-
-static void rt2800mmio_tbtt_tasklet(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
- u32 reg;
-
- rt2x00lib_beacondone(rt2x00dev);
-
- if (rt2x00dev->intf_ap_count) {
- /*
- * The rt2800pci hardware tbtt timer is off by 1us per tbtt
- * causing beacon skew and as a result causing problems with
- * some powersaving clients over time. Shorten the beacon
- * interval every 64 beacons by 64us to mitigate this effect.
- */
- if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®);
- rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL,
- (rt2x00dev->beacon_int * 16) - 1);
- rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®);
- rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL,
- (rt2x00dev->beacon_int * 16));
- rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- }
- drv_data->tbtt_tick++;
- drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
- }
-
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
-}
-
-static void rt2800mmio_rxdone_tasklet(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00mmio_rxdone(rt2x00dev))
- tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
-}
-
-static void rt2800mmio_autowake_tasklet(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2800mmio_wakeup(rt2x00dev);
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- rt2800mmio_enable_interrupt(rt2x00dev,
- INT_MASK_CSR_AUTO_WAKEUP);
-}
-
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
-{
- u32 status;
- int i;
-
- /*
- * The TX_FIFO_STATUS interrupt needs special care. We should
- * read TX_STA_FIFO but we should do it immediately as otherwise
- * the register can overflow and we would lose status reports.
- *
- * Hence, read the TX_STA_FIFO register and copy all tx status
- * reports into a kernel FIFO which is handled in the txstatus
- * tasklet. We use a tasklet to process the tx status reports
- * because we can schedule the tasklet multiple times (when the
- * interrupt fires again during tx status processing).
- *
- * Furthermore we don't disable the TX_FIFO_STATUS
- * interrupt here but leave it enabled so that the TX_STA_FIFO
- * can also be read while the tx status tasklet gets executed.
- *
- * Since we have only one producer and one consumer we don't
- * need to lock the kfifo.
- */
- for (i = 0; i < rt2x00dev->tx->limit; i++) {
- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
-
- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
- break;
-
- if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
- break;
- }
- }
-
- /* Schedule the tasklet for processing the tx status. */
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-}
-
-static irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
-{
- struct rt2x00_dev *rt2x00dev = dev_instance;
- u32 reg, mask;
-
- /* Read status and ACK all interrupts */
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
- rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
- if (!reg)
- return IRQ_NONE;
-
- if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- return IRQ_HANDLED;
-
- /*
- * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
- * for interrupts and interrupt masks we can just use the value of
- * INT_SOURCE_CSR to create the interrupt mask.
- */
- mask = ~reg;
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
- rt2800mmio_txstatus_interrupt(rt2x00dev);
- /*
- * Never disable the TX_FIFO_STATUS interrupt.
- */
- rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
- }
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
- tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
- tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
- tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
- tasklet_schedule(&rt2x00dev->autowake_tasklet);
-
- /*
- * Disable all interrupts for which a tasklet was scheduled right now,
- * the tasklet will reenable the appropriate interrupts.
- */
- spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®);
- reg &= mask;
- rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- spin_unlock(&rt2x00dev->irqmask_lock);
-
- return IRQ_HANDLED;
-}
-
-/*
* Device probe functions.
*/
static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
--
1.7.10
^ permalink raw reply related
* [PATCH 10/21] rt2x00: rt2800pci: use rt2800mmio prefix for initialization functions
From: Gabor Juhos @ 2013-10-17 7:42 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
The functions are used for devices with memory
mapped I/O and contain no PCI specific code at
all. Use rt2800mmio prefix instead of rt2800pci
in the function names to reflect that.
The patch contains no functional changes.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index d0e4ec5..7770471 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -245,7 +245,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Initialization functions.
*/
-static bool rt2800pci_get_entry_state(struct queue_entry *entry)
+static bool rt2800mmio_get_entry_state(struct queue_entry *entry)
{
struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
@@ -261,7 +261,7 @@ static bool rt2800pci_get_entry_state(struct queue_entry *entry)
}
}
-static void rt2800pci_clear_entry(struct queue_entry *entry)
+static void rt2800mmio_clear_entry(struct queue_entry *entry)
{
struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -290,7 +290,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
}
}
-static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
+static int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev)
{
struct queue_entry_priv_mmio *entry_priv;
@@ -358,7 +358,7 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
-static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
+static int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -411,7 +411,7 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/* Wait for DMA, ignore error until we initialize queues. */
rt2800_wait_wpdma_ready(rt2x00dev);
- if (unlikely(rt2800pci_init_queues(rt2x00dev)))
+ if (unlikely(rt2800mmio_init_queues(rt2x00dev)))
return -EIO;
retval = rt2800_enable_radio(rt2x00dev);
@@ -553,7 +553,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.read_eeprom = rt2800pci_read_eeprom,
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware,
- .drv_init_registers = rt2800pci_init_registers,
+ .drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
};
@@ -570,8 +570,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.load_firmware = rt2800_load_firmware,
.initialize = rt2x00mmio_initialize,
.uninitialize = rt2x00mmio_uninitialize,
- .get_entry_state = rt2800pci_get_entry_state,
- .clear_entry = rt2800pci_clear_entry,
+ .get_entry_state = rt2800mmio_get_entry_state,
+ .clear_entry = rt2800mmio_clear_entry,
.set_device_state = rt2800pci_set_device_state,
.rfkill_poll = rt2800_rfkill_poll,
.link_stats = rt2800_link_stats,
--
1.7.10
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox