* Re: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Dmitry Torokhov @ 2016-10-24 23:47 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, briannorris
In-Reply-To: <1477318892-22877-2-git-send-email-akarwar@marvell.com>
On Mon, Oct 24, 2016 at 07:51:29PM +0530, Amitkumar Karwar wrote:
> This variable is guarded by spinlock at all other places. This patch
> takes care of missing spinlock usage in mwifiex_shutdown_drv().
>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> drivers/net/wireless/marvell/mwifiex/init.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index 82839d9..8e5e424 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -670,11 +670,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
>
> adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
> /* wait for mwifiex_process to complete */
> + spin_lock_irqsave(&adapter->main_proc_lock, flags);
> if (adapter->mwifiex_processing) {
> + spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
> mwifiex_dbg(adapter, WARN,
> "main process is still running\n");
> return ret;
> }
> + spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
What happens if adapter->mwifiex_processing will become true here?
>
> /* cancel current command */
> if (adapter->curr_cmd) {
> --
> 1.9.1
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH 1/2] mwifiex: fix corner case power save issue
From: Brian Norris @ 2016-10-24 23:07 UTC (permalink / raw)
To: Amitkumar Karwar; +Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam
In-Reply-To: <1477062948-8558-1-git-send-email-akarwar@marvell.com>
Hi,
On Fri, Oct 21, 2016 at 08:45:47PM +0530, Amitkumar Karwar wrote:
> We may get SLEEP event from firmware even if TXDone for last Tx packet
> is still pending. In this case, we may end up accessing PCIe memory for
> handling TXDone after power save handshake is completed. This causes
> kernel crash with external abort.
>
> We will delay sending SLEEP confirm to firmware in
> this case to resolve the problem.
>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> index 5347728..f582f61 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> @@ -1118,7 +1118,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
> void
> mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
> {
> - if (!adapter->cmd_sent &&
> + if (!adapter->cmd_sent && !adapter->data_sent &&
> !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
> mwifiex_dnld_sleep_confirm_cmd(adapter);
> else
Looks good to me, and tests out on my systems:
Tested-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Brian Norris <briannorris@chromium.org>
^ permalink raw reply
* Re: [PATCH 5/5] mwifiex: wait for firmware dump completion in remove_card
From: Brian Norris @ 2016-10-24 20:23 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, dmitry.torokhov,
Xinming Hu
In-Reply-To: <1477318892-22877-5-git-send-email-akarwar@marvell.com>
On Mon, Oct 24, 2016 at 07:51:32PM +0530, Amitkumar Karwar wrote:
> From: Xinming Hu <huxm@marvell.com>
>
> This patch ensures to wait for firmware dump completion in
> mwifiex_remove_card().
>
> For sdio interface, reset_trigger variable is used to identify
> if mwifiex_sdio_remove() is called by sdio_work during reset or
> the call is from sdio subsystem.
>
> This patch fixes a kernel crash observed during reboot when firmware
> dump operation is in process.
>
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> drivers/net/wireless/marvell/mwifiex/pcie.c | 2 ++
> drivers/net/wireless/marvell/mwifiex/sdio.c | 15 ++++++++++++++-
> 2 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 986bf07..4512e86 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -528,6 +528,8 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
> if (!adapter || !adapter->priv_num)
> return;
>
> + cancel_work_sync(&pcie_work);
Is there a good reason you have to cancel the work? What if you were
just to finish it (i.e., flush_work())?
In any case, I think this is fine, so for the PCIe bits:
Reviewed-by: Brian Norris <briannorris@chromium.org>
> +
> if (user_rmmod && !adapter->mfg_mode) {
> #ifdef CONFIG_PM_SLEEP
> if (adapter->is_suspended)
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index 4cad1c2..f974260 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -46,6 +46,15 @@
> */
> static u8 user_rmmod;
>
> +/* reset_trigger variable is used to identify if mwifiex_sdio_remove()
> + * is called by sdio_work during reset or the call is from sdio subsystem.
> + * We will cancel sdio_work only if the call is from sdio subsystem.
> + */
> +static u8 reset_triggered;
> +
> +static void mwifiex_sdio_work(struct work_struct *work);
> +static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
> +
> static struct mwifiex_if_ops sdio_ops;
> static unsigned long iface_work_flags;
>
> @@ -289,6 +298,9 @@ mwifiex_sdio_remove(struct sdio_func *func)
> if (!adapter || !adapter->priv_num)
> return;
>
> + if (!reset_triggered)
> + cancel_work_sync(&sdio_work);
> +
> mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
>
> if (user_rmmod && !adapter->mfg_mode) {
> @@ -2290,7 +2302,9 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
> * discovered and initializes them from scratch.
> */
>
> + reset_triggered = 1;
> mwifiex_sdio_remove(func);
> + reset_triggered = 0;
Boy that's ugly! Couldn't you just create something like
__mwifiex_sdio_remove(), which does everything except the
cancel_work_sync()? Then you'd do this for the .remove() callback:
cancel_work_sync(&sdio_work);
__mwifiex_sdio_remove(func);
and for mwifiex_recreate_adapter() you'd just call
__mwifiex_sdio_remove()? The static variable that simply serves as a
(non-reentrant) function call parameter seems like a really poor
alternative to this simple refactoring.
Or you could just address the TODO in this function, and you wouldn't
have to do this dance at all...
Brian
>
> /* power cycle the adapter */
> sdio_claim_host(func);
> @@ -2621,7 +2635,6 @@ static void mwifiex_sdio_work(struct work_struct *work)
> mwifiex_sdio_card_reset_work(save_adapter);
> }
>
> -static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
> /* This function resets the card */
> static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
> {
> --
> 1.9.1
>
^ permalink raw reply
* Re: Bayesian rate control
From: Björn Smedman @ 2016-10-24 20:17 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, ath9k-devel
In-Reply-To: <1477286912.4085.1.camel@sipsolutions.net>
Hi Johannes,
Thanks for the pointers.
On Mon, Oct 24, 2016 at 7:28 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
>> I'm thinking the best driver for rate control experimentation would
>> be ath9k, right? If so then a TP-Link TL-WA901ND router (apparently
>> based on Qualcomm QCA956x SOC) with OpenWrt, and a TP-Link TL-WDN4800
>> PCIe card (apparently based on Atheros AR9380 with PCI ID 168c:0030)
>> for my desktop sounds like a good combo, no?
>
> Seems reasonable, yes. You wouldn't have VHT, but HT has enough search
> space to keep you busy ;-)
Are there any cards out there that support VHT and use s/w rate
control (Minstrel)? Just in case I run out of search space. :P
BR Bj=C3=B6rn
^ permalink raw reply
* Re: compex wle900vx (ath10k) problem on 4.4.24 / armv7
From: Oliver Zemann @ 2016-10-24 20:14 UTC (permalink / raw)
To: Matthias Klein, Michal Kazior; +Cc: linux-wireless
In-Reply-To: <em1c0906d6-d30a-4f2c-bafb-bfec0d18a58d@nb-mak>
>> Can you try cherry-picking it into your 4.4.24 and see if it helps?
I created a patch which should work for 4.4.24 (at least for arch linux
arm it applied successful)
diff --git a/drivers/pci/pcie/portdrv_core.c
b/drivers/pci/pcie/portdrv_core.c
index 88122dc..f2caf38 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/pm_runtime.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pm.h>
@@ -350,6 +351,8 @@ static int pcie_device_init(struct pci_dev *pdev,
int service, int irq)
return retval;
}
+ pm_runtime_no_callbacks(device);
+
return 0;
}
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index be35da2..1624cc3 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -93,6 +93,28 @@ static int pcie_port_resume_noirq(struct device *dev)
return 0;
}
+static int pcie_port_runtime_suspend(struct device *dev)
+{
+ return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
+}
+
+static int pcie_port_runtime_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int pcie_port_runtime_idle(struct device *dev)
+{
+ /*
+ * Assume the PCI core has set bridge_d3 whenever it thinks the port
+ * should be good to go to D3. Everything else, including moving
+ * the port to D3, is handled by the PCI core.
+ */
+ return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
+}
++
+
+
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.suspend = pcie_port_device_suspend,
.resume = pcie_port_device_resume,
@@ -101,6 +123,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.poweroff = pcie_port_device_suspend,
.restore = pcie_port_device_resume,
.resume_noirq = pcie_port_resume_noirq,
+ .runtime_suspend = pcie_port_runtime_suspend,
+ .runtime_resume = pcie_port_runtime_resume,
+ .runtime_idle = pcie_port_runtime_idle,
};
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
@@ -139,11 +164,39 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
* it by default.
*/
dev->d3cold_allowed = false;
+
+ /*
+ * Prevent runtime PM if the port is advertising support for PCIe
+ * hotplug. Otherwise the BIOS hotplug SMI code might not be able
+ * to enumerate devices behind this port properly (the port is
+ * powered down preventing all config space accesses to the
+ * subordinate devices). We can't be sure for native PCIe hotplug
+ * either so prevent that as well.
+ */
+ if (!dev->is_hotplug_bridge) {
+ /*
+ * Keep the port resumed 100ms to make sure things like
+ * config space accesses from userspace (lspci) will not
+ * cause the port to repeatedly suspend and resume.
+ */
+ pm_runtime_set_autosuspend_delay(&dev->dev, 100);
+ pm_runtime_use_autosuspend(&dev->dev);
+ pm_runtime_mark_last_busy(&dev->dev);
+ pm_runtime_put_autosuspend(&dev->dev);
+ pm_runtime_allow(&dev->dev);
+ }
+
return 0;
}
static void pcie_portdrv_remove(struct pci_dev *dev)
{
+ if (!dev->is_hotplug_bridge) {
+ pm_runtime_forbid(&dev->dev);
+ pm_runtime_get_noresume(&dev->dev);
+ pm_runtime_dont_use_autosuspend(&dev->dev);
+ }
+
pcie_port_device_remove(dev);
}
Just compiling the kernel... lets see what happens
^ permalink raw reply related
* Re: [PATCH 3/5] mwifiex: do not free firmware dump memory in shutdown_drv
From: Brian Norris @ 2016-10-24 19:41 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, dmitry.torokhov,
briannorris, Xinming Hu
In-Reply-To: <1477318892-22877-3-git-send-email-akarwar@marvell.com>
On Mon, Oct 24, 2016 at 07:51:30PM +0530, Amitkumar Karwar wrote:
> From: Xinming Hu <huxm@marvell.com>
>
> mwifiex_upload_device_dump() already takes care of freeing firmware dump
> memory. Doing the same thing in mwifiex_shutdown_drv() is redundant.
>
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Looks good:
Reviewed-by: Brian Norris <briannorris@chromium.org>
> ---
> drivers/net/wireless/marvell/mwifiex/init.c | 19 -------------------
> 1 file changed, 19 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index 8e5e424..365efb8 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -407,8 +407,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
> static void
> mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
> {
> - int idx;
> -
> if (!adapter) {
> pr_err("%s: adapter is NULL\n", __func__);
> return;
> @@ -426,23 +424,6 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
> mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
> mwifiex_free_cmd_buffer(adapter);
>
> - for (idx = 0; idx < adapter->num_mem_types; idx++) {
> - struct memory_type_mapping *entry =
> - &adapter->mem_type_mapping_tbl[idx];
> -
> - if (entry->mem_ptr) {
> - vfree(entry->mem_ptr);
> - entry->mem_ptr = NULL;
> - }
> - entry->mem_size = 0;
> - }
> -
> - if (adapter->drv_info_dump) {
> - vfree(adapter->drv_info_dump);
> - adapter->drv_info_dump = NULL;
> - adapter->drv_info_size = 0;
> - }
> -
> if (adapter->sleep_cfm)
> dev_kfree_skb_any(adapter->sleep_cfm);
> }
> --
> 1.9.1
>
^ permalink raw reply
* Re: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Brian Norris @ 2016-10-24 19:19 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, dmitry.torokhov
In-Reply-To: <1477318892-22877-2-git-send-email-akarwar@marvell.com>
On Mon, Oct 24, 2016 at 07:51:29PM +0530, Amitkumar Karwar wrote:
> This variable is guarded by spinlock at all other places. This patch
> takes care of missing spinlock usage in mwifiex_shutdown_drv().
>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> drivers/net/wireless/marvell/mwifiex/init.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index 82839d9..8e5e424 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -670,11 +670,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
>
> adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
> /* wait for mwifiex_process to complete */
> + spin_lock_irqsave(&adapter->main_proc_lock, flags);
> if (adapter->mwifiex_processing) {
I'm not quite sure why we have this check in the first place; if the
main process is still running, then don't we have bigger problems here
anyway? But this is definitely the "right" way to check this flag, so:
Reviewed-by: Brian Norris <briannorris@chromium.org>
> + spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
> mwifiex_dbg(adapter, WARN,
> "main process is still running\n");
> return ret;
> }
> + spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
>
> /* cancel current command */
> if (adapter->curr_cmd) {
> --
> 1.9.1
>
^ permalink raw reply
* Re: compex wle900vx (ath10k) problem on 4.4.24 / armv7
From: Oliver Zemann @ 2016-10-24 18:10 UTC (permalink / raw)
To: Jonas Gorski; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <CAOiHx=mY8DtgM-DxxqQW9U0=PeMjUbuvBsEjVbLissV6tVyYcA@mail.gmail.com>
>
> (please don't toppost)
Did not know that this is forbidden, sorry
> You can find an sd-card image at
> https://downloads.lede-project.org/snapshots/targets/mvebu/generic/ -
> it won't contain any wifi drivers though, you will need to install
> them separately - easiest by providing internet access over the wan
> port (the single ethernet port for the pro, it defaults to dhcp
> client), then running "opkg install kmod-ath10k" on shell.
I used dd to install the latest image from today to the SD. I am
connected through usb with screen, thats a very nice feature of the
board :)
I logged in, updated the packages with opkg update and then installed
kmod-ath10k but i received many errors:
[ 380.987440] ath10k_core: Unknown symbol cfg80211_find_ie_match (err 0)
[ 380.993996] ath10k_core: Unknown symbol ieee80211_wake_queue (err 0)
[ 381.000383] ath10k_core: Unknown symbol ieee80211_find_sta (err 0)
[ 381.006586] ath10k_core: Unknown symbol
ieee80211_stop_rx_ba_session_offl (err 0)
[ 381.014101] ath10k_core: Unknown symbol ieee80211_tx_status_irqsafe
(err 0)
[ 381.021096] ath10k_core: Unknown symbol
ieee80211_iter_chan_contexts_atomic (err 0)
[ 381.028778] ath10k_core: Unknown symbol __cfg80211_alloc_reply_skb
(err 0)
[ 381.035681] ath10k_core: Unknown symbol __cfg80211_alloc_event_skb
(err 0)
[ 381.042584] ath10k_core: Unknown symbol cfg80211_put_bss (err 0)
[ 381.048623] ath10k_core: Unknown symbol ieee80211_bss_get_ie (err 0)
[ 381.055005] ath10k_core: Unknown symbol wiphy_to_ieee80211_hw (err 0)
[ 381.061472] ath10k_core: Unknown symbol __cfg80211_send_event_skb (err 0)
[ 381.068284] ath10k_core: Unknown symbol ath_reg_notifier_apply (err 0)
[ 381.074878] ath10k_core: Unknown symbol ieee80211_queue_delayed_work
(err 0)
[ 381.081959] ath10k_core: Unknown symbol ieee80211_proberesp_get (err 0)
[ 381.088610] ath10k_core: Unknown symbol ieee80211_find_sta_by_ifaddr
(err 0)
[ 381.095689] ath10k_core: Unknown symbol
ieee80211_remain_on_channel_expired (err 0)
[ 381.103379] ath10k_core: Unknown symbol ath_is_world_regd (err 0)
[ 381.109503] ath10k_core: Unknown symbol ieee80211_wake_queues (err 0)
[ 381.115965] ath10k_core: Unknown symbol ieee80211_report_low_ack (err 0)
[ 381.122691] ath10k_core: Unknown symbol ieee80211_beacon_get_template
(err 0)
[ 381.129855] ath10k_core: Unknown symbol ieee80211_free_txskb (err 0)
[ 381.136232] ath10k_core: Unknown symbol ieee80211_alloc_hw_nm (err 0)
[ 381.142699] ath10k_core: Unknown symbol cfg80211_get_bss (err 0)
[ 381.148731] ath10k_core: Unknown symbol ieee80211_tx_dequeue (err 0)
[ 381.155111] ath10k_core: Unknown symbol __ieee80211_get_channel (err 0)
[ 381.161755] ath10k_core: Unknown symbol cfg80211_vendor_cmd_reply (err 0)
[ 381.168574] ath10k_core: Unknown symbol ieee80211_tx_status (err 0)
[ 381.174866] ath10k_core: Unknown symbol ieee80211_stop_queue (err 0)
[ 381.181246] ath10k_core: Unknown symbol ieee80211_ready_on_channel
(err 0)
[ 381.188142] ath10k_core: Unknown symbol ieee80211_stop_queues (err 0)
[ 381.194621] ath10k_core: Unknown symbol ieee80211_scan_completed (err 0)
[ 381.201349] ath10k_core: Unknown symbol
ieee80211_iterate_active_interfaces_atomic (err 0)
[ 381.209651] ath10k_core: Unknown symbol
ieee80211_channel_to_frequency (err 0)
[ 381.216896] ath10k_core: Unknown symbol ieee80211_unregister_hw (err 0)
[ 381.223537] ath10k_core: Unknown symbol dfs_pattern_detector_init (err 0)
[ 381.230354] ath10k_core: Unknown symbol ath_regd_init (err 0)
[ 381.236119] ath10k_core: Unknown symbol ieee80211_csa_update_counter
(err 0)
[ 381.243195] ath10k_core: Unknown symbol ieee80211_beacon_get_tim (err 0)
[ 381.249924] ath10k_core: Unknown symbol ieee80211_hdrlen (err 0)
[ 381.255951] ath10k_core: Unknown symbol
ieee80211_start_rx_ba_session_offl (err 0)
[ 381.263548] ath10k_core: Unknown symbol ieee80211_radar_detected (err 0)
[ 381.270276] ath10k_core: Unknown symbol ieee80211_csa_is_complete (err 0)
[ 381.277090] ath10k_core: Unknown symbol ieee80211_queue_work (err 0)
[ 381.283475] ath10k_core: Unknown symbol cfg80211_find_vendor_ie (err 0)
[ 381.290123] ath10k_core: Unknown symbol ieee80211_csa_finish (err 0)
[ 381.296498] ath10k_core: Unknown symbol ieee80211_rx_napi (err 0)
[ 381.330745] ath10k_pci: Unknown symbol ath10k_warn (err 0)
[ 381.336261] ath10k_pci: Unknown symbol ath10k_err (err 0)
[ 381.341699] ath10k_pci: Unknown symbol ath10k_print_driver_info (err 0)
[ 381.348340] ath10k_pci: Unknown symbol ath10k_htt_hif_tx_complete (err 0)
[ 381.355162] ath10k_pci: Unknown symbol
ath10k_htc_tx_completion_handler (err 0)
[ 381.362509] ath10k_pci: Unknown symbol
ath10k_debug_get_new_fw_crash_data (err 0)
[ 381.370020] ath10k_pci: Unknown symbol ath10k_core_create (err 0)
[ 381.376143] ath10k_pci: Unknown symbol
ath10k_htt_rx_pktlog_completion_handler (err 0)
[ 381.384097] ath10k_pci: Unknown symbol ath10k_core_destroy (err 0)
[ 381.390304] ath10k_pci: Unknown symbol
ath10k_htc_rx_completion_handler (err 0)
[ 381.397637] ath10k_pci: Unknown symbol ath10k_core_register (err 0)
[ 381.403930] ath10k_pci: Unknown symbol ath10k_info (err 0)
[ 381.409445] ath10k_pci: Unknown symbol backport_dependency_symbol (err 0)
[ 381.416255] ath10k_pci: Unknown symbol ath10k_htt_t2h_msg_handler (err 0)
[ 381.423072] ath10k_pci: Unknown symbol ath10k_core_unregister (err 0)
[ 381.429537] ath10k_pci: Unknown symbol ath10k_htt_txrx_compl_task (err 0)
Regards
Oli
^ permalink raw reply
* [PATCH 3/3] mwifiex: Enable WoWLAN for both sdio and pcie
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja@google.com>
Commit ce4f6f0c353b ("mwifiex: add platform specific wakeup interrupt
support") added WoWLAN feature only for sdio. This patch moves that
code to the common module so that all the interface drivers can use
it for free. It enables pcie and sdio for its use currently.
Signed-off-by: Rajat Jain <rajatja@google.com>
---
drivers/net/wireless/marvell/mwifiex/main.c | 41 ++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 25 ++++++++++
drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +
drivers/net/wireless/marvell/mwifiex/sdio.c | 72 ++---------------------------
drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ----
5 files changed, 73 insertions(+), 75 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index b2f3d96..20c9b77 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,14 +1552,55 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv)
+{
+ struct mwifiex_adapter *adapter = priv;
+
+ if (adapter->irq_wakeup >= 0) {
+ dev_dbg(adapter->dev, "%s: wake by wifi", __func__);
+ adapter->wake_by_wifi = true;
+ disable_irq_nosync(irq);
+ }
+
+ /* Notify PM core we are wakeup source */
+ pm_wakeup_event(adapter->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
{
+ int ret;
struct device *dev = adapter->dev;
if (!dev->of_node)
return;
adapter->dt_node = dev->of_node;
+ adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0);
+ if (!adapter->irq_wakeup) {
+ dev_info(dev, "fail to parse irq_wakeup from device tree\n");
+ return;
+ }
+
+ ret = devm_request_irq(dev, adapter->irq_wakeup,
+ mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+ "wifi_wake", adapter);
+ if (ret) {
+ dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
+ adapter->irq_wakeup, ret);
+ goto err_exit;
+ }
+
+ disable_irq(adapter->irq_wakeup);
+ if (device_init_wakeup(dev, true)) {
+ dev_err(dev, "fail to init wakeup for mwifiex\n");
+ goto err_exit;
+ }
+ return;
+
+err_exit:
+ adapter->irq_wakeup = 0;
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 83e0776..12def94 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1010,6 +1010,10 @@ struct mwifiex_adapter {
bool usb_mc_setup;
struct cfg80211_wowlan_nd_info *nd_info;
struct ieee80211_regdomain *regd;
+
+ /* Wake-on-WLAN (WoWLAN) */
+ int irq_wakeup;
+ bool wake_by_wifi;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1409,6 +1413,27 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
return false;
}
+/* Disable platform specific wakeup interrupt */
+static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter)
+{
+ if (adapter->irq_wakeup >= 0) {
+ disable_irq_wake(adapter->irq_wakeup);
+ if (!adapter->wake_by_wifi)
+ disable_irq(adapter->irq_wakeup);
+ }
+}
+
+/* Enable platform specific wakeup interrupt */
+static inline void mwifiex_enable_wake(struct mwifiex_adapter *adapter)
+{
+ /* Enable platform specific wakeup interrupt */
+ if (adapter->irq_wakeup >= 0) {
+ adapter->wake_by_wifi = false;
+ enable_irq(adapter->irq_wakeup);
+ enable_irq_wake(adapter->irq_wakeup);
+ }
+}
+
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ea423d5..af93661 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -133,6 +133,7 @@ static int mwifiex_pcie_suspend(struct device *dev)
adapter = card->adapter;
+ mwifiex_enable_wake(adapter);
hs_actived = mwifiex_enable_hs(adapter);
/* Indicate device suspended */
@@ -179,6 +180,7 @@ static int mwifiex_pcie_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_ASYNC_CMD);
+ mwifiex_disable_wake(adapter);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 558743a..ff5bb45 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -79,67 +79,18 @@ static const struct of_device_id mwifiex_sdio_of_match_table[] = {
{ }
};
-static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
-{
- struct mwifiex_plt_wake_cfg *cfg = priv;
-
- if (cfg->irq_wifi >= 0) {
- pr_info("%s: wake by wifi", __func__);
- cfg->wake_by_wifi = true;
- disable_irq_nosync(irq);
- }
-
- /* Notify PM core we are wakeup source */
- pm_wakeup_event(cfg->dev, 0);
-
- return IRQ_HANDLED;
-}
-
/* This function parse device tree node using mmc subnode devicetree API.
* The device node is saved in card->plt_of_node.
* if the device tree node exist and include interrupts attributes, this
* function will also request platform specific wakeup interrupt.
*/
-static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
+static int mwifiex_sdio_probe_of(struct device *dev)
{
- struct mwifiex_plt_wake_cfg *cfg;
- int ret;
-
if (!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
dev_err(dev, "required compatible string missing\n");
return -EINVAL;
}
- card->plt_of_node = dev->of_node;
- card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
- GFP_KERNEL);
- cfg = card->plt_wake_cfg;
- if (cfg && card->plt_of_node) {
- cfg->dev = dev;
- cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
- if (!cfg->irq_wifi) {
- dev_dbg(dev,
- "fail to parse irq_wifi from device tree\n");
- } else {
- ret = devm_request_irq(dev, cfg->irq_wifi,
- mwifiex_wake_irq_wifi,
- IRQF_TRIGGER_LOW,
- "wifi_wake", cfg);
- if (ret) {
- dev_dbg(dev,
- "Failed to request irq_wifi %d (%d)\n",
- cfg->irq_wifi, ret);
- card->plt_wake_cfg = NULL;
- return 0;
- }
- disable_irq(cfg->irq_wifi);
- }
- }
-
- ret = device_init_wakeup(dev, true);
- if (ret)
- dev_err(dev, "fail to init wakeup for mwifiex");
-
return 0;
}
@@ -199,11 +150,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
/* device tree node parsing and platform specific configuration*/
if (func->dev.of_node) {
- ret = mwifiex_sdio_probe_of(&func->dev, card);
- if (ret) {
- dev_err(&func->dev, "SDIO dt node parse failed\n");
+ ret = mwifiex_sdio_probe_of(&func->dev);
+ if (ret)
goto err_disable;
- }
valid_of_node = true;
}
@@ -269,12 +218,7 @@ static int mwifiex_sdio_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_SYNC_CMD);
- /* Disable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- disable_irq_wake(card->plt_wake_cfg->irq_wifi);
- if (!card->plt_wake_cfg->wake_by_wifi)
- disable_irq(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_disable_wake(adapter);
return 0;
}
@@ -354,13 +298,7 @@ static int mwifiex_sdio_suspend(struct device *dev)
}
adapter = card->adapter;
-
- /* Enable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- card->plt_wake_cfg->wake_by_wifi = false;
- enable_irq(card->plt_wake_cfg->irq_wifi);
- enable_irq_wake(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_enable_wake(adapter);
/* Enable the Host Sleep */
if (!mwifiex_enable_hs(adapter)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index 07cdd23..b9fbc5c 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -154,12 +154,6 @@
a->mpa_rx.start_port = 0; \
} while (0)
-struct mwifiex_plt_wake_cfg {
- struct device *dev;
- int irq_wifi;
- bool wake_by_wifi;
-};
-
/* data structure for SDIO MPA TX */
struct mwifiex_sdio_mpa_tx {
/* multiport tx aggregation buffer pointer */
@@ -243,8 +237,6 @@ struct mwifiex_sdio_card_reg {
struct sdio_mmc_card {
struct sdio_func *func;
struct mwifiex_adapter *adapter;
- struct device_node *plt_of_node;
- struct mwifiex_plt_wake_cfg *plt_wake_cfg;
const char *firmware;
const struct mwifiex_sdio_card_reg *reg;
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH 2/3] mwifiex: Introduce mwifiex_probe_of() to parse common properties
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja@google.com>
Introduce function mwifiex_probe_of() to parse common properties.
Since the interface drivers get to decide whether or not the device
tree node was a valid one (depending on the compatible property),
let the interface drivers pass a flag to indicate whether the device
tree node was a valid one.
The function mwifiex_probe_of()nodetself is currently only a place
holder with the next patch adding content to it.
Signed-off-by: Rajat Jain <rajatja@google.com>
---
drivers/net/wireless/marvell/mwifiex/main.c | 15 ++++++++++++++-
drivers/net/wireless/marvell/mwifiex/main.h | 2 +-
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/sdio.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 5 +----
drivers/net/wireless/marvell/mwifiex/usb.c | 2 +-
6 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index dcceab2..b2f3d96 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,6 +1552,16 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
+{
+ struct device *dev = adapter->dev;
+
+ if (!dev->of_node)
+ return;
+
+ adapter->dt_node = dev->of_node;
+}
+
/*
* This function adds the card.
*
@@ -1568,7 +1578,7 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
int
mwifiex_add_card(void *card, struct semaphore *sem,
struct mwifiex_if_ops *if_ops, u8 iface_type,
- struct device *dev)
+ struct device *dev, bool of_node_valid)
{
struct mwifiex_adapter *adapter;
@@ -1581,6 +1591,9 @@ mwifiex_add_card(void *card, struct semaphore *sem,
}
adapter->dev = dev;
+ if (of_node_valid)
+ mwifiex_probe_of(adapter);
+
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 91218a1..83e0776 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1412,7 +1412,7 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
- struct device *);
+ struct device *, bool);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 49b5835..ea423d5 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -194,6 +194,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pcie_service_card *card;
+ bool valid_of_node = false;
int ret;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
@@ -221,10 +222,11 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
ret = mwifiex_pcie_probe_of(&pdev->dev);
if (ret)
goto err_free;
+ valid_of_node = true;
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE, &pdev->dev);
+ MWIFIEX_PCIE, &pdev->dev, valid_of_node);
if (ret) {
pr_err("%s failed\n", __func__);
goto err_free;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index c95f41f..558743a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -156,6 +156,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
{
int ret;
struct sdio_mmc_card *card = NULL;
+ bool valid_of_node = false;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
func->vendor, func->device, func->class, func->num);
@@ -203,10 +204,11 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
dev_err(&func->dev, "SDIO dt node parse failed\n");
goto err_disable;
}
+ valid_of_node = true;
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO, &func->dev);
+ MWIFIEX_SDIO, &func->dev, valid_of_node);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index c8dccf5..73e337e 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2218,10 +2218,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
* The cal-data can be read from device tree and/or
* a configuration file and downloaded to firmware.
*/
- if ((priv->adapter->iface_type == MWIFIEX_SDIO ||
- priv->adapter->iface_type == MWIFIEX_PCIE) &&
- adapter->dev->of_node) {
- adapter->dt_node = adapter->dev->of_node;
+ if (adapter->dt_node) {
if (of_property_read_u32(adapter->dt_node,
"marvell,wakeup-pin",
&data) == 0) {
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index f847fff..11c9629 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -476,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB, &card->udev->dev);
+ MWIFIEX_USB, &card->udev->dev, false);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH 1/3] mwifiex: Allow mwifiex early access to device structure
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja@google.com>
Today all the interface drivers (usb/pcie/sdio) assign the
adapter->dev in the register_dev() callback, although they
have this piece of info well before hand.
This patch makes the device structure available for mwifiex
right at the beginning, so that it can be used for early
initialization if needed.
This is needed for subsequent patches in this patchset that
intend to unify and consolidate some of the code that would
otherwise have to be duplicated among the interface drivers
(sdio, pcie, usb).
Signed-off-by: Rajat Jain <rajatja@google.com>
---
drivers/net/wireless/marvell/mwifiex/main.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/main.h | 3 ++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +---
drivers/net/wireless/marvell/mwifiex/sdio.c | 5 +----
drivers/net/wireless/marvell/mwifiex/usb.c | 3 +--
5 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2478ccd..dcceab2 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1567,7 +1567,8 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
*/
int
mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops, u8 iface_type)
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev)
{
struct mwifiex_adapter *adapter;
@@ -1579,6 +1580,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_init_sw;
}
+ adapter->dev = dev;
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 26df28f..91218a1 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1411,7 +1411,8 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
+ struct device *);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index f7c84d3..49b5835 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -224,7 +224,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE);
+ MWIFIEX_PCIE, &pdev->dev);
if (ret) {
pr_err("%s failed\n", __func__);
goto err_free;
@@ -2990,11 +2990,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct pci_dev *pdev = card->dev;
/* save adapter pointer in card */
card->adapter = adapter;
- adapter->dev = &pdev->dev;
if (mwifiex_pcie_request_irq(adapter))
return -1;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 807af13..c95f41f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -206,7 +206,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO);
+ MWIFIEX_SDIO, &func->dev);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
@@ -2106,9 +2106,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
return ret;
}
-
- adapter->dev = &func->dev;
-
strcpy(adapter->fw_name, card->firmware);
if (card->fw_dump_enh) {
adapter->mem_type_mapping_tbl = generic_mem_type_map;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 73eb084..f847fff 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -476,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB);
+ MWIFIEX_USB, &card->udev->dev);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
@@ -932,7 +932,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
card->adapter = adapter;
- adapter->dev = &card->udev->dev;
switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
case USB8997_PID_1:
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH 0/3] mwifiex: Make WoWLAN a common feature
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
I have a Marvell card on the PCIe bus that needs to support
WoWLAN (wake-on-wireless-LAN) feature. This is a feature offered
by the "core" mwifiex card and is not specific to an interface
(pcie/sdio/usb).
Currently the code to parse the WowLAN pin, and activate it
resides only in sdio.c [mostly commit ce4f6f0c353b ("mwifiex: add
platform specific wakeup interrupt support")]. I started by
copying all that code & data structures in pcie.c/pcie.h but then
realized that the we should probably have it common since the
feature is not interface specific.
Further, I noticed that interface driver had no interest in
device trees since there are no properties specific to interfaces.
Currently the only properties needed, are the common ones needed
by the core mwifiex.
This patch set thus introduces mwifiex_probe_of() to parse the
common properties, and then moves the WowLAN specific code to the
common module so that all the interfaces can use it. Essentially
this is a single logical patch that has been split up into
multiple patches only for the reason of simplicity and code
reviews.
This is currently rebased on the top of Linus' tree with the
following 2 patches applied:
https://patchwork.kernel.org/patch/9362275/
https://patchwork.kernel.org/patch/9390225/
Rajat Jain (3):
mwifiex: Allow mwifiex early access to device structure
mwifiex: Introduce mwifiex_probe_of() to parse common properties
mwifiex: Enable WoWLAN for both sdio and pcie
drivers/net/wireless/marvell/mwifiex/main.c | 58 ++++++++++++++++++-
drivers/net/wireless/marvell/mwifiex/main.h | 28 ++++++++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 8 ++-
drivers/net/wireless/marvell/mwifiex/sdio.c | 79 +++-----------------------
drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ---
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 5 +-
drivers/net/wireless/marvell/mwifiex/usb.c | 3 +-
7 files changed, 99 insertions(+), 90 deletions(-)
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply
* Re: [PATCH 1/5] mwifiex: remove redundant condition in main process
From: Brian Norris @ 2016-10-24 17:43 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, dmitry.torokhov,
briannorris
In-Reply-To: <1477318892-22877-1-git-send-email-akarwar@marvell.com>
On Mon, Oct 24, 2016 at 07:51:28PM +0530, Amitkumar Karwar wrote:
> This condition while calling mwifiex_check_ps_cond() is redundant.
> The function internally already takes care of it.
>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Unless you're intentionally *not* logging the "Delay Sleep Confirm" in
some cases, this looks good:
Reviewed-by: Brian Norris <briannorris@chromium.org>
> ---
> drivers/net/wireless/marvell/mwifiex/main.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index 2478ccd..3b31ea2 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -355,10 +355,8 @@ process_start:
>
> /* Check if we need to confirm Sleep Request
> received previously */
> - if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
> - if (!adapter->cmd_sent && !adapter->curr_cmd)
> - mwifiex_check_ps_cond(adapter);
> - }
> + if (adapter->ps_state == PS_STATE_PRE_SLEEP)
> + mwifiex_check_ps_cond(adapter);
>
> /* * The ps_state may have been changed during processing of
> * Sleep Request event.
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH] cw1200: fix bogus maybe-uninitialized warning
From: Arnd Bergmann @ 2016-10-24 15:41 UTC (permalink / raw)
To: Solomon Peachy, Kalle Valo
Cc: Arnd Bergmann, Johannes Berg, linux-wireless, netdev,
linux-kernel
On x86, the cw1200 driver produces a rather silly warning about the
possible use of the 'ret' variable without an initialization
presumably after being confused by the architecture specific definition
of WARN_ON:
drivers/net/wireless/st/cw1200/wsm.c: In function ‘wsm_handle_rx’:
drivers/net/wireless/st/cw1200/wsm.c:1457:9: error: ‘ret’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
As the driver just checks the same variable twice here, we can simplify
it by removing the second condition, which makes it more readable and
avoids the warning.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/wireless/st/cw1200/wsm.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/st/cw1200/wsm.c b/drivers/net/wireless/st/cw1200/wsm.c
index 680d60eabc75..094e6637ade2 100644
--- a/drivers/net/wireless/st/cw1200/wsm.c
+++ b/drivers/net/wireless/st/cw1200/wsm.c
@@ -385,14 +385,13 @@ static int wsm_multi_tx_confirm(struct cw1200_common *priv,
if (WARN_ON(count <= 0))
return -EINVAL;
- if (count > 1) {
- /* We already released one buffer, now for the rest */
- ret = wsm_release_tx_buffer(priv, count - 1);
- if (ret < 0)
- return ret;
- else if (ret > 0)
- cw1200_bh_wakeup(priv);
- }
+ /* We already released one buffer, now for the rest */
+ ret = wsm_release_tx_buffer(priv, count - 1);
+ if (ret < 0)
+ return ret;
+
+ if (ret > 0)
+ cw1200_bh_wakeup(priv);
cw1200_debug_txed_multi(priv, count);
for (i = 0; i < count; ++i) {
--
2.9.0
^ permalink raw reply related
* [PATCH] wireless: fix bogus maybe-uninitialized warning
From: Arnd Bergmann @ 2016-10-24 15:38 UTC (permalink / raw)
To: Kalle Valo, Stanislav Yakovlev, Jouni Malinen, Johannes Berg,
David S. Miller
Cc: linux-wireless, netdev, Arnd Bergmann, linux-kernel
In-Reply-To: <20161024153918.2810634-1-arnd@arndb.de>
The hostap_80211_rx() function is supposed to set up the mac addresses
for four possible cases, based on two bits of input data. For
some reason, gcc decides that it's possible that none of the these
four cases apply and the addresses remain uninitialized:
drivers/net/wireless/intersil/hostap/hostap_80211_rx.c: In function ‘hostap_80211_rx’:
arch/x86/include/asm/string_32.h:77:14: warning: ‘src’ may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/net/wireless/intel/ipw2x00/libipw_rx.c: In function ‘libipw_rx’:
arch/x86/include/asm/string_32.h:77:14: error: ‘dst’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
arch/x86/include/asm/string_32.h:78:22: error: ‘*((void *)&dst+4)’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
This warning is clearly nonsense, but changing the last case into
'default' makes it obvious to the compiler too, which avoids the
warning and probably leads to better object code too.
The same code is duplicated several times in the kernel, so this
patch uses the same workaround for all copies. The exact configuration
was hit only very rarely in randconfig builds and I only saw it
in three drivers, but I assume that all of them are potentially
affected, and it's better to keep the code consistent.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++----
drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 2 +-
drivers/net/wireless/intersil/hostap/hostap_80211_rx.c | 2 +-
net/wireless/lib80211_crypt_tkip.c | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 3fd1cc98fd2f..84a6d12c3f8a 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -421,10 +421,6 @@ int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
switch ((le16_to_cpu(wh.frame_control)) &
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
- case 0:
- memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
- memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
- break;
case IEEE80211_FCTL_TODS:
memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
@@ -435,6 +431,10 @@ int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
break;
case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
break;
+ default:
+ memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
+ memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
+ break;
}
skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index cef7f7d79cd9..1c1ec7bb9302 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -507,7 +507,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
memcpy(dst, hdr->addr3, ETH_ALEN);
memcpy(src, hdr->addr4, ETH_ALEN);
break;
- case 0:
+ default:
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
break;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
index 599f30f22841..34dbddbf3f9b 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
@@ -855,7 +855,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
memcpy(dst, hdr->addr3, ETH_ALEN);
memcpy(src, hdr->addr4, ETH_ALEN);
break;
- case 0:
+ default:
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
break;
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index 71447cf86306..ba0a1f398ce5 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -556,7 +556,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
break;
- case 0:
+ default:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
--
2.9.0
^ permalink raw reply related
* [PATCH] staging: rtl8192x: fix bogus maybe-uninitialized warning
From: Arnd Bergmann @ 2016-10-24 15:38 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: linux-wireless, netdev, Arnd Bergmann, Kurt Kanzenbach, devel,
linux-kernel
The rtllib_rx_extract_addr() is supposed to set up the mac addresses
for four possible cases, based on two bits of input data. For
some reason, gcc decides that it's possible that none of the these
four cases apply and the addresses remain uninitialized:
drivers/staging/rtl8192e/rtllib_rx.c: In function ‘rtllib_rx_InfraAdhoc’:
include/linux/etherdevice.h:316:61: error: ‘*((void *)&dst+4)’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
drivers/staging/rtl8192e/rtllib_rx.c:1318:5: note: ‘*((void *)&dst+4)’ was declared here
ded from /git/arm-soc/drivers/staging/rtl8192e/rtllib_rx.c:40:0:
include/linux/etherdevice.h:316:36: error: ‘dst’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
drivers/staging/rtl8192e/rtllib_rx.c:1318:5: note: ‘dst’ was declared here
This warning is clearly nonsense, but changing the last case into
'default' makes it obvious to the compiler too, which avoids the
warning and probably leads to better object code too.
As the same warning appears in other files that have the exact
same code, I'm fixing it in both rtl8192e and rtl8192u, even
though I did not observe it for the latter.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/staging/rtl8192e/rtllib_rx.c | 2 +-
drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 2 +-
drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index c743182b933e..d6777ecda64d 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -986,7 +986,7 @@ static void rtllib_rx_extract_addr(struct rtllib_device *ieee,
ether_addr_copy(src, hdr->addr4);
ether_addr_copy(bssid, ieee->current_network.bssid);
break;
- case 0:
+ default:
ether_addr_copy(dst, hdr->addr1);
ether_addr_copy(src, hdr->addr2);
ether_addr_copy(bssid, hdr->addr3);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index 6fa96d57d316..e68850897adf 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -553,7 +553,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
break;
- case 0:
+ default:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 89cbc077a48d..2e4d2d7bc2e7 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1079,7 +1079,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
memcpy(src, hdr->addr4, ETH_ALEN);
memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
break;
- case 0:
+ default:
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
memcpy(bssid, hdr->addr3, ETH_ALEN);
--
2.9.0
^ permalink raw reply related
* Re: Bayesian rate control
From: Dave Taht @ 2016-10-24 15:09 UTC (permalink / raw)
To: Björn Smedman, make-wifi-fast
Cc: linux-wireless, ath9k-devel@lists.ath9k.org
In-Reply-To: <CAGp19xcg1qCP3+JNbuiB7Hx=UjLN7KP55wVJT0sKV-iE12501A@mail.gmail.com>
On Sun, Oct 23, 2016 at 6:57 AM, Bj=C3=B6rn Smedman <bjorn@openias.org> wro=
te:
> Hi all,
>
> I've been thinking about rate control a bit lately. I've written up
> some of my thoughts in a blog post
> (http://www.openias.org/bayesian-wifi-rate-control), but very briefly
It is nice to see some newer thinking here.
> put I'd like to build a rate control algorithm based on Bayesian
> statistical inference, possibly by modeling the rate control problem
> as a "multi-armed bandit" problem and/or using Thompson sampling.
The paper on minstrel's design was never widely published. I linked to it h=
ere:
http://blog.cerowrt.org/post/minstrel/
Looking harder at rate control has long been on my todo list, but at
the top of my list to finish first has been the fair queuing
(fq_codel) and airtime fairness work.
https://blog.tohojo.dk/2016/06/fixing-the-wifi-performance-anomaly-on-ath9k=
.html#results
http://blog.cerowrt.org/post/real_results
Once you are statistically hitting more stations, more often, on a
more regular basis, with smaller txops, I felt that many things that
were perceived as rate control problems would go away, and other
things become easier.
A basic "fix" to minstrel is to opportunistically sample (which so far
as I know, minstrel-blues does), rather than at a fixed rate.
btw: I called my early (unpublished) attempt at a "minstrel-2", "bard". :)
The now-enormous search space is a big problem in present-day
minstrel, followed by excessive retries/latency when sampling, and
hidden stations are becoming more and more of a problem as densities
go up. (long list of minstrel issues on that first link I posted
above).
> A couple of questions for the list:
>
> 1. Is there anybody else out there thinking along similar lines?
Yes and no. At the moment I am thinking about the insights from the
TCP "BBR" work google just published: (paywalled but at:
http://queue.acm.org/app/ ) where they also point to max-plus algebra
as being helpful for solving the problems it had.
> I'd very much like to find collaborators interested in working on
> this. It coruld serve as a pretty nice masters thesis problem, for
> example.
Please join us over on the make-wifi-fast list. There are more than a
few good papers to be had out of it.
>
> 2. What would be the best hardware/software stack to base this work on?
Presently ath9k is the only game in town, and developing/debugging on
x86 is the easiest.
> I'm thinking the best driver for rate control experimentation would be
> ath9k, right? If so then a TP-Link TL-WA901ND router (apparently based
> on Qualcomm QCA956x SOC) with OpenWrt, and a TP-Link TL-WDN4800 PCIe
> card (apparently based on Atheros AR9380 with PCI ID 168c:0030) for my
> desktop sounds like a good combo, no? But would I have to run a custom
> kernel on my desktop then (or can I somehow get by with an Ubuntu
> standard kernel)?
These days I am using a pcengines apu2 as my primary x86 testbed, with
ath9k and ath10k cards in it (and one day mt72). The new turris omnia
looks like a good platform also. I've been trying to use stuff newer
than AR92xx there.
Another box I really like is the ubnt uap-lite.
Prior to all those, it was the wndr3800, archer c7v2, and nanostation
m5s for outdoor work.
>
> Any other thoughts or pointers are also more than welcome.
>
> Many thanks,
>
> Bj=C3=B6rn Smedman
--=20
Dave T=C3=A4ht
Let's go make home routers and wifi faster! With better software!
http://blog.cerowrt.org
^ permalink raw reply
* RE: cfg80211: race problem between suspend and disconnect event
From: Amitkumar Karwar @ 2016-10-24 14:54 UTC (permalink / raw)
To: Johannes Berg
Cc: Kalle Valo, Brian Norris, Nishant Sarmukadam, Cathy Luo,
linux-wireless@vger.kernel.org, Ganapathi Bhat
In-Reply-To: <1477085053.4068.65.camel@sipsolutions.net>
SGkgSm9oYW5uZXMsDQoNCj4gRnJvbTogSm9oYW5uZXMgQmVyZyBbbWFpbHRvOmpvaGFubmVzQHNp
cHNvbHV0aW9ucy5uZXRdDQo+IFNlbnQ6IFNhdHVyZGF5LCBPY3RvYmVyIDIyLCAyMDE2IDI6NTQg
QU0NCj4gVG86IEFtaXRrdW1hciBLYXJ3YXINCj4gQ2M6IEthbGxlIFZhbG87IEJyaWFuIE5vcnJp
czsgTmlzaGFudCBTYXJtdWthZGFtOyBDYXRoeSBMdW87IGxpbnV4LQ0KPiB3aXJlbGVzc0B2Z2Vy
Lmtlcm5lbC5vcmc7IEdhbmFwYXRoaSBCaGF0DQo+IFN1YmplY3Q6IFJlOiBjZmc4MDIxMTogcmFj
ZSBwcm9ibGVtIGJldHdlZW4gc3VzcGVuZCBhbmQgZGlzY29ubmVjdCBldmVudA0KPiANCj4gDQo+
ID4gWWVzLiBJbiBvdXIgY2FzZSwgKjgwMl8xMV9ERUFVVEhFTlRJQ0FURSBjb21tYW5kIGRvd25s
b2FkZWQgdG8NCj4gPiBmaXJtd2FyZSB0YWtlcyBjYXJlIG9mIGZsdXNoaW5nIHRoZSBrZXlzLg0K
PiA+DQo+ID4gSSBjYW4gc2VlIGJlbG93IGNvZGUgaW4gY2ZnODAyMTEncyBkaXNjb25uZWN0IGhh
bmRsaW5nLiBJdCBzZWVtcyB0byBiZQ0KPiA+IHRoZXJlIGZvciBsb25nIHRpbWUuDQo+IA0KPiBZ
ZWFoLCBJIHNhdyBpdCwgYnV0IGl0J3Mgbm90IGNsZWFyIHRvIG1lIHRoYXQgdGhlcmUncyBtdWNo
IHBvaW50IGluIGl0Lg0KPiBJbiBhbnkgY2FzZSwgdGhhdCdzIGFuIHVucmVsYXRlZCBxdWVzdGlv
biBpbiBhIHdheSwgYmVjYXVzZSB0aGVyZQ0KPiBkZWZpbml0ZWx5IGFyZSB0aGluZ3MgaGFwcGVu
aW5nIGhlcmUgdGhhdCBzaG91bGQgYmUgIm1vcmUgc3luY2hyb25vdXMiLA0KPiByZWdhcmRsZXNz
IG9mIHdoZXRoZXIgb3Igbm90IHRoZSBrZXkgZGVsZXRpb24gbWFrZXMgc2Vuc2UuDQo+IA0KPiA+
IEkgdGhpbmssIHlvdXIgY2ZnODAyMTEgY2hhbmdlIHdpbGwgaGVscC4gV2UgZG8gZW5zdXJlIHRo
YXQNCj4gPiBjZmc4MDIxMV9kaXNjb25uZWN0ZWQoKSBpcyBjYWxsZWQgYmVmb3JlIGV4aXRpbmcN
Cj4gPiBtd2lmaWV4X2NmZzgwMjExX2Rpc2Nvbm5lY3QoKS4NCj4gPiBTZW5kaW5nIEhvc3RDbWRf
Q01EXzgwMl8xMV9ERUFVVEhFTlRJQ0FURSBjb21tYW5kIHRvIGZpcm13YXJlIGlzIGENCj4gPiBi
bG9ja2luZyBjYWxsLiBjZmc4MDIxMV9kaXNjb25uZWN0ZWQoKSBpcyBjYWxsZWQgd2hpbGUgaGFu
ZGxpbmcgdGhhdA0KPiA+IGNvbW1hbmQncyByZXNwb25zZS4NCj4gDQo+IEFoIG9rLCBJIG1pc3Nl
ZCB0aGF0IC0gSSB0aG91Z2h0IGl0IHdhcyBhc3luY2hyb25vdXMuDQo+IA0KPiA+ID4gU28gc29t
ZWhvdyB5b3UnZCBoYXZlIHRvIHN5bmNocm9uaXplIHdpdGggdGhlIGZpcm13YXJlIGFzIHdlbGws
IHRvDQo+ID4gPiBwcm9jZXNzIGFsbCB0aG9zZSB0aGluZ3MgYmVmb3JlIHN1c3BlbmQsIEkgZ3Vl
c3M/DQo+ID4gPg0KPiBbLi4uXQ0KPiA+IFRoaXMgd291bGQgbm90IGJlIG5lZWRlZC4NCj4gDQo+
IFJpZ2h0LiBDYXJlIHRvIHRlc3QgbXkgcGF0Y2ggYmVmb3JlIEkgcHJvcGVybHkgc3VibWl0IGl0
Pw0KDQpXZSByYW4gdGhlIHRlc3RzIGFuZCBjb25maXJtZWQgdGhhdCB5b3VyIHBhdGNoIGRvZXMg
c29sdmUgdGhlIHByb2JsZW0uIFlvdSBjYW4gc3VibWl0IGl0Lg0KDQpSZWdhcmRzLA0KQW1pdGt1
bWFyDQo=
^ permalink raw reply
* Re: [PATCH v2 2/2] mac80211: passively scan DFS channels if requested
From: Simon Wunderlich @ 2016-10-24 14:53 UTC (permalink / raw)
To: Johannes Berg; +Cc: Antonio Quartulli, linux-wireless
In-Reply-To: <1477319916.4085.29.camel@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 2824 bytes --]
On Monday, October 24, 2016 4:38:36 PM CEST Johannes Berg wrote:
> On Mon, 2016-10-24 at 16:36 +0200, Simon Wunderlich wrote:
> > On Monday, October 24, 2016 4:16:02 PM CEST Johannes Berg wrote:
> > > On Mon, 2016-10-24 at 15:42 +0200, Simon Wunderlich wrote:
> > > > Otherwise, it would be pretty much impossible to perform CSAs to
> > > > another DFS channel.
> > >
> > > I was told that to do that you'd need another NIC that's pre-
> > > CAC'ing another channel.
> >
> > Here is the portion from ETSI 301 893 v1.8.1 [1] (the most recent one
> > to my knowledege), section 4.7.1.4 which describes operation from
> >
> > master devices (Access Points):
> > [...]
>
> Yeah I'm pretty sure there are differences in ETSI vs. FCC. Perhaps the
> information I was told about was for FCC. But perhaps it's all just
> completely wrong :)
I think I've found the right specification [1] for FCC. They doesn't state so
explicitly that it is allowed, but I don't see any remark that this behaviour
is forbidden, either. The important section is 5.1.1 Master devices in 905462
D02 UNII DFS Compliance Procedures New Rules v02, which is pretty similar to
ETSI. They say:
<snip>
a)
The Master Device will use DFS in order to detect Radar Waveforms with
received signal strength above the DFS Detection Threshold in the 5250 - 5350
MHz and 5470 - 5725 MHz bands. DFS is not required in the 5150 - 5250 MHz or
5725 - 5825 MHz bands.
b)
Before initiating a network on a Channel, the Master Device will perform a
Channel Availability Check for a specified time duration (Channel Availability
Check Time) to ensure that there is no radar system operating on the
Channel, using DFS described under subsection a) above.
c) The Master Device initiates a U-NII network by transmitting control
signals that will enable other U-NII devices to Associate with the Master
Device.
d)
During normal operation, the Master Device will monitor the Channel
(In-Service Monitoring) to ensure that there is no radar system operating on
the Channel, using DFS described under a).
e)
If the Master Device has detected a Radar Waveform during In-Service
Monitoring as described under d), the Operating Channel of the U-
NII network is no longer an Available Channel. The Master Device will
instruct all associated Client Device(s) to stop transmitting on this
Channel within the Channel Move Time. The transmissions during the
Channel Move Time will be limited to the Channel Closing Transmission
Time.
</snap>
Again, no explicit "on installation" here, but there is also nothing saying
that we can not check/operate on other channels in the meantime. (NOTE: going
off-channel while operating is a different topic).
Cheers,
Simon
[1] https://apps.fcc.gov/oetcf/kdb/forms/FTSSearchResultPage.cfm?
switch=P&id=27155
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/2] mac80211: passively scan DFS channels if requested
From: Johannes Berg @ 2016-10-24 14:38 UTC (permalink / raw)
To: Simon Wunderlich; +Cc: Antonio Quartulli, linux-wireless
In-Reply-To: <4116422.yZP7iyh9mq@prime>
On Mon, 2016-10-24 at 16:36 +0200, Simon Wunderlich wrote:
> On Monday, October 24, 2016 4:16:02 PM CEST Johannes Berg wrote:
> >
> > On Mon, 2016-10-24 at 15:42 +0200, Simon Wunderlich wrote:
> > >
> > > Otherwise, it would be pretty much impossible to perform CSAs to
> > > another DFS channel.
> >
> > I was told that to do that you'd need another NIC that's pre-
> > CAC'ing another channel.
>
> Here is the portion from ETSI 301 893 v1.8.1 [1] (the most recent one
> to my knowledege), section 4.7.1.4 which describes operation from
> master devices (Access Points):
> [...]
Yeah I'm pretty sure there are differences in ETSI vs. FCC. Perhaps the
information I was told about was for FCC. But perhaps it's all just
completely wrong :)
johannes
^ permalink raw reply
* Re: [PATCH v2 2/2] mac80211: passively scan DFS channels if requested
From: Simon Wunderlich @ 2016-10-24 14:36 UTC (permalink / raw)
To: Johannes Berg; +Cc: Antonio Quartulli, linux-wireless
In-Reply-To: <1477318562.4085.28.camel@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 2513 bytes --]
On Monday, October 24, 2016 4:16:02 PM CEST Johannes Berg wrote:
> On Mon, 2016-10-24 at 15:42 +0200, Simon Wunderlich wrote:
> > Otherwise, it would be pretty much impossible to perform CSAs to
> > another DFS channel.
>
> I was told that to do that you'd need another NIC that's pre-CAC'ing
> another channel.
Here is the portion from ETSI 301 893 v1.8.1 [1] (the most recent one to my
knowledege), section 4.7.1.4 which describes operation from master devices
(Access Points):
<snip>
b) A master device shall only start operations on Available Channels. At
installation (or reinstallation) of the equipment, the RLAN is assumed to have
no Available Channels within the band 5 250 MHz to 5 350 MHz and/or 5 470 MHz
to 5 725 MHz. In such a case, before starting operations on one or more of
these channels, the master device shall perform either a Channel Availability
Check or an Off-Channel CAC to ensure that there are no radars operating on
any selected channel. If no radar has been detected, the channel(s) becomes an
Available Channel(s) and remains as such until a radar signal is detected
during the In-Service Monitoring.
The Channel Availability Check or the Off-Channel CAC may be performed over a
wider bandwidth such that all channels within the tested bandwidth become
Available Channels.
NOTE 1:The initial Channel Availability Check may be activated manually at
installation or reinstallation of the equipment.
c) Once the RLAN has started operations on an Available Channel, then that
channel becomes an Operating Channel. During normal operation, the master
device shall monitor all Operating Channels (In-Service Monitoring) to ensure
that there is no radar operating within these channel(s). If no radar was
detected on an Operating Channel but the RLAN stops operating on that channel,
then the channel becomes an Available Channel.
NOTE 2:An RLAN is allowed to start transmissions on multiple (adjacent or non-
adjacent) Available Channels. In this case all these channels become Operating
Channels.
<snap>
As I interpret this, (b) states explicitly that we can have many available
channels. We only need to mark channels where we detect a radar.
BTW, there was also something like a 24h disconnect previously, which was
removed in 2009 [2].
Cheers,
Simon
[1] http://www.etsi.org/deliver/etsi_en/301800_301899/301893/01.08.01_60/
en_301893v010801p.pdf
[2] http://www.wlan-skynet.de/docs/rechtliches/etsi_301_893.shtml (german
only)
>
> johannes
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH 5/5] mwifiex: wait for firmware dump completion in remove_card
From: Amitkumar Karwar @ 2016-10-24 14:21 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, dmitry.torokhov, briannorris,
Xinming Hu, Amitkumar Karwar
In-Reply-To: <1477318892-22877-1-git-send-email-akarwar@marvell.com>
From: Xinming Hu <huxm@marvell.com>
This patch ensures to wait for firmware dump completion in
mwifiex_remove_card().
For sdio interface, reset_trigger variable is used to identify
if mwifiex_sdio_remove() is called by sdio_work during reset or
the call is from sdio subsystem.
This patch fixes a kernel crash observed during reboot when firmware
dump operation is in process.
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 2 ++
drivers/net/wireless/marvell/mwifiex/sdio.c | 15 ++++++++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 986bf07..4512e86 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -528,6 +528,8 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
if (!adapter || !adapter->priv_num)
return;
+ cancel_work_sync(&pcie_work);
+
if (user_rmmod && !adapter->mfg_mode) {
#ifdef CONFIG_PM_SLEEP
if (adapter->is_suspended)
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 4cad1c2..f974260 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -46,6 +46,15 @@
*/
static u8 user_rmmod;
+/* reset_trigger variable is used to identify if mwifiex_sdio_remove()
+ * is called by sdio_work during reset or the call is from sdio subsystem.
+ * We will cancel sdio_work only if the call is from sdio subsystem.
+ */
+static u8 reset_triggered;
+
+static void mwifiex_sdio_work(struct work_struct *work);
+static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
+
static struct mwifiex_if_ops sdio_ops;
static unsigned long iface_work_flags;
@@ -289,6 +298,9 @@ mwifiex_sdio_remove(struct sdio_func *func)
if (!adapter || !adapter->priv_num)
return;
+ if (!reset_triggered)
+ cancel_work_sync(&sdio_work);
+
mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
if (user_rmmod && !adapter->mfg_mode) {
@@ -2290,7 +2302,9 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
* discovered and initializes them from scratch.
*/
+ reset_triggered = 1;
mwifiex_sdio_remove(func);
+ reset_triggered = 0;
/* power cycle the adapter */
sdio_claim_host(func);
@@ -2621,7 +2635,6 @@ static void mwifiex_sdio_work(struct work_struct *work)
mwifiex_sdio_card_reset_work(save_adapter);
}
-static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
/* This function resets the card */
static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
{
--
1.9.1
^ permalink raw reply related
* [PATCH 4/5] mwifiex: firmware dump code rearrangement in pcie.c
From: Amitkumar Karwar @ 2016-10-24 14:21 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, dmitry.torokhov, briannorris,
Xinming Hu, Amitkumar Karwar
In-Reply-To: <1477318892-22877-1-git-send-email-akarwar@marvell.com>
From: Xinming Hu <huxm@marvell.com>
The next patch will refer to pcie_work in mwifiex_pcie_remove function.
This patch puts pcie_work related functions ahead to mwifiex_pcie_remove
to avoid static forward declaration.
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 590 ++++++++++++++--------------
1 file changed, 294 insertions(+), 296 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 9147e6a..986bf07 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -65,6 +65,42 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
}
/*
+ * This function writes data into PCIE card register.
+ */
+static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ iowrite32(data, card->pci_mmap1 + reg);
+
+ return 0;
+}
+
+/* This function reads data from PCIE card register.
+ */
+static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ *data = ioread32(card->pci_mmap1 + reg);
+ if (*data == 0xffffffff)
+ return 0xffffffff;
+
+ return 0;
+}
+
+/* This function reads u8 data from PCIE card register. */
+static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
+ int reg, u8 *data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ *data = ioread8(card->pci_mmap1 + reg);
+
+ return 0;
+}
+
+/*
* This function reads sleep cookie and checks if FW is ready
*/
static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
@@ -88,6 +124,249 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
return false;
}
+/* Function to dump PCIE scratch registers in case of FW crash
+ */
+static int
+mwifiex_pcie_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
+{
+ char *p = drv_buf;
+ char buf[256], *ptr;
+ int i;
+ u32 value;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ int pcie_scratch_reg[] = {PCIE_SCRATCH_12_REG,
+ PCIE_SCRATCH_13_REG,
+ PCIE_SCRATCH_14_REG};
+
+ if (!p)
+ return 0;
+
+ mwifiex_dbg(adapter, MSG, "PCIE register dump start\n");
+
+ if (mwifiex_read_reg(adapter, reg->fw_status, &value)) {
+ mwifiex_dbg(adapter, ERROR, "failed to read firmware status");
+ return 0;
+ }
+
+ ptr = buf;
+ mwifiex_dbg(adapter, MSG, "pcie scratch register:");
+ for (i = 0; i < ARRAY_SIZE(pcie_scratch_reg); i++) {
+ mwifiex_read_reg(adapter, pcie_scratch_reg[i], &value);
+ ptr += sprintf(ptr, "reg:0x%x, value=0x%x\n",
+ pcie_scratch_reg[i], value);
+ }
+
+ mwifiex_dbg(adapter, MSG, "%s\n", buf);
+ p += sprintf(p, "%s\n", buf);
+
+ mwifiex_dbg(adapter, MSG, "PCIE register dump end\n");
+
+ return p - drv_buf;
+}
+
+/* This function read/write firmware */
+static enum rdwr_status
+mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
+{
+ int ret, tries;
+ u8 ctrl_data;
+ u32 fw_status;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+ if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status))
+ return RDWR_STATUS_FAILURE;
+
+ ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
+ reg->fw_dump_host_ready);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR,
+ "PCIE write err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
+ if (ctrl_data == FW_DUMP_DONE)
+ return RDWR_STATUS_SUCCESS;
+ if (doneflag && ctrl_data == doneflag)
+ return RDWR_STATUS_DONE;
+ if (ctrl_data != reg->fw_dump_host_ready) {
+ mwifiex_dbg(adapter, WARN,
+ "The ctrl reg was changed, re-try again!\n");
+ ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
+ reg->fw_dump_host_ready);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR,
+ "PCIE write err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+ }
+ usleep_range(100, 200);
+ }
+
+ mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
+ return RDWR_STATUS_FAILURE;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
+ unsigned int reg, reg_start, reg_end;
+ u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num;
+ u8 idx, i, read_reg, doneflag = 0;
+ enum rdwr_status stat;
+ u32 memory_size;
+ int ret;
+
+ if (!card->pcie.can_dump_fw)
+ return;
+
+ for (idx = 0; idx < adapter->num_mem_types; idx++) {
+ struct memory_type_mapping *entry =
+ &adapter->mem_type_mapping_tbl[idx];
+
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+ }
+
+ mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
+
+ /* Read the number of the memories which will dump */
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ return;
+
+ reg = creg->fw_dump_start;
+ mwifiex_read_reg_byte(adapter, reg, &fw_dump_num);
+
+ /* W8997 chipset firmware dump will be restore in single region*/
+ if (fw_dump_num == 0)
+ dump_num = 1;
+ else
+ dump_num = fw_dump_num;
+
+ /* Read the length of every memory which will dump */
+ for (idx = 0; idx < dump_num; idx++) {
+ struct memory_type_mapping *entry =
+ &adapter->mem_type_mapping_tbl[idx];
+ memory_size = 0;
+ if (fw_dump_num != 0) {
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ return;
+
+ reg = creg->fw_dump_start;
+ for (i = 0; i < 4; i++) {
+ mwifiex_read_reg_byte(adapter, reg, &read_reg);
+ memory_size |= (read_reg << (i * 8));
+ reg++;
+ }
+ } else {
+ memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE;
+ }
+
+ if (memory_size == 0) {
+ mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
+ ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
+ creg->fw_dump_read_done);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
+ return;
+ }
+ break;
+ }
+
+ mwifiex_dbg(adapter, DUMP,
+ "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+ entry->mem_ptr = vmalloc(memory_size + 1);
+ entry->mem_size = memory_size;
+ if (!entry->mem_ptr)
+ return;
+
+ dbg_ptr = entry->mem_ptr;
+ end_ptr = dbg_ptr + memory_size;
+
+ doneflag = entry->done_flag;
+ mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
+ entry->mem_name);
+
+ do {
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ return;
+
+ reg_start = creg->fw_dump_start;
+ reg_end = creg->fw_dump_end;
+ for (reg = reg_start; reg <= reg_end; reg++) {
+ mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
+ if (dbg_ptr < end_ptr) {
+ dbg_ptr++;
+ continue;
+ }
+ mwifiex_dbg(adapter, ERROR,
+ "pre-allocated buf not enough\n");
+ tmp_ptr =
+ vzalloc(memory_size + MWIFIEX_SIZE_4K);
+ if (!tmp_ptr)
+ return;
+ memcpy(tmp_ptr, entry->mem_ptr, memory_size);
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = tmp_ptr;
+ tmp_ptr = NULL;
+ dbg_ptr = entry->mem_ptr + memory_size;
+ memory_size += MWIFIEX_SIZE_4K;
+ end_ptr = entry->mem_ptr + memory_size;
+ }
+
+ if (stat != RDWR_STATUS_DONE)
+ continue;
+
+ mwifiex_dbg(adapter, DUMP,
+ "%s done: size=0x%tx\n",
+ entry->mem_name, dbg_ptr - entry->mem_ptr);
+ break;
+ } while (true);
+ }
+ mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
+}
+
+static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
+{
+ mwifiex_drv_info_dump(adapter);
+ mwifiex_pcie_fw_dump(adapter);
+ mwifiex_upload_device_dump(adapter);
+}
+
+static unsigned long iface_work_flags;
+static struct mwifiex_adapter *save_adapter;
+static void mwifiex_pcie_work(struct work_struct *work)
+{
+ if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+ &iface_work_flags))
+ mwifiex_pcie_device_dump_work(save_adapter);
+}
+
+static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
+
+/* This function dumps FW information */
+static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
+{
+ save_adapter = adapter;
+ if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
+ return;
+
+ set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
+
+ schedule_work(&pcie_work);
+}
+
#ifdef CONFIG_PM_SLEEP
/*
* Kernel needs to suspend all functions separately. Therefore all
@@ -353,58 +632,21 @@ static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
mwifiex_pcie_resume);
#endif
-/* PCI Device Driver */
-static struct pci_driver __refdata mwifiex_pcie = {
- .name = "mwifiex_pcie",
- .id_table = mwifiex_ids,
- .probe = mwifiex_pcie_probe,
- .remove = mwifiex_pcie_remove,
-#ifdef CONFIG_PM_SLEEP
- .driver = {
- .pm = &mwifiex_pcie_pm_ops,
- },
-#endif
- .shutdown = mwifiex_pcie_shutdown,
- .err_handler = mwifiex_pcie_err_handler,
-};
-
-/*
- * This function writes data into PCIE card register.
- */
-static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
-{
- struct pcie_service_card *card = adapter->card;
-
- iowrite32(data, card->pci_mmap1 + reg);
-
- return 0;
-}
-
-/*
- * This function reads data from PCIE card register.
- */
-static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
-{
- struct pcie_service_card *card = adapter->card;
-
- *data = ioread32(card->pci_mmap1 + reg);
- if (*data == 0xffffffff)
- return 0xffffffff;
-
- return 0;
-}
-
-/* This function reads u8 data from PCIE card register. */
-static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
- int reg, u8 *data)
-{
- struct pcie_service_card *card = adapter->card;
-
- *data = ioread8(card->pci_mmap1 + reg);
-
- return 0;
-}
-
+/* PCI Device Driver */
+static struct pci_driver __refdata mwifiex_pcie = {
+ .name = "mwifiex_pcie",
+ .id_table = mwifiex_ids,
+ .probe = mwifiex_pcie_probe,
+ .remove = mwifiex_pcie_remove,
+#ifdef CONFIG_PM_SLEEP
+ .driver = {
+ .pm = &mwifiex_pcie_pm_ops,
+ },
+#endif
+ .shutdown = mwifiex_pcie_shutdown,
+ .err_handler = mwifiex_pcie_err_handler,
+};
+
/*
* This function adds delay loop to ensure FW is awake before proceeding.
*/
@@ -2482,250 +2724,6 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
return 0;
}
-/* Function to dump PCIE scratch registers in case of FW crash
- */
-static int
-mwifiex_pcie_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
-{
- char *p = drv_buf;
- char buf[256], *ptr;
- int i;
- u32 value;
- struct pcie_service_card *card = adapter->card;
- const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- int pcie_scratch_reg[] = {PCIE_SCRATCH_12_REG,
- PCIE_SCRATCH_13_REG,
- PCIE_SCRATCH_14_REG};
-
- if (!p)
- return 0;
-
- mwifiex_dbg(adapter, MSG, "PCIE register dump start\n");
-
- if (mwifiex_read_reg(adapter, reg->fw_status, &value)) {
- mwifiex_dbg(adapter, ERROR, "failed to read firmware status");
- return 0;
- }
-
- ptr = buf;
- mwifiex_dbg(adapter, MSG, "pcie scratch register:");
- for (i = 0; i < ARRAY_SIZE(pcie_scratch_reg); i++) {
- mwifiex_read_reg(adapter, pcie_scratch_reg[i], &value);
- ptr += sprintf(ptr, "reg:0x%x, value=0x%x\n",
- pcie_scratch_reg[i], value);
- }
-
- mwifiex_dbg(adapter, MSG, "%s\n", buf);
- p += sprintf(p, "%s\n", buf);
-
- mwifiex_dbg(adapter, MSG, "PCIE register dump end\n");
-
- return p - drv_buf;
-}
-
-/* This function read/write firmware */
-static enum rdwr_status
-mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
-{
- int ret, tries;
- u8 ctrl_data;
- u32 fw_status;
- struct pcie_service_card *card = adapter->card;
- const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
- if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status))
- return RDWR_STATUS_FAILURE;
-
- ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
- reg->fw_dump_host_ready);
- if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "PCIE write err\n");
- return RDWR_STATUS_FAILURE;
- }
-
- for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
- mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
- if (ctrl_data == FW_DUMP_DONE)
- return RDWR_STATUS_SUCCESS;
- if (doneflag && ctrl_data == doneflag)
- return RDWR_STATUS_DONE;
- if (ctrl_data != reg->fw_dump_host_ready) {
- mwifiex_dbg(adapter, WARN,
- "The ctrl reg was changed, re-try again!\n");
- ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
- reg->fw_dump_host_ready);
- if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "PCIE write err\n");
- return RDWR_STATUS_FAILURE;
- }
- }
- usleep_range(100, 200);
- }
-
- mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
- return RDWR_STATUS_FAILURE;
-}
-
-/* This function dump firmware memory to file */
-static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
-{
- struct pcie_service_card *card = adapter->card;
- const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
- unsigned int reg, reg_start, reg_end;
- u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num;
- u8 idx, i, read_reg, doneflag = 0;
- enum rdwr_status stat;
- u32 memory_size;
- int ret;
-
- if (!card->pcie.can_dump_fw)
- return;
-
- for (idx = 0; idx < adapter->num_mem_types; idx++) {
- struct memory_type_mapping *entry =
- &adapter->mem_type_mapping_tbl[idx];
-
- if (entry->mem_ptr) {
- vfree(entry->mem_ptr);
- entry->mem_ptr = NULL;
- }
- entry->mem_size = 0;
- }
-
- mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
-
- /* Read the number of the memories which will dump */
- stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
- if (stat == RDWR_STATUS_FAILURE)
- return;
-
- reg = creg->fw_dump_start;
- mwifiex_read_reg_byte(adapter, reg, &fw_dump_num);
-
- /* W8997 chipset firmware dump will be restore in single region*/
- if (fw_dump_num == 0)
- dump_num = 1;
- else
- dump_num = fw_dump_num;
-
- /* Read the length of every memory which will dump */
- for (idx = 0; idx < dump_num; idx++) {
- struct memory_type_mapping *entry =
- &adapter->mem_type_mapping_tbl[idx];
- memory_size = 0;
- if (fw_dump_num != 0) {
- stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
- if (stat == RDWR_STATUS_FAILURE)
- return;
-
- reg = creg->fw_dump_start;
- for (i = 0; i < 4; i++) {
- mwifiex_read_reg_byte(adapter, reg, &read_reg);
- memory_size |= (read_reg << (i * 8));
- reg++;
- }
- } else {
- memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE;
- }
-
- if (memory_size == 0) {
- mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
- ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
- creg->fw_dump_read_done);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
- return;
- }
- break;
- }
-
- mwifiex_dbg(adapter, DUMP,
- "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
- entry->mem_ptr = vmalloc(memory_size + 1);
- entry->mem_size = memory_size;
- if (!entry->mem_ptr) {
- mwifiex_dbg(adapter, ERROR,
- "Vmalloc %s failed\n", entry->mem_name);
- return;
- }
- dbg_ptr = entry->mem_ptr;
- end_ptr = dbg_ptr + memory_size;
-
- doneflag = entry->done_flag;
- mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
- entry->mem_name);
-
- do {
- stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
- if (RDWR_STATUS_FAILURE == stat)
- return;
-
- reg_start = creg->fw_dump_start;
- reg_end = creg->fw_dump_end;
- for (reg = reg_start; reg <= reg_end; reg++) {
- mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
- if (dbg_ptr < end_ptr) {
- dbg_ptr++;
- continue;
- }
- mwifiex_dbg(adapter, ERROR,
- "pre-allocated buf not enough\n");
- tmp_ptr =
- vzalloc(memory_size + MWIFIEX_SIZE_4K);
- if (!tmp_ptr)
- return;
- memcpy(tmp_ptr, entry->mem_ptr, memory_size);
- vfree(entry->mem_ptr);
- entry->mem_ptr = tmp_ptr;
- tmp_ptr = NULL;
- dbg_ptr = entry->mem_ptr + memory_size;
- memory_size += MWIFIEX_SIZE_4K;
- end_ptr = entry->mem_ptr + memory_size;
- }
-
- if (stat != RDWR_STATUS_DONE)
- continue;
-
- mwifiex_dbg(adapter, DUMP,
- "%s done: size=0x%tx\n",
- entry->mem_name, dbg_ptr - entry->mem_ptr);
- break;
- } while (true);
- }
- mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
-}
-
-static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
-{
- mwifiex_drv_info_dump(adapter);
- mwifiex_pcie_fw_dump(adapter);
- mwifiex_upload_device_dump(adapter);
-}
-
-static unsigned long iface_work_flags;
-static struct mwifiex_adapter *save_adapter;
-static void mwifiex_pcie_work(struct work_struct *work)
-{
- if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
- &iface_work_flags))
- mwifiex_pcie_device_dump_work(save_adapter);
-}
-
-static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
-/* This function dumps FW information */
-static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
-{
- save_adapter = adapter;
- if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
- return;
-
- set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
-
- schedule_work(&pcie_work);
-}
-
/*
* This function initializes the PCI-E host memory space, WCB rings, etc.
*
--
1.9.1
^ permalink raw reply related
* [PATCH 3/5] mwifiex: do not free firmware dump memory in shutdown_drv
From: Amitkumar Karwar @ 2016-10-24 14:21 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, dmitry.torokhov, briannorris,
Xinming Hu, Amitkumar Karwar
In-Reply-To: <1477318892-22877-1-git-send-email-akarwar@marvell.com>
From: Xinming Hu <huxm@marvell.com>
mwifiex_upload_device_dump() already takes care of freeing firmware dump
memory. Doing the same thing in mwifiex_shutdown_drv() is redundant.
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
drivers/net/wireless/marvell/mwifiex/init.c | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 8e5e424..365efb8 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -407,8 +407,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
static void
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
- int idx;
-
if (!adapter) {
pr_err("%s: adapter is NULL\n", __func__);
return;
@@ -426,23 +424,6 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
mwifiex_free_cmd_buffer(adapter);
- for (idx = 0; idx < adapter->num_mem_types; idx++) {
- struct memory_type_mapping *entry =
- &adapter->mem_type_mapping_tbl[idx];
-
- if (entry->mem_ptr) {
- vfree(entry->mem_ptr);
- entry->mem_ptr = NULL;
- }
- entry->mem_size = 0;
- }
-
- if (adapter->drv_info_dump) {
- vfree(adapter->drv_info_dump);
- adapter->drv_info_dump = NULL;
- adapter->drv_info_size = 0;
- }
-
if (adapter->sleep_cfm)
dev_kfree_skb_any(adapter->sleep_cfm);
}
--
1.9.1
^ permalink raw reply related
* [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Amitkumar Karwar @ 2016-10-24 14:21 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, dmitry.torokhov, briannorris,
Amitkumar Karwar
In-Reply-To: <1477318892-22877-1-git-send-email-akarwar@marvell.com>
This variable is guarded by spinlock at all other places. This patch
takes care of missing spinlock usage in mwifiex_shutdown_drv().
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
drivers/net/wireless/marvell/mwifiex/init.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 82839d9..8e5e424 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -670,11 +670,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
/* wait for mwifiex_process to complete */
+ spin_lock_irqsave(&adapter->main_proc_lock, flags);
if (adapter->mwifiex_processing) {
+ spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
mwifiex_dbg(adapter, WARN,
"main process is still running\n");
return ret;
}
+ spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
/* cancel current command */
if (adapter->curr_cmd) {
--
1.9.1
^ 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