* Re: [PATCH 1/2] cfg80211: on ibss_joined use the channel to get the proper bss object
From: Johannes Berg @ 2013-10-17 14:35 UTC (permalink / raw)
To: Antonio Quartulli; +Cc: linux-wireless, Antonio Quartulli
In-Reply-To: <1381790282-1146-1-git-send-email-antonio@meshcoding.com>
On Tue, 2013-10-15 at 00:38 +0200, Antonio Quartulli wrote:
> From: Antonio Quartulli <antonio@open-mesh.com>
>
> It may be the case that the same IBSS (same bssid and essid)
> exists on two different channels (i.e. two IBSSes created
> with different but fixed freq) and therefore the latter must
> be also used to distinguish them.
>
> Fix wdev->current_bss assignment by passing the channel to
> cfg80211_get_bss() on ibss_joined.
> This ensures that cfg80211_get_bss() picks up the proper bss
> object.
This makes no sense, wdev->channel should always be NULL (unless the
same wdev was in AP or mesh mode first and that somehow leaked out?)
johannes
^ permalink raw reply
* Re: [PATCH 1/6] cfg80211: export reg_initiator_name()
From: Johannes Berg @ 2013-10-17 14:34 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linville, linux-wireless
In-Reply-To: <1381797731-2454-2-git-send-email-mcgrof@do-not-panic.com>
On Mon, 2013-10-14 at 17:42 -0700, Luis R. Rodriguez wrote:
> Drivers can now use this to parse the regulatory request and
> be more verbose when needed.
Applied.
johannes
^ permalink raw reply
* Re: [PATCH] cfg80211: fix channel to frequency mapping in 5.9GHz range
From: Johannes Berg @ 2013-10-17 14:33 UTC (permalink / raw)
To: Dennis H Jensen; +Cc: linville, linux-wireless
In-Reply-To: <1381830012.3711.50.camel@djensen-laptop>
On Tue, 2013-10-15 at 11:40 +0200, Dennis H Jensen wrote:
> > Yes, but then before 5910 would have been channel 182. Now you're making
> > it channel 197. That doesn't really make sense at all.
>
> OK, fair enough, but the fact is that there is a hole in the frequencies
> that were added in 802.11p.
802.11p ... yeah, that's an issue.
> > > In case that doesn't do it. What is needed to get channel 182 to be 5910
> > > MHz as Annex E defines for the US and Europe? Channel to frequency
> > > mapping based on operating class?
> >
> > Annex E is the 802.11 spec, to get something into that ...
>
> You misunderstood me; the European operating class 14, for example,
> states that channel 182 is to be 5910.
That's a 10MHz channel only.
In any case, I don't see a good way out. Pretending that the channel
number is something else like you did in this patch is clearly wrong and
will obviously lead to interoperability issues.
I think we need to actually start taking the operating class (or maybe
just the starting frequency) into account in the kernel. How we do that
I don't really know.
johannes
^ permalink raw reply
* Re: [PATCH 00/21] rt2x00: separate rt2800 PCI and SoC driver
From: Helmut Schaa @ 2013-10-17 14:31 UTC (permalink / raw)
To: Gabor Juhos; +Cc: John W. Linville, linux-wireless, rt2x00 Users List
In-Reply-To: <1381995755-16471-1-git-send-email-juhosg@openwrt.org>
On Thu, Oct 17, 2013 at 9:42 AM, Gabor Juhos <juhosg@openwrt.org> wrote:
> 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.
Nice series. Does this also reduce module size on when building for
SoC without PCI support?
Helmut
^ permalink raw reply
* Re: [PATCH] mac80211: fixes for mesh powersave logic
From: Johannes Berg @ 2013-10-17 14:30 UTC (permalink / raw)
To: Marco Porsch; +Cc: linux-wireless, devel
In-Reply-To: <1381832964-3684-1-git-send-email-marco@cozybit.com>
On Tue, 2013-10-15 at 12:29 +0200, Marco Porsch wrote:
> This patch fixes errors in the mesh powersave logic which
> cause that remote peers do not get peer power mode change
> notifications and mesh peer service periods (MPSPs) got
> stuck.
>
> When closing a peer link, set the (now invalid) peer-specific
> power mode to 'unknown'.
>
> Avoid overhead when local power mode is unchanged.
>
> Reliably clear MPSP flags on peering status update.
>
> Avoid MPSP flags getting stuck by not requesting a further
> MPSP ownership if we already are an MPSP owner.
Applied to -next, there are too many unimportant and unrelated changes
in this patch for me to send it to 3.12 at this point.
johannes
^ permalink raw reply
* Re: [PATCH] mac80211: Remove check for offchannel state when waking netdev queues
From: Johannes Berg @ 2013-10-17 14:28 UTC (permalink / raw)
To: Seth Forshee; +Cc: linux-wireless
In-Reply-To: <1381871781-29128-1-git-send-email-seth.forshee@canonical.com>
On Tue, 2013-10-15 at 16:16 -0500, Seth Forshee wrote:
> 6c17b77b67587b9f9e3070fb89fe98cef3187131 ensures that a device's
> mac80211 queues will remain stopped while offchannel. Since the
> vif can no longer be offchannel when the queues wake it's not
> necessary to check for this before waking its netdev queues.
Applied.
johannes
^ permalink raw reply
* Re: [PATCH] ath10k: add error handling to ath10k_pci_wait()
From: Kalle Valo @ 2013-10-17 14:27 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQ=x+KJxXtcdMYKEGGjfF3oryTXgA2N+4OAa+6fcSAK4uw@mail.gmail.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> On 17 October 2013 01:36, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>> ath10k_pci_wait() didn't notify any errors to callers, it
>> just printed a warning so add proper error handling.
>>
>> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
[...]
>> @@ -2227,7 +2231,13 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
>> ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
>> PCIE_SOC_WAKE_ADDRESS);
>>
>> - ath10k_pci_wait(ar);
>> + ret = ath10k_pci_wait(ar);
>> + if (ret) {
>> + ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n",
>> + ret);
>> + free_irq(ar_pci->pdev->irq, ar);
>> + return ret;
>> + }
>
> I think we could actually use ath10k_do_pci_wake/sleep() here (see
> above iowrite). It does basically the same thing - sets the wake
> register and waits until HW wakes up. I think ath10k_pci_wait() could
> even go away.
That would be nice, I'll take a look. Thanks for the review.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 0/5] rfkill-gpio: ACPI support
From: Johannes Berg @ 2013-10-17 14:26 UTC (permalink / raw)
To: Heikki Krogerus
Cc: John W. Linville, Rhyland Klein, Rafael J. Wysocki, linux-acpi,
linux-wireless, netdev
In-Reply-To: <1381920823-15403-1-git-send-email-heikki.krogerus@linux.intel.com>
On Wed, 2013-10-16 at 13:53 +0300, 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.
Applied. I'm totally relying on all the reviewers though, since I have
very little idea of what's going on. If anyone else wants to maintain
the rfkill-gpio driver I'd welcome that :-)
johannes
^ permalink raw reply
* Re: [PATCH] ath10k: add error handling to ath10k_pci_wait()
From: Michal Kazior @ 2013-10-17 14:24 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <20131017083615.31028.25088.stgit@localhost6.localdomain6>
On 17 October 2013 01:36, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> ath10k_pci_wait() didn't notify any errors to callers, it
> just printed a warning so add proper error handling.
>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath10k/pci.c | 28 ++++++++++++++++++++++++----
> 1 file changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
> index 1e9cfcc9..92759cd 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -525,15 +525,19 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar)
> return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON);
> }
>
> -static void ath10k_pci_wait(struct ath10k *ar)
> +static int ath10k_pci_wait(struct ath10k *ar)
> {
> int n = 100;
>
> while (n-- && !ath10k_pci_target_is_awake(ar))
> msleep(10);
>
> - if (n < 0)
> + if (n < 0) {
> ath10k_warn("Unable to wakeup target\n");
> + return -ETIMEDOUT;
> + }
> +
> + return 0;
> }
>
> int ath10k_do_pci_wake(struct ath10k *ar)
> @@ -2227,7 +2231,13 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
> ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
> PCIE_SOC_WAKE_ADDRESS);
>
> - ath10k_pci_wait(ar);
> + ret = ath10k_pci_wait(ar);
> + if (ret) {
> + ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n",
> + ret);
> + free_irq(ar_pci->pdev->irq, ar);
> + return ret;
> + }
I think we could actually use ath10k_do_pci_wake/sleep() here (see
above iowrite). It does basically the same thing - sets the wake
register and waits until HW wakes up. I think ath10k_pci_wait() could
even go away.
>
> /*
> * A potential race occurs here: The CORE_BASE write
> @@ -2290,6 +2300,10 @@ static int ath10k_pci_start_intr(struct ath10k *ar)
> }
>
> ret = ath10k_pci_start_intr_legacy(ar);
> + if (ret) {
> + ath10k_warn("Failed to start legacy interrupts: %d\n", ret);
> + return ret;
> + }
>
> exit:
> ar_pci->num_msi_intrs = num;
> @@ -2315,13 +2329,19 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
> {
> struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
> int wait_limit = 300; /* 3 sec */
> + int ret;
>
> /* Wait for Target to finish initialization before we proceed. */
> iowrite32(PCIE_SOC_WAKE_V_MASK,
> ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
> PCIE_SOC_WAKE_ADDRESS);
>
> - ath10k_pci_wait(ar);
> + ret = ath10k_pci_wait(ar);
> + if (ret) {
> + ath10k_warn("Failed to reset target, target did not wake up: %d\n",
> + ret);
> + return ret;
> + }
Ditto.
Michał
^ permalink raw reply
* Re: [PATCH] mac80211_hwsim: Add iface comb for DFS
From: Johannes Berg @ 2013-10-17 13:44 UTC (permalink / raw)
To: Janusz Dziedzic; +Cc: linux-wireless
In-Reply-To: <1381773079-2678-1-git-send-email-janusz.dziedzic@tieto.com>
On Mon, 2013-10-14 at 19:51 +0200, Janusz Dziedzic wrote:
> Add iface combination that allow DFS support.
> Add also debugfs dfs_simulate_radar file that
> can be used to simulate radar event.
> This could be usefull for mac80211/cfg80211/
typo: useful
> @@ -1714,6 +1716,7 @@ static void mac80211_hwsim_free(void)
>
> list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
> debugfs_remove(data->debugfs_group);
> + debugfs_remove(data->debugfs_radar);
I think it would be good to convert to debugfs_remove_recursive first -
that avoids the need for the new dentry pointer as well as the remove
here. Can you do that (as a separate patch)?
> +static int hwsim_write_simulate_radar(void *dat, u64 val)
> +{
> + struct mac80211_hwsim_data *data = dat;
> +
> + ieee80211_radar_detected(data->hw);
> +
> + return 0;
> +}
> +
> +DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL,
> + hwsim_write_simulate_radar, "%llu\n");
Does the u64 make sense? Probably doesn't matter much, but seems weird
to be so specific for a file that really doesn't care about the value?
johannes
^ permalink raw reply
* Re: [PATCH 3.12] mac80211: disable WMM with invalid parameters
From: Johannes Berg @ 2013-10-17 13:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Antonio Quartulli
In-Reply-To: <1381995881-16935-1-git-send-email-johannes@sipsolutions.net>
On Thu, 2013-10-17 at 09:44 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Some APs (notably a Sitecom WL-153 v1 with firmware 1.45) are sending
> invalid WMM parameters setting AIFSN, ECWmin and ECWmax to zero. The
> spec mandates that the value of AIFSN is at least 2, and some cards
> (e.g. Intel with the iwldvm driver) can't transmit when the invalid
> QoS parameters are actually uploaded to the firmware.
>
> Since there's little chance of being able to guess the values that
> the AP actually meant, disable WMM if such an invalid case is found.
> Since ECWmin/ECWmax are allowed to be zero, only verify AIFSN >= 2
> and ECWmin <= ECWmax.
I've applied a fixed version.
johannes
^ permalink raw reply
* Re: Power saving features for iwl4965
From: Stanislaw Gruszka @ 2013-10-17 13:32 UTC (permalink / raw)
To: Pedro Francisco; +Cc: Tino Keitel, ML linux-wireless
In-Reply-To: <20131017090654.GA21496@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 307 bytes --]
On Thu, Oct 17, 2013 at 11:06:55AM +0200, Stanislaw Gruszka wrote:
> Sorry for late answer. I have two more patches, which perhaps make
> powersave stop crashing on 3945. Please test them (note that I only
> compile tested, be carefull :-)
First patch has a bug. I'm attaching improved version.
Stanislaw
[-- Attachment #2: 0001-iwlegacy-poke-device-when-waiting-for-hcmd.patch --]
[-- Type: text/plain, Size: 2045 bytes --]
>From dae9f167853f266d5efe688f965968725375e2ae Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Thu, 17 Oct 2013 15:30:07 +0200
Subject: [PATCH] iwlegacy poke device when waiting for hcmd
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlegacy/common.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index b03e22e..3d8dae3c 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -254,8 +254,6 @@ il_get_cmd_string(u8 cmd)
}
EXPORT_SYMBOL(il_get_cmd_string);
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
static void
il_generic_cmd_callback(struct il_priv *il, struct il_device_cmd *cmd,
struct il_rx_pkt *pkt)
@@ -305,11 +303,15 @@ il_send_cmd_async(struct il_priv *il, struct il_host_cmd *cmd)
return 0;
}
+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+#define COMMAND_POKE_TIMEOUT (HZ / 10)
+
int
il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd)
{
- int cmd_idx;
- int ret;
+ unsigned long flags;
+ int cmd_idx, ret;
+ int timeout = HOST_COMPLETE_TIMEOUT;
lockdep_assert_held(&il->mutex);
@@ -333,9 +335,22 @@ il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd)
goto out;
}
- ret = wait_event_timeout(il->wait_command_queue,
- !test_bit(S_HCMD_ACTIVE, &il->status),
- HOST_COMPLETE_TIMEOUT);
+ while (timeout > 0) {
+ ret = wait_event_timeout(il->wait_command_queue,
+ !test_bit(S_HCMD_ACTIVE, &il->status),
+ COMMAND_POKE_TIMEOUT);
+ if (ret)
+ break;
+
+ /* Poke the device, it may have lost the command. */
+ spin_lock_irqsave(&il->reg_lock, flags);
+ _il_grab_nic_access(il);
+ _il_release_nic_access(il);
+ spin_unlock_irqrestore(&il->reg_lock, flags);
+
+ timeout -= COMMAND_POKE_TIMEOUT;
+ }
+
if (!ret) {
if (test_bit(S_HCMD_ACTIVE, &il->status)) {
IL_ERR("Error sending %s: time out after %dms.\n",
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH 5/5] net: rfkill: gpio: add ACPI support
From: Rafael J. Wysocki @ 2013-10-17 11:48 UTC (permalink / raw)
To: Mika Westerberg
Cc: Heikki Krogerus, John W. Linville, Johannes Berg, Rhyland Klein,
linux-acpi, linux-wireless, netdev
In-Reply-To: <20131017074426.GG3521@intel.com>
On Thursday, October 17, 2013 10:44:26 AM Mika Westerberg wrote:
> 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.
OK, so
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
for the ACPI-related changes.
Thanks!
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply
* Re: [PATCH 3.12 1/3] mac80211: fix honouring rate flags in low-rate transmit
From: Johannes Berg @ 2013-10-17 11:35 UTC (permalink / raw)
To: linux-wireless; +Cc: Andrei Otcheretianski
In-Reply-To: <1381843030-12260-1-git-send-email-johannes@sipsolutions.net>
On Tue, 2013-10-15 at 15:17 +0200, Johannes Berg wrote:
> From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
>
> Transmissions with the IEEE80211_TX_CTL_NO_CCK_RATE flag set
> (which can come from userspace) were no longer guaranteed to
> be transmitted with allowed rates since commit 2103dec14792b
> ("mac80211: select and adjust bitrates according to channel
> mode") due to a missing rate_flags check in that commit. The
> commit also introduced the need to check the 5/10 MHz flags
> but accidentally didn't. Fix it by adding the missing check.
Applied 1 and 2.
johannes
^ permalink raw reply
* Re: [PATCH 3.12] mac80211: disable WMM with invalid parameters
From: Johannes Berg @ 2013-10-17 11:10 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless@vger.kernel.org, Antonio Quartulli
In-Reply-To: <CAB3XZEff+Xguf_Bk7p4S2N3j03dT1tB0u1u8enP4cd8NtD2jnA@mail.gmail.com>
On Thu, 2013-10-17 at 11:41 +0200, Eliad Peller wrote:
> > + do {
> > + wp = cfg80211_find_vendor_ie(0x0050F2, 2, start, len);
> > + start = wp;
> > + len -= wp[1];
> you might NULL deref here.
> but i don't really see how this calculation makes sense anyway (you
> should probably increase start and take care of the ie's id+len (i.e.
> wp[1] + 2) as well)?
Yeah, that loop was pretty bogus ...
while (true) {
wp = cfg80211_find_vendor_ie(
WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WMM,
start, len);
if (!wp)
break;
start = wp;
len -= wp[1] + 2;
/* if this IE is too short, try the next */
if (wp[1] <= 4)
continue;
/* if this IE is WMM params, we found what we wanted */
if (wp[6] == 1)
break;
}
is better, I think?
johannes
^ permalink raw reply
* [PATCH 3.12] rt2800usb: slow down TX status polling
From: Stanislaw Gruszka @ 2013-10-17 10:04 UTC (permalink / raw)
To: linux-wireless; +Cc: users
Polling TX statuses too frequently has two negative effects. First is
randomly peek CPU usage, causing overall system functioning delays.
Second bad effect is that device is not able to fill TX statuses in
H/W register on some workloads and we get lot of timeouts like below:
ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2
ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2
ieee80211 phy4: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
This not only cause flood of messages in dmesg, but also bad throughput,
since rate scaling algorithm can not work optimally.
In the future, we should probably make polling interval be adjusted
automatically, but for now just increase values, this make mentioned
problems gone.
Resolve:
https://bugzilla.kernel.org/show_bug.cgi?id=62781
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 96677ce5..e095e61 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -176,8 +176,8 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
if (rt2800usb_txstatus_pending(rt2x00dev)) {
- /* Read register after 250 us */
- hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000),
+ /* Read register after 1 ms */
+ hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 1000000),
HRTIMER_MODE_REL);
return false;
}
@@ -202,8 +202,8 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
return;
- /* Read TX_STA_FIFO register after 500 us */
- hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000),
+ /* Read TX_STA_FIFO register after 2 ms */
+ hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 2000000),
HRTIMER_MODE_REL);
}
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH 3.12] mac80211: disable WMM with invalid parameters
From: Eliad Peller @ 2013-10-17 9:41 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless@vger.kernel.org, Antonio Quartulli, Johannes Berg
In-Reply-To: <1381995881-16935-1-git-send-email-johannes@sipsolutions.net>
On Thu, Oct 17, 2013 at 10:44 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Some APs (notably a Sitecom WL-153 v1 with firmware 1.45) are sending
> invalid WMM parameters setting AIFSN, ECWmin and ECWmax to zero. The
> spec mandates that the value of AIFSN is at least 2, and some cards
> (e.g. Intel with the iwldvm driver) can't transmit when the invalid
> QoS parameters are actually uploaded to the firmware.
>
> Since there's little chance of being able to guess the values that
> the AP actually meant, disable WMM if such an invalid case is found.
> Since ECWmin/ECWmax are allowed to be zero, only verify AIFSN >= 2
> and ECWmin <= ECWmax.
>
> Reported-by: Antonio Quartulli <antonio@meshcoding.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
[...]
> @@ -4192,9 +4231,36 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
> }
>
> /* prepare assoc data */
> -
> +
> ifmgd->beacon_crc_valid = false;
>
> + assoc_data->wmm = bss->wmm_used &&
> + (local->hw.queues >= IEEE80211_NUM_ACS);
> + if (assoc_data->wmm) {
> + /* try to check validity of WMM params IE */
> + const struct cfg80211_bss_ies *ies;
> + const u8 *wp, *start;
> + int len;
> +
> + rcu_read_lock();
> + ies = rcu_dereference(req->bss->ies);
> + start = ies->data;
> + len = ies->len;
> +
> + do {
> + wp = cfg80211_find_vendor_ie(0x0050F2, 2, start, len);
> + start = wp;
> + len -= wp[1];
you might NULL deref here.
but i don't really see how this calculation makes sense anyway (you
should probably increase start and take care of the ie's id+len (i.e.
wp[1] + 2) as well)?
Eliad.
^ permalink raw reply
* Re: Power saving features for iwl4965
From: Stanislaw Gruszka @ 2013-10-17 9:06 UTC (permalink / raw)
To: Pedro Francisco; +Cc: Tino Keitel, ML linux-wireless
In-Reply-To: <CAJZjf_x3xwMijn5Jjc0qAaFdzq-4sH-gtm+hv5jKVpFCSBu0=Q@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2086 bytes --]
On Sun, Aug 04, 2013 at 03:53:14PM +0100, Pedro Francisco wrote:
> On Sun, Aug 4, 2013 at 3:24 PM, Pedro Francisco
> <pedrogfrancisco@gmail.com> wrote:
> > On Wed, Jul 31, 2013 at 1:08 PM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> >> On Wed, Jul 17, 2013 at 12:48:30PM +0100, Pedro Francisco wrote:
> >>> On Tue, Jul 16, 2013 at 11:27 AM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> >>> >> I seem only to be able to trigger it with disable_hw_scan=0, I need
> >>> >> further testing with disable_hw_scan=1 (I use disable_hw_scan=0
> >>> >> because it prevents me from getting disconnected from eduroam Cisco
> >>> >> APs -- haven't tested disable_hw_scan=0 since the VOIP-friendly SW
> >>> >> scanning patch, however).
> >>> >>
> >>> >> Do you want the log anyway? (modprobe iwl3945 debug=0x47ffffff
> >>> >> disable_hw_scan=0 and runtime PCI powersave also enabled -- I don't
> >>> >> know if it matters).
> >>> >
> >>> > As this is not causing troubles with default disable_hw_scan option,
> >>> > I'll post that patch.
> >>>
> >>> My mistake, I can trigger error conditions _independently_ of
> >>> disable_hw_scan option being enabled or disabled, as long as powersave
> >>> is enabled.
> >>>
> >>> I'll send you a private email with the logs.
> >>
> >> I think I found bug which couse this firmware crash. We have only 5
> >> queues so updating write_ptr for txq[5] can cause random value write
> >> to HBUS_TARG_WRPTR register. I also added spin_lock to do not abuse
> >> writes we do in tx skb.
> >>
> >> Please test attached patch (with powersave on :-)
> >
> > Still not working :( I tested for two nights, first one was fine,
> > second was not (the only difference was I had kernel parameter
> > `slub_debug` on the second night, but my guess it shouldn't affect
> > anything?).
> >
> > Snippet of log follows, full logs I'll send privately (beware,
> > unzipped it's 423MB).
Sorry for late answer. I have two more patches, which perhaps make
powersave stop crashing on 3945. Please test them (note that I only
compile tested, be carefull :-)
Thanks
Stanislaw
[-- Attachment #2: 0001-iwlegacy-poke-device-when-waiting-for-hcmd.patch --]
[-- Type: text/plain, Size: 2005 bytes --]
>From c9da2966ce58ed1446367a0b14b0953ebc3fbfbe Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Thu, 17 Oct 2013 10:48:44 +0200
Subject: [PATCH 1/2] iwlegacy poke device when waiting for hcmd
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlegacy/common.c | 27 ++++++++++++++++++++-------
1 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index b03e22e..7ada864 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -254,8 +254,6 @@ il_get_cmd_string(u8 cmd)
}
EXPORT_SYMBOL(il_get_cmd_string);
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
static void
il_generic_cmd_callback(struct il_priv *il, struct il_device_cmd *cmd,
struct il_rx_pkt *pkt)
@@ -305,11 +303,15 @@ il_send_cmd_async(struct il_priv *il, struct il_host_cmd *cmd)
return 0;
}
+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+#define COMMAND_POKE_TIMEOUT (HZ / 10)
+
int
il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd)
{
- int cmd_idx;
- int ret;
+ unsigned long flags;
+ int cmd_idx, ret;
+ int timeout = HOST_COMPLETE_TIMEOUT;
lockdep_assert_held(&il->mutex);
@@ -333,9 +335,20 @@ il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd)
goto out;
}
- ret = wait_event_timeout(il->wait_command_queue,
- !test_bit(S_HCMD_ACTIVE, &il->status),
- HOST_COMPLETE_TIMEOUT);
+ while (timeout) {
+ ret = wait_event_timeout(il->wait_command_queue,
+ !test_bit(S_HCMD_ACTIVE, &il->status),
+ COMMAND_POKE_TIMEOUT);
+ if (ret)
+ break;
+
+ /* Poke the device, it may have lost the command. */
+ spin_lock_irqsave(&il->reg_lock, flags);
+ _il_grab_nic_access(il);
+ _il_release_nic_access(il);
+ spin_unlock_irqrestore(&il->reg_lock, flags);
+ }
+
if (!ret) {
if (test_bit(S_HCMD_ACTIVE, &il->status)) {
IL_ERR("Error sending %s: time out after %dms.\n",
--
1.7.1
[-- Attachment #3: 0002-iwlegacy-merge-and-fix-reclaim-for-3945.patch --]
[-- Type: text/plain, Size: 3829 bytes --]
>From 05b86620fcec5f18293b0df2a4dddbe34ae24125 Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Thu, 17 Oct 2013 11:03:21 +0200
Subject: [PATCH 2/2] iwlegacy: merge and fix reclaim for 3945
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlegacy/3945-mac.c | 9 +--------
drivers/net/wireless/iwlegacy/4965-mac.c | 12 +-----------
drivers/net/wireless/iwlegacy/common.h | 14 ++++++++++++++
3 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index dea3b50..d7c8dd3 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -1248,14 +1248,7 @@ il3945_rx_handle(struct il_priv *il)
len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
len += sizeof(u32); /* account for status word */
- /* Reclaim a command buffer only if this packet is a response
- * to a (driver-originated) command.
- * If the packet (e.g. Rx frame) originated from uCode,
- * there is no command buffer to reclaim.
- * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
- * but apparently a few don't get set; catch them here. */
- reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
- pkt->hdr.cmd != N_STATS && pkt->hdr.cmd != C_TX;
+ reclaim = il_need_reclaim(il, pkt);
/* Based on type of command response or notification,
* handle those that need handling via function in
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 86812b9..97cfaa9 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -4274,17 +4274,7 @@ il4965_rx_handle(struct il_priv *il)
len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
len += sizeof(u32); /* account for status word */
- /* Reclaim a command buffer only if this packet is a response
- * to a (driver-originated) command.
- * If the packet (e.g. Rx frame) originated from uCode,
- * there is no command buffer to reclaim.
- * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
- * but apparently a few don't get set; catch them here. */
- reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
- (pkt->hdr.cmd != N_RX_PHY) && (pkt->hdr.cmd != N_RX) &&
- (pkt->hdr.cmd != N_RX_MPDU) &&
- (pkt->hdr.cmd != N_COMPRESSED_BA) &&
- (pkt->hdr.cmd != N_STATS) && (pkt->hdr.cmd != C_TX);
+ reclaim = il_need_reclaim(il, pkt);
/* Based on type of command response or notification,
* handle those that need handling via function in
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 83f8ed8..eccd6a4 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1978,6 +1978,20 @@ extern void il_wr_prph(struct il_priv *il, u32 addr, u32 val);
extern u32 il_read_targ_mem(struct il_priv *il, u32 addr);
extern void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val);
+static inline bool il_need_reclaim(struct il_priv *il, struct il_rx_pkt *pkt)
+{
+ /* Reclaim a command buffer only if this packet is a response
+ * to a (driver-originated) command. If the packet (e.g. Rx frame)
+ * originated from uCode, there is no command buffer to reclaim.
+ * Ucode should set SEQ_RX_FRAME bit if ucode-originated, but
+ * apparently a few don't get set; catch them here.
+ */
+ return !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+ pkt->hdr.cmd != N_STATS && pkt->hdr.cmd != C_TX &&
+ pkt->hdr.cmd != N_RX_PHY && pkt->hdr.cmd != N_RX &&
+ pkt->hdr.cmd != N_RX_MPDU && pkt->hdr.cmd != N_COMPRESSED_BA;
+}
+
static inline void
_il_write8(struct il_priv *il, u32 ofs, u8 val)
{
--
1.7.1
^ permalink raw reply related
* Pull request: ath 20131017
From: Kalle Valo @ 2013-10-17 9:06 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, ath10k, ath6kl-devel
Hi John,
here's a pull request for ath6kl and ath10k. Notable changes:
Bartosz added support to ath10k for our 10.x AP firmware branch, which
gives us AP specific features and fixes. We still support the main
firmware branch as well just like before, ath10k detects runtime what
firmware is used. Unfortunately the firmware interface in 10.x branch is
somewhat different so there was quite a lot of changes in ath10k for
this.
Michal and Sujith did some performance improvements in ath10k. Vladimir
fixed a compiler warning and Fengguang removed an extra semicolon.
Please let me know if there are any problems.
Kalle
The following changes since commit 6e712d427cb0542afdd5220edb6e4f4f8a5b952d:
ath10k: replenish HTT RX buffers in a tasklet (2013-09-26 17:22:54 +0300)
are available in the git repository at:
git://github.com/kvalo/ath.git for-linville
for you to fetch changes up to 56b84287d14aa74823a9c290d0c5839d38365110:
ath10k: add might_sleep() to ath10k_wmi_cmd_send() (2013-10-16 15:44:47 +0300)
----------------------------------------------------------------
Bartosz Markowski (18):
ath10k: introduce dynamic WMI structures
ath10k: add wmi_10x_<cmd/event> definitions
ath10k: warn if give WMI command is not supported
ath10k: implement WMI events handling frame for both firmwares
ath10k: split ath10k_wmi_service_ready_event_rx
ath10k: drop the fw versioning sanity check
ath10k: implement host memory chunks
ath10k: bring back the WMI path for mgmt frames
ath10k: split wmi_cmd_init path
ath10k: add TARGET values for 10.x firmware
ath10k: introduce dynamic vdev parameters
ath10k: introduce dynamic pdev parameters
ath10k: handle FW API differences for scan structures
ath10k: enable 10.x firmware branch support
ath10k: extend the max_scan time
ath10k: do not warn about unsupported vdev param
ath10k: rename WMI_CMD_UNDEFINED
ath10k: return better errno for unsupported pdev params
Fengguang Wu (1):
ath10k: remove unneded semicolon from ath10k_core_fetch_firmware_api_n()
Kalle Valo (6):
ath10k: rename board_data in struct ath10k
ath10k: store separate pointers for firmware data
ath10k: implement firmware IE container support
ath10k: fix ath10k_debug_start() locking
ath10k: fix ath10k_bss_assoc() to not sleep in atomic context
ath10k: add might_sleep() to ath10k_wmi_cmd_send()
Marek Puzyniak (1):
ath10k: make monitor vdev down before stoping it
Michal Kazior (12):
ath10k: split tid calculation from tx function
ath10k: split vdev_id calculation from tx function
ath10k: remove ce_sendlist_send
ath10k: remove num_sends_allowed
ath10k: fix printf format string
ath10k: fix possible memory leak in new FW loading
ath10k: fix RX performance when using AP 10.X FW
ath10k: use workqueue to set WEP TX key
ath10k: fix add_interface failure handling
ath10k: track vif list internally
ath10k: fix scheduling while atomic config bug
ath10k: remove unnecessary checks
Sujith Manoharan (1):
ath10k: Fix bug in max. VHT A-MPDU size
Vladimir Murzin (1):
ath6kl: fix compilation warning in ath6kl_htc_pipe_conn_service
drivers/net/wireless/ath/ath10k/ce.c | 35 +-
drivers/net/wireless/ath/ath10k/ce.h | 16 +-
drivers/net/wireless/ath/ath10k/core.c | 285 ++++++--
drivers/net/wireless/ath/ath10k/core.h | 47 +-
drivers/net/wireless/ath/ath10k/debug.c | 15 +-
drivers/net/wireless/ath/ath10k/debug.h | 5 +
drivers/net/wireless/ath/ath10k/htt_tx.c | 4 +-
drivers/net/wireless/ath/ath10k/hw.h | 56 +-
drivers/net/wireless/ath/ath10k/mac.c | 512 ++++++++------
drivers/net/wireless/ath/ath10k/mac.h | 2 +
drivers/net/wireless/ath/ath10k/pci.c | 25 +-
drivers/net/wireless/ath/ath10k/pci.h | 3 -
drivers/net/wireless/ath/ath10k/wmi.c | 1087 ++++++++++++++++++++++++++++--
drivers/net/wireless/ath/ath10k/wmi.h | 968 +++++++++++++++++++++++++-
drivers/net/wireless/ath/ath6kl/htc.h | 2 +-
15 files changed, 2674 insertions(+), 388 deletions(-)
^ permalink raw reply
* [PATCH] ath10k: add error handling to ath10k_pci_wait()
From: Kalle Valo @ 2013-10-17 8:36 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
ath10k_pci_wait() didn't notify any errors to callers, it
just printed a warning so add proper error handling.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/pci.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 1e9cfcc9..92759cd 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -525,15 +525,19 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar)
return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON);
}
-static void ath10k_pci_wait(struct ath10k *ar)
+static int ath10k_pci_wait(struct ath10k *ar)
{
int n = 100;
while (n-- && !ath10k_pci_target_is_awake(ar))
msleep(10);
- if (n < 0)
+ if (n < 0) {
ath10k_warn("Unable to wakeup target\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
}
int ath10k_do_pci_wake(struct ath10k *ar)
@@ -2227,7 +2231,13 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
PCIE_SOC_WAKE_ADDRESS);
- ath10k_pci_wait(ar);
+ ret = ath10k_pci_wait(ar);
+ if (ret) {
+ ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n",
+ ret);
+ free_irq(ar_pci->pdev->irq, ar);
+ return ret;
+ }
/*
* A potential race occurs here: The CORE_BASE write
@@ -2290,6 +2300,10 @@ static int ath10k_pci_start_intr(struct ath10k *ar)
}
ret = ath10k_pci_start_intr_legacy(ar);
+ if (ret) {
+ ath10k_warn("Failed to start legacy interrupts: %d\n", ret);
+ return ret;
+ }
exit:
ar_pci->num_msi_intrs = num;
@@ -2315,13 +2329,19 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int wait_limit = 300; /* 3 sec */
+ int ret;
/* Wait for Target to finish initialization before we proceed. */
iowrite32(PCIE_SOC_WAKE_V_MASK,
ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
PCIE_SOC_WAKE_ADDRESS);
- ath10k_pci_wait(ar);
+ ret = ath10k_pci_wait(ar);
+ if (ret) {
+ ath10k_warn("Failed to reset target, target did not wake up: %d\n",
+ ret);
+ return ret;
+ }
while (wait_limit-- &&
!(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) &
^ permalink raw reply related
* Re: [PATCH 3.12 3/3] mac80211: sanity check WMM/QoS parameters
From: Johannes Berg @ 2013-10-17 7:46 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1381843030-12260-3-git-send-email-johannes@sipsolutions.net>
On Tue, 2013-10-15 at 15:17 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Check for invalid WMM parameters (AIFSN < 2 or CWmax < CWmin)
> and try to set them to usable values in this case.
>
> Notably the Sitecom WL-153 v1 with firmware 1.45 is sending
> AIFSN, ECWmin and ECWmax as all zero.
We reviewed this and decided that it would be more robust to connect as
a non-WMM station, since we can't know what other parameters are wrong.
I've just posted a replacement patch to that effect.
johannes
^ permalink raw reply
* [PATCH 3.12] mac80211: disable WMM with invalid parameters
From: Johannes Berg @ 2013-10-17 7:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Antonio Quartulli, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
Some APs (notably a Sitecom WL-153 v1 with firmware 1.45) are sending
invalid WMM parameters setting AIFSN, ECWmin and ECWmax to zero. The
spec mandates that the value of AIFSN is at least 2, and some cards
(e.g. Intel with the iwldvm driver) can't transmit when the invalid
QoS parameters are actually uploaded to the firmware.
Since there's little chance of being able to guess the values that
the AP actually meant, disable WMM if such an invalid case is found.
Since ECWmin/ECWmax are allowed to be zero, only verify AIFSN >= 2
and ECWmin <= ECWmax.
Reported-by: Antonio Quartulli <antonio@meshcoding.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mlme.c | 86 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 611abfc..0764095 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -335,6 +335,7 @@ enum ieee80211_sta_flags {
IEEE80211_STA_DISABLE_VHT = BIT(11),
IEEE80211_STA_DISABLE_80P80MHZ = BIT(12),
IEEE80211_STA_DISABLE_160MHZ = BIT(13),
+ IEEE80211_STA_DISABLE_WMM = BIT(14),
};
struct ieee80211_mgd_auth_data {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 86e4ad5..9c47060 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2717,7 +2717,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
*/
ifmgd->wmm_last_param_set = -1;
- if (elems.wmm_param)
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && elems.wmm_param)
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
elems.wmm_param_len);
else
@@ -3152,7 +3152,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
&elems, true);
- if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
+ ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
elems.wmm_param_len))
changed |= BSS_CHANGED_QOS;
@@ -4135,6 +4136,44 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
return err;
}
+static bool ieee80211_usable_wmm_params(struct ieee80211_sub_if_data *sdata,
+ const u8 *wmm_param, int len)
+{
+ const u8 *pos;
+ size_t left;
+
+ if (len < 8)
+ return false;
+
+ if (wmm_param[5] != 1 /* version */)
+ return false;
+
+ pos = wmm_param + 8;
+ left = len - 8;
+
+ for (; left >= 4; left -= 4, pos += 4) {
+ u8 aifsn = pos[0] & 0x0f;
+ u8 ecwmin = pos[1] & 0x0f;
+ u8 ecwmax = (pos[1] & 0xf0) >> 4;
+ int aci = (pos[0] >> 5) & 0x03;
+
+ if (aifsn < 2) {
+ sdata_info(sdata,
+ "AP has invalid WMM params (AIFSN=%d for ACI %d), disabling WMM\n",
+ aifsn, aci);
+ return false;
+ }
+ if (ecwmin > ecwmax) {
+ sdata_info(sdata,
+ "AP has invalid WMM params (ECWmin/max=%d/%d for ACI %d), disabling WMM\n",
+ ecwmin, ecwmax, aci);
+ return false;
+ }
+ }
+
+ return true;
+}
+
int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
struct cfg80211_assoc_request *req)
{
@@ -4192,9 +4231,36 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
/* prepare assoc data */
-
+
ifmgd->beacon_crc_valid = false;
+ assoc_data->wmm = bss->wmm_used &&
+ (local->hw.queues >= IEEE80211_NUM_ACS);
+ if (assoc_data->wmm) {
+ /* try to check validity of WMM params IE */
+ const struct cfg80211_bss_ies *ies;
+ const u8 *wp, *start;
+ int len;
+
+ rcu_read_lock();
+ ies = rcu_dereference(req->bss->ies);
+ start = ies->data;
+ len = ies->len;
+
+ do {
+ wp = cfg80211_find_vendor_ie(0x0050F2, 2, start, len);
+ start = wp;
+ len -= wp[1];
+ } while (wp && wp[1] > 6 && wp[6] != 1);
+
+ if (!wp || !ieee80211_usable_wmm_params(sdata, wp + 2,
+ wp[1] - 2)) {
+ assoc_data->wmm = false;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_WMM;
+ }
+ rcu_read_unlock();
+ }
+
/*
* IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
* We still associate in non-HT mode (11a/b/g) if any one of these
@@ -4224,18 +4290,22 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
/* Also disable HT if we don't support it or the AP doesn't use WMM */
sband = local->hw.wiphy->bands[req->bss->channel->band];
if (!sband->ht_cap.ht_supported ||
- local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
+ local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
+ ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
- if (!bss->wmm_used)
+ if (!bss->wmm_used &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
netdev_info(sdata->dev,
"disabling HT as WMM/QoS is not supported by the AP\n");
}
/* disable VHT if we don't support it or the AP doesn't use WMM */
if (!sband->vht_cap.vht_supported ||
- local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
+ local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
+ ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
- if (!bss->wmm_used)
+ if (!bss->wmm_used &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
netdev_info(sdata->dev,
"disabling VHT as WMM/QoS is not supported by the AP\n");
}
@@ -4264,8 +4334,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
sdata->smps_mode = ifmgd->req_smps;
assoc_data->capability = req->bss->capability;
- assoc_data->wmm = bss->wmm_used &&
- (local->hw.queues >= IEEE80211_NUM_ACS);
assoc_data->supp_rates = bss->supp_rates;
assoc_data->supp_rates_len = bss->supp_rates_len;
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 21/21] rt2x00: rt2800pci: use module_pci_driver macro
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>
Use the module_pci_driver() macro to make the code simpler
by eliminating module_init and module_exit calls.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 260d2fd..b504455 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -470,16 +470,4 @@ static struct pci_driver rt2800pci_driver = {
.resume = rt2x00pci_resume,
};
-
-static int __init rt2800pci_init(void)
-{
- return pci_register_driver(&rt2800pci_driver);
-}
-
-static void __exit rt2800pci_exit(void)
-{
- pci_unregister_driver(&rt2800pci_driver);
-}
-
-module_init(rt2800pci_init);
-module_exit(rt2800pci_exit);
+module_pci_driver(rt2800pci_driver);
--
1.7.10
^ permalink raw reply related
* [PATCH 20/21] rt2x00: rt2800pci: move SoC specific code into a separate 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>
The PCI and SoC specific drivers are using separate
code now so it is not reasonable to use the same
module for both drivers anymore.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/Kconfig | 21 ++-
drivers/net/wireless/rt2x00/Makefile | 1 +
drivers/net/wireless/rt2x00/rt2800pci.c | 244 +---------------------------
drivers/net/wireless/rt2x00/rt2800soc.c | 263 +++++++++++++++++++++++++++++++
4 files changed, 284 insertions(+), 245 deletions(-)
create mode 100644 drivers/net/wireless/rt2x00/rt2800soc.c
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index e863249..006b8bc 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -58,12 +58,11 @@ config RT61PCI
config RT2800PCI
tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
- depends on PCI || SOC_RT288X || SOC_RT305X
+ depends on PCI
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
+ select RT2X00_LIB_PCI
select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO
select CRC_CCITT
@@ -200,6 +199,22 @@ config RT2800USB_UNKNOWN
endif
+config RT2800SOC
+ tristate "Ralink WiSoC support"
+ depends on SOC_RT288X || SOC_RT305X
+ select RT2X00_LIB_SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+ select RT2X00_LIB_FIRMWARE
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
+ ---help---
+ This adds support for Ralink WiSoC devices.
+ Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+
+ When compiled as a module, this driver will be called rt2800soc.
+
+
config RT2800_LIB
tristate
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index d11e356..24a6601 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RT2800PCI) += rt2800pci.o
obj-$(CONFIG_RT2500USB) += rt2500usb.o
obj-$(CONFIG_RT73USB) += rt73usb.o
obj-$(CONFIG_RT2800USB) += rt2800usb.o
+obj-$(CONFIG_RT2800SOC) += rt2800soc.o
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 488d1c4..260d2fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -37,13 +37,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/platform_device.h>
#include <linux/eeprom_93cx6.h>
#include "rt2x00.h"
#include "rt2x00mmio.h"
#include "rt2x00pci.h"
-#include "rt2x00soc.h"
#include "rt2800lib.h"
#include "rt2800mmio.h"
#include "rt2800.h"
@@ -56,7 +54,6 @@ static bool modparam_nohwcrypt = false;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-#ifdef CONFIG_PCI
static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
@@ -449,230 +446,15 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
#endif
{ 0, }
};
-#endif /* CONFIG_PCI */
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");
MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards");
-#ifdef CONFIG_PCI
MODULE_FIRMWARE(FIRMWARE_RT2860);
MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
-#endif /* CONFIG_PCI */
MODULE_LICENSE("GPL");
-#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
-static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
-{
- return modparam_nohwcrypt;
-}
-
-static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
- rt2800_disable_radio(rt2x00dev);
- rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
-}
-
-static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
- enum dev_state state)
-{
- int retval = 0;
-
- switch (state) {
- case STATE_RADIO_ON:
- retval = rt2800mmio_enable_radio(rt2x00dev);
- break;
-
- case STATE_RADIO_OFF:
- rt2800soc_disable_radio(rt2x00dev);
- break;
-
- case STATE_RADIO_IRQ_ON:
- case STATE_RADIO_IRQ_OFF:
- rt2800mmio_toggle_irq(rt2x00dev, state);
- break;
-
- case STATE_DEEP_SLEEP:
- case STATE_SLEEP:
- case STATE_STANDBY:
- case STATE_AWAKE:
- /* These states are not supported, but don't report an error */
- retval = 0;
- break;
-
- default:
- retval = -ENOTSUPP;
- break;
- }
-
- if (unlikely(retval))
- rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
- state, retval);
-
- return retval;
-}
-
-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
-{
- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
-
- if (!base_addr)
- return -ENOMEM;
-
- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
-
- iounmap(base_addr);
- return 0;
-}
-
-/* Firmware functions */
-static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
- WARN_ON_ONCE(1);
- return NULL;
-}
-
-static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev,
- const u8 *data, const size_t len)
-{
- WARN_ON_ONCE(1);
- return 0;
-}
-
-static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev,
- const u8 *data, const size_t len)
-{
- WARN_ON_ONCE(1);
- return 0;
-}
-
-static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
- const u8 *data, const size_t len)
-{
- WARN_ON_ONCE(1);
- return 0;
-}
-
-static const struct ieee80211_ops rt2800soc_mac80211_ops = {
- .tx = rt2x00mac_tx,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .configure_filter = rt2x00mac_configure_filter,
- .set_key = rt2x00mac_set_key,
- .sw_scan_start = rt2x00mac_sw_scan_start,
- .sw_scan_complete = rt2x00mac_sw_scan_complete,
- .get_stats = rt2x00mac_get_stats,
- .get_tkip_seq = rt2800_get_tkip_seq,
- .set_rts_threshold = rt2800_set_rts_threshold,
- .sta_add = rt2x00mac_sta_add,
- .sta_remove = rt2x00mac_sta_remove,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2800_conf_tx,
- .get_tsf = rt2800_get_tsf,
- .rfkill_poll = rt2x00mac_rfkill_poll,
- .ampdu_action = rt2800_ampdu_action,
- .flush = rt2x00mac_flush,
- .get_survey = rt2800_get_survey,
- .get_ringparam = rt2x00mac_get_ringparam,
- .tx_frames_pending = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2800_ops rt2800soc_rt2800_ops = {
- .register_read = rt2x00mmio_register_read,
- .register_read_lock = rt2x00mmio_register_read, /* same for SoCs */
- .register_write = rt2x00mmio_register_write,
- .register_write_lock = rt2x00mmio_register_write, /* same for SoCs */
- .register_multiread = rt2x00mmio_register_multiread,
- .register_multiwrite = rt2x00mmio_register_multiwrite,
- .regbusy_read = rt2x00mmio_regbusy_read,
- .read_eeprom = rt2800soc_read_eeprom,
- .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
- .drv_write_firmware = rt2800soc_write_firmware,
- .drv_init_registers = rt2800mmio_init_registers,
- .drv_get_txwi = rt2800mmio_get_txwi,
-};
-
-static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
- .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 = rt2800soc_get_firmware_name,
- .check_firmware = rt2800soc_check_firmware,
- .load_firmware = rt2800soc_load_firmware,
- .initialize = rt2x00mmio_initialize,
- .uninitialize = rt2x00mmio_uninitialize,
- .get_entry_state = rt2800mmio_get_entry_state,
- .clear_entry = rt2800mmio_clear_entry,
- .set_device_state = rt2800soc_set_device_state,
- .rfkill_poll = rt2800_rfkill_poll,
- .link_stats = rt2800_link_stats,
- .reset_tuner = rt2800_reset_tuner,
- .link_tuner = rt2800_link_tuner,
- .gain_calibration = rt2800_gain_calibration,
- .vco_calibration = rt2800_vco_calibration,
- .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,
- .write_beacon = rt2800_write_beacon,
- .clear_beacon = rt2800_clear_beacon,
- .fill_rxdone = rt2800mmio_fill_rxdone,
- .config_shared_key = rt2800_config_shared_key,
- .config_pairwise_key = rt2800_config_pairwise_key,
- .config_filter = rt2800_config_filter,
- .config_intf = rt2800_config_intf,
- .config_erp = rt2800_config_erp,
- .config_ant = rt2800_config_ant,
- .config = rt2800_config,
- .sta_add = rt2800_sta_add,
- .sta_remove = rt2800_sta_remove,
-};
-
-static const struct rt2x00_ops rt2800soc_ops = {
- .name = KBUILD_MODNAME,
- .drv_data_size = sizeof(struct rt2800_drv_data),
- .max_ap_intf = 8,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
- .tx_queues = NUM_TX_QUEUES,
- .queue_init = rt2800mmio_queue_init,
- .lib = &rt2800soc_rt2x00_ops,
- .drv = &rt2800soc_rt2800_ops,
- .hw = &rt2800soc_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
- .debugfs = &rt2800_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-static int rt2800soc_probe(struct platform_device *pdev)
-{
- return rt2x00soc_probe(pdev, &rt2800soc_ops);
-}
-
-static struct platform_driver rt2800soc_driver = {
- .driver = {
- .name = "rt2800_wmac",
- .owner = THIS_MODULE,
- .mod_name = KBUILD_MODNAME,
- },
- .probe = rt2800soc_probe,
- .remove = rt2x00soc_remove,
- .suspend = rt2x00soc_suspend,
- .resume = rt2x00soc_resume,
-};
-#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
-
-#ifdef CONFIG_PCI
static int rt2800pci_probe(struct pci_dev *pci_dev,
const struct pci_device_id *id)
{
@@ -687,38 +469,16 @@ static struct pci_driver rt2800pci_driver = {
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
};
-#endif /* CONFIG_PCI */
+
static int __init rt2800pci_init(void)
{
- int ret = 0;
-
-#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
- ret = platform_driver_register(&rt2800soc_driver);
- if (ret)
- return ret;
-#endif
-#ifdef CONFIG_PCI
- ret = pci_register_driver(&rt2800pci_driver);
- if (ret) {
-#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
- platform_driver_unregister(&rt2800soc_driver);
-#endif
- return ret;
- }
-#endif
-
- return ret;
+ return pci_register_driver(&rt2800pci_driver);
}
static void __exit rt2800pci_exit(void)
{
-#ifdef CONFIG_PCI
pci_unregister_driver(&rt2800pci_driver);
-#endif
-#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
- platform_driver_unregister(&rt2800soc_driver);
-#endif
}
module_init(rt2800pci_init);
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c
new file mode 100644
index 0000000..1359227
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
@@ -0,0 +1,263 @@
+/* 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: rt2800soc
+ * Abstract: rt2800 WiSoC specific routines.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00soc.h"
+#include "rt2800.h"
+#include "rt2800lib.h"
+#include "rt2800mmio.h"
+
+/* Allow hardware encryption to be disabled. */
+static bool modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+ return modparam_nohwcrypt;
+}
+
+static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+ rt2800_disable_radio(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
+}
+
+static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
+ enum dev_state state)
+{
+ int retval = 0;
+
+ switch (state) {
+ case STATE_RADIO_ON:
+ retval = rt2800mmio_enable_radio(rt2x00dev);
+ break;
+
+ case STATE_RADIO_OFF:
+ rt2800soc_disable_radio(rt2x00dev);
+ break;
+
+ case STATE_RADIO_IRQ_ON:
+ case STATE_RADIO_IRQ_OFF:
+ rt2800mmio_toggle_irq(rt2x00dev, state);
+ break;
+
+ case STATE_DEEP_SLEEP:
+ case STATE_SLEEP:
+ case STATE_STANDBY:
+ case STATE_AWAKE:
+ /* These states are not supported, but don't report an error */
+ retval = 0;
+ break;
+
+ default:
+ retval = -ENOTSUPP;
+ break;
+ }
+
+ if (unlikely(retval))
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
+
+ return retval;
+}
+
+static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+ void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+
+ if (!base_addr)
+ return -ENOMEM;
+
+ memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+
+ iounmap(base_addr);
+ return 0;
+}
+
+/* Firmware functions */
+static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+ WARN_ON_ONCE(1);
+ return NULL;
+}
+
+static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev,
+ const u8 *data, const size_t len)
+{
+ WARN_ON_ONCE(1);
+ return 0;
+}
+
+static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev,
+ const u8 *data, const size_t len)
+{
+ WARN_ON_ONCE(1);
+ return 0;
+}
+
+static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
+ const u8 *data, const size_t len)
+{
+ WARN_ON_ONCE(1);
+ return 0;
+}
+
+static const struct ieee80211_ops rt2800soc_mac80211_ops = {
+ .tx = rt2x00mac_tx,
+ .start = rt2x00mac_start,
+ .stop = rt2x00mac_stop,
+ .add_interface = rt2x00mac_add_interface,
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .configure_filter = rt2x00mac_configure_filter,
+ .set_key = rt2x00mac_set_key,
+ .sw_scan_start = rt2x00mac_sw_scan_start,
+ .sw_scan_complete = rt2x00mac_sw_scan_complete,
+ .get_stats = rt2x00mac_get_stats,
+ .get_tkip_seq = rt2800_get_tkip_seq,
+ .set_rts_threshold = rt2800_set_rts_threshold,
+ .sta_add = rt2x00mac_sta_add,
+ .sta_remove = rt2x00mac_sta_remove,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2800_conf_tx,
+ .get_tsf = rt2800_get_tsf,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
+ .ampdu_action = rt2800_ampdu_action,
+ .flush = rt2x00mac_flush,
+ .get_survey = rt2800_get_survey,
+ .get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2800_ops rt2800soc_rt2800_ops = {
+ .register_read = rt2x00mmio_register_read,
+ .register_read_lock = rt2x00mmio_register_read, /* same for SoCs */
+ .register_write = rt2x00mmio_register_write,
+ .register_write_lock = rt2x00mmio_register_write, /* same for SoCs */
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
+ .read_eeprom = rt2800soc_read_eeprom,
+ .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
+ .drv_write_firmware = rt2800soc_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+ .drv_get_txwi = rt2800mmio_get_txwi,
+};
+
+static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
+ .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 = rt2800soc_get_firmware_name,
+ .check_firmware = rt2800soc_check_firmware,
+ .load_firmware = rt2800soc_load_firmware,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
+ .get_entry_state = rt2800mmio_get_entry_state,
+ .clear_entry = rt2800mmio_clear_entry,
+ .set_device_state = rt2800soc_set_device_state,
+ .rfkill_poll = rt2800_rfkill_poll,
+ .link_stats = rt2800_link_stats,
+ .reset_tuner = rt2800_reset_tuner,
+ .link_tuner = rt2800_link_tuner,
+ .gain_calibration = rt2800_gain_calibration,
+ .vco_calibration = rt2800_vco_calibration,
+ .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,
+ .write_beacon = rt2800_write_beacon,
+ .clear_beacon = rt2800_clear_beacon,
+ .fill_rxdone = rt2800mmio_fill_rxdone,
+ .config_shared_key = rt2800_config_shared_key,
+ .config_pairwise_key = rt2800_config_pairwise_key,
+ .config_filter = rt2800_config_filter,
+ .config_intf = rt2800_config_intf,
+ .config_erp = rt2800_config_erp,
+ .config_ant = rt2800_config_ant,
+ .config = rt2800_config,
+ .sta_add = rt2800_sta_add,
+ .sta_remove = rt2800_sta_remove,
+};
+
+static const struct rt2x00_ops rt2800soc_ops = {
+ .name = KBUILD_MODNAME,
+ .drv_data_size = sizeof(struct rt2800_drv_data),
+ .max_ap_intf = 8,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
+ .tx_queues = NUM_TX_QUEUES,
+ .queue_init = rt2800mmio_queue_init,
+ .lib = &rt2800soc_rt2x00_ops,
+ .drv = &rt2800soc_rt2800_ops,
+ .hw = &rt2800soc_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+ .debugfs = &rt2800_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+static int rt2800soc_probe(struct platform_device *pdev)
+{
+ return rt2x00soc_probe(pdev, &rt2800soc_ops);
+}
+
+static struct platform_driver rt2800soc_driver = {
+ .driver = {
+ .name = "rt2800_wmac",
+ .owner = THIS_MODULE,
+ .mod_name = KBUILD_MODNAME,
+ },
+ .probe = rt2800soc_probe,
+ .remove = rt2x00soc_remove,
+ .suspend = rt2x00soc_suspend,
+ .resume = rt2x00soc_resume,
+};
+
+module_platform_driver(rt2800soc_driver);
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver.");
+MODULE_LICENSE("GPL");
--
1.7.10
^ permalink raw reply related
* [PATCH 19/21] rt2x00: rt2800pci: use separate hwcrypt_disabled callback for SoC devices
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 'rt2800pci_hwcrypt_disabled' function is the
only PCI specific callback which is used by the
SoC driver. Create a clone of that to get rid of
the dependency.
Even though the two functions are using the same
variable, but the SoC specific code will be moved
into a separate module which will have its own
'modparam_nohwcrypt' variable.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 77ddd1a..488d1c4 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -56,12 +56,12 @@ static bool modparam_nohwcrypt = false;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+#ifdef CONFIG_PCI
static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
}
-#ifdef CONFIG_PCI
static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
{
unsigned int i;
@@ -462,6 +462,11 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
MODULE_LICENSE("GPL");
#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
+static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+ return modparam_nohwcrypt;
+}
+
static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
{
rt2800_disable_radio(rt2x00dev);
@@ -585,7 +590,7 @@ static const struct rt2800_ops rt2800soc_rt2800_ops = {
.register_multiwrite = rt2x00mmio_register_multiwrite,
.regbusy_read = rt2x00mmio_regbusy_read,
.read_eeprom = rt2800soc_read_eeprom,
- .hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
+ .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
.drv_write_firmware = rt2800soc_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
--
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