Linux wireless drivers development
 help / color / mirror / Atom feed
* [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 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

* 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

* 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: [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: 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: 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: [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: [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 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 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Brian Norris @ 2016-10-24 23:55 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Amitkumar Karwar, linux-wireless, Cathy Luo, Nishant Sarmukadam,
	briannorris
In-Reply-To: <20161024234720.GB15034@dtor-ws>

Hi,

On Mon, Oct 24, 2016 at 04:47:20PM -0700, Dmitry Torokhov wrote:
> 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?

That's why I commented:

"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?"

I think the answer is, we really better NOT see that become true. That
means that we've fired off more interrupts and began processing them.
But all callers should have disabled interrupts and stopped or flushed
the queue at this point, AFAICT.

So I expect the intention here is to be essentially an assert(), without
actually making it fatal. Maybe there's a better way to handle this? I
can't really think of a good one right now.

Brian

> >  
> >  	/* cancel current command */
> >  	if (adapter->curr_cmd) {
> > -- 
> > 1.9.1
> > 
> 
> -- 
> Dmitry

^ permalink raw reply

* Re: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Dmitry Torokhov @ 2016-10-24 23:57 UTC (permalink / raw)
  To: Brian Norris
  Cc: Amitkumar Karwar, linux-wireless, Cathy Luo, Nishant Sarmukadam
In-Reply-To: <20161024191914.GB968@localhost>

On Mon, Oct 24, 2016 at 12:19:15PM -0700, Brian Norris wrote:
> 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:

No, this is definitely not right way to check it. What exactly does this
spinlock protect? It seems that the intent is to make sure we do not
call mwifiex_shutdown_drv() while mwifiex_main_process() is executing.
It even says above that we are "waiting" for it (but we do not, we may
bail out or we may not, depends on luck).

To implement this properly you not only need to take a lock and check
the flag, but keep the lock until mwifiex_shutdown_drv() is done, or
use some other way to let mwifiex_main_process() know it should not
access the adapter while mwifiex_shutdown_drv() is running.

NACK.

Thanks.

> 
> 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
> > 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH 5/5] mwifiex: wait for firmware dump completion in remove_card
From: Dmitry Torokhov @ 2016-10-25  0:14 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, briannorris,
	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);
> +
>  	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;

It would be really great if the driver supported multiple devices. IOW
please avoid module-globals.

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

What exactly happens if I trigger mwifiex_sdio_remove() from sysfs at
the same time this code is running?

>  
>  	/* 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
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH 3/5] mwifiex: do not free firmware dump memory in shutdown_drv
From: Dmitry Torokhov @ 2016-10-25  0:17 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, 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>
> ---
>  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;
> -	}

Why do you even keep the pointer to dump memory in the adapter
structure? You allocate it in mwifiex_drv_info_dump() and immediately
use it in mwifiex_upload_device_dump(). Why not simply pass the pointer
between the functions?

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v4 1/3] mwifiex: reset card->adapter during device unregister
From: Brian Norris @ 2016-10-25  0:51 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
	rajatja@google.com, Xinming Hu, abhishekbh@google.com,
	Dmitry Torokhov
In-Reply-To: <b1231f275ecc4e45a9c98dadb1d585f1@SC-EXCH04.marvell.com>

Hi Amit,

On Thu, Oct 20, 2016 at 01:11:31PM +0000, Amitkumar Karwar wrote:
> > From: Brian Norris [mailto:briannorris@chromium.org]
> > Sent: Tuesday, October 11, 2016 5:53 AM
> > To: Amitkumar Karwar
> > Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> > rajatja@google.com; Xinming Hu; abhishekbh@google.com; Dmitry Torokhov
> > Subject: Re: [PATCH v4 1/3] mwifiex: reset card->adapter during device
> > unregister
> > 
> > On Mon, Oct 10, 2016 at 01:53:32PM -0700, Brian Norris wrote:
> > > On Thu, Oct 06, 2016 at 11:36:24PM +0530, Amitkumar Karwar wrote:
> > > > From: Xinming Hu <huxm@marvell.com>
> > > >
> > > > card->adapter gets initialized during device registration.
> > > > As it's not cleared, we may end up accessing invalid memory in some
> > > > corner cases. This patch fixes the problem.
> > > >
> > > > Signed-off-by: Xinming Hu <huxm@marvell.com>
> > > > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> > > > ---
> > > > v4: Same as v1, v2, v3
> > > > ---
> > > >  drivers/net/wireless/marvell/mwifiex/pcie.c | 1 +
> > > > drivers/net/wireless/marvell/mwifiex/sdio.c | 1 +
> > > >  2 files changed, 2 insertions(+)
> > > >
> > > > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > index f1eeb73..ba9e068 100644
> > > > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > @@ -3042,6 +3042,7 @@ static void mwifiex_unregister_dev(struct
> > mwifiex_adapter *adapter)
> > > >  				pci_disable_msi(pdev);
> > > >  	       }
> > > >  	}
> > > > +	card->adapter = NULL;
> > > >  }
> > > >
> > > >  /* This function initializes the PCI-E host memory space, WCB
> > rings, etc.
> > > > diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > index 8718950..4cad1c2 100644
> > > > --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > @@ -2066,6 +2066,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter
> > *adapter)
> > > >  	struct sdio_mmc_card *card = adapter->card;
> > > >
> > > >  	if (adapter->card) {
> > > > +		card->adapter = NULL;
> > > >  		sdio_claim_host(card->func);
> > > >  		sdio_disable_func(card->func);
> > > >  		sdio_release_host(card->func);
> > >
> > > As discussed on v1, I had qualms about the raciness between
> > > reads/writes of card->adapter, but I believe we:
> > > (a) can't have any command activity while writing the ->adapter field
> > > (either we're just init'ing the device, or we've disabled interrupts
> > > and are tearing it down) and
> > > (b) can't have a race between suspend()/resume() and unregister_dev(),
> > > since unregister_dev() is called from device remove() (which should
> > > not be concurrent with suspend()).
> > >
> > > Also, I thought you had the same problem in usb.c, but in fact, you
> > > fixed that ages ago here:
> > >
> > > 353d2a69ea26 mwifiex: fix issues in driver unload path for USB
> > > chipsets
> > >
> > > Would be nice if fixes were bettery synchronized across the three
> > > interface drivers you support. We seem to be discovering unnecessary
> > > divergence on a few points recently.
> > >
> > > At any rate:
> > >
> > > Reviewed-by: Brian Norris <briannorris@chromium.org>
> > > Tested-by: Brian Norris <briannorris@chromium.org>
> > 
> > Dmitry helped me re-realize my original qualms:
> > 
> > mwifiex_unregister_dev() is called in the failure path for your async FW
> > request, and so it may race with suspend(). So I retract my Reviewed-by.
> > Sorry.
> 
> Thanks for your comments.
> 
> Actually description for this patch was ambiguous and incorrect. Sorry
> for that. This patch doesn't fix any race. In fact, we don't have a
> race between init and remove threads due to semaphore usage as per
> design. This patch just adds missing "card->adapter=NULL" so that when
> teardown/remove thread starts after init failure, it won't try freeing
> already freed things.

So to be clear, you'r talking about mwifiex_fw_dpc(), which in the error path
has:

       if (adapter->if_ops.unregister_dev)
                adapter->if_ops.unregister_dev(adapter); <--- POINT A: This is where you want to set ->adapter = NULL
...
        if (init_failed)
                mwifiex_free_adapter(adapter);
        up(sem); <--- POINT B: This is where you release the semaphore, which is supposed to guarantee that remove() isn't happening
        return;
}

But you *do* have a race between the above code and the remove code in some
cases. Particularly, see this:

static void mwifiex_pcie_remove(struct pci_dev *pdev)
{
        struct pcie_service_card *card;
        struct mwifiex_adapter *adapter;
        struct mwifiex_private *priv;
        
        card = pci_get_drvdata(pdev);
        if (!card)
                return;

        adapter = card->adapter; <--- POINT C: This can execute at the same time as unregister_dev()
        if (!adapter || !adapter->priv_num)
                return;

        if (user_rmmod && !adapter->mfg_mode) {
#ifdef CONFIG_PM_SLEEP
                if (adapter->is_suspended)
                        mwifiex_pcie_resume(&pdev->dev);
#endif

                mwifiex_deauthenticate_all(adapter);

                priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);

                mwifiex_disable_auto_ds(priv);

                mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
        }

        mwifiex_remove_card(card->adapter, &add_remove_card_sem); <--- POINT D: You only grab the semaphore here
}

So IIUC, you have a race **even here, where you claim the semaphore
should protect you** such that the adapter might be freed, but you still
can access it anywhere between C and D. i.e., you can see this:

Thread 1                              Thread 2
                                      (1) POINT C (retrieve adapter != NULL)
(2) POINT A (set adapter NULL)
(3) POINT B (adapter has been freed)
                                      (3) ....Keep accessing freed adapter structure
                                      (4) POINT D - acquire semaphore, but we're too late

Step 3 is an error, and AFAICT, that's exactly what you're trying to
solve in this patch. It essentially comes down to the same fact: you're
getting a reference to the adapter structure *without* any protection at
all. Your add_remove_card_sem is *almost* the right thing to resolve
this, but you still don't have the ordering quite right.

Maybe you could solve this all by acquiring the semaphore in suspend(),
remove(), shutdown(), before you ever acquire the card->adapter? If you
do that first (to fix the race), and only *then* do you submit the
$subject patch, then you might have fixed all the races in question (at
least between FW init and {suspend,resume,remove,shutdown} -- you have
plenty of other races still, both known and unknown).

[[ Also, a side note on POINT D: it's possible that even though you're
retrieving card->adapter in the argument to that function call, it's
possible the compiler will notice that this is redundant with the
retrieval at POINT C and just use that one. But even if not, there's a
window between "retrieve function argument" and "grab semaphore in
mwifiex_remove_card()". ]]

---

BTW I'm gonna sidetrack us here... what's up with this code, in pcie.c?

        if (!down_interruptible(&add_remove_card_sem))
                up(&add_remove_card_sem);

I can understand that you want to grab the semaphore for the remove code, but
why do you want to immediately release it? If you release it, that must
mean that someone else is trying to get it. And they won't notice that
you're tearing down the device... (Also, why aren't you handling the
interrupted case?)

> I have updated patch description in v5 series.
> 
> You are right. We may have a race between init failure and suspend
> thread. I have prepared 4th patch in my v5 series to address this.
> 
> > 
> > I'm going to look into converting to asynchronous device probing, which
> > might remove the need for async FW request, and would therefore resolve
> > both patch 1 and 3's races without any additional complicated hacks. But
> > I'm not sure if that will satisfy all mwifiex users well enough. I'll
> > have to give it a little more thought. Any thoughts from your side,
> > Amit?
> > 
> 
> This is not needed.

Yeah, I ended up deciding this really wasn't that great of a solution.
For one, you also need to do firmware reloads for your PCIe reset
handling, and this happens in parallel to any device suspend. So:
(a) I'd bet that has plenty of race conditions and
(b) that means we can't just "load the firmware synchronously once and
forget about it"

> 4th patch in V5 series would take care of this race.

No, patch 4 does not handle this race, and it doesn't handle the race I
point out above either. You still can get a pointer card->adapter and
then see another thread subsequently free() it out from under you.

> I will be posting v5 series shortly.

Nak to both v4 and v5. They're not substantially different.

Brian

^ permalink raw reply

* Re: [PATCH v5 1/4] mwifiex: reset card->adapter during device unregister
From: Brian Norris @ 2016-10-25  1:00 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, briannorris,
	dmitry.torokhov, Xinming Hu
In-Reply-To: <1476969979-28554-1-git-send-email-akarwar@marvell.com>

On Thu, Oct 20, 2016 at 06:56:16PM +0530, Amitkumar Karwar wrote:
> From: Xinming Hu <huxm@marvell.com>
> 
> card->adapter gets initialized in mwifiex_register_dev(). As it's not
> cleared in mwifiex_unregister_dev(), we may end up accessing the memory
> which is already free in below scenario.
> 
> Scenario: Driver initialization is failed due to incorrect firmware or
> some other reason. Meanwhile device reboot/unload occurs.
> 
> Please note that we have 'add_remove_card_sem' semaphore. So if there
> is a race betweem init and remove threads, they will execute one after
> another.

I argued in v4 [1] that this is false, and therefore this patch isn't
really correct. Carrying the NACK here.

Brian

[1] https://patchwork.kernel.org/patch/9365209/

> This patch ensures that "card->adapter" is set to NULL when
> all cleanup is performed in init failure thread. Later remove thread
> can return immediately if "card->adapter" is NULL
> 
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> v4: Same as v1, v2, v3
> v5: Patch description is updated to get clear picture. There is no race
> for init and remove threads as per design. This patch just adds missing
> "card->adapter= NULL" change to avoid accessing already freed memory which
> leads to a crash.
> ---
>  drivers/net/wireless/marvell/mwifiex/pcie.c | 1 +
>  drivers/net/wireless/marvell/mwifiex/sdio.c | 1 +
>  2 files changed, 2 insertions(+)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 063c707..302ffd1 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -3021,6 +3021,7 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
>  			if (card->msi_enable)
>  				pci_disable_msi(pdev);
>  	       }
> +		card->adapter = NULL;
>  	}
>  }
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index 8718950..4cad1c2 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -2066,6 +2066,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
>  	struct sdio_mmc_card *card = adapter->card;
>  
>  	if (adapter->card) {
> +		card->adapter = NULL;
>  		sdio_claim_host(card->func);
>  		sdio_disable_func(card->func);
>  		sdio_release_host(card->func);
> -- 
> 1.9.1
> 

^ permalink raw reply

* Re: compex wle900vx (ath10k) problem on 4.4.24 / armv7
From: Oliver Zemann @ 2016-10-25  5:53 UTC (permalink / raw)
  To: Matthias Klein, Michal Kazior; +Cc: linux-wireless
In-Reply-To: <45bffe7d-8f27-ef26-b7f9-78709e52652f@gmail.com>


> I created a patch which should work for 4.4.24 (at least for arch 
> linux arm it applied successful)
>
> Just compiling the kernel... lets see what happens
Did not work. First, there was a + which was wrong, guess i have this 
simply overseen. After fixing that i got:

drivers/pci/pcie/portdrv_pci.c: In function 'pcie_port_runtime_suspend':
drivers/pci/pcie/portdrv_pci.c:98:24: error: 'struct pci_dev' has no 
member named 'bridge_d3'
   return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
                         ^~
drivers/pci/pcie/portdrv_pci.c: In function 'pcie_port_runtime_idle':
drivers/pci/pcie/portdrv_pci.c:113:24: error: 'struct pci_dev' has no 
member named 'bridge_d3'
   return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
                         ^~
drivers/pci/pcie/portdrv_pci.c:114:1: warning: control reaches end of 
non-void function [-Wreturn-type]
  }
  ^
drivers/pci/pcie/portdrv_pci.c: In function 'pcie_port_runtime_suspend':
drivers/pci/pcie/portdrv_pci.c:99:1: warning: control reaches end of 
non-void function [-Wreturn-type]
  }
  ^
make[3]: *** [scripts/Makefile.build:259: 
drivers/pci/pcie/portdrv_pci.o] Error 1
make[2]: *** [scripts/Makefile.build:403: drivers/pci/pcie] Error 2
make[1]: *** [scripts/Makefile.build:403: drivers/pci] Error 2
make: *** [Makefile:959: drivers] Error 2
==> ERROR: A failure occurred in build().
     Aborting...

A simple cherry pick does not work in that case.

^ permalink raw reply

* Re: Bayesian rate control
From: Johannes Berg @ 2016-10-25  7:14 UTC (permalink / raw)
  To: Björn Smedman; +Cc: linux-wireless, ath9k-devel
In-Reply-To: <CAGp19xdgsoyx9Sa=uas1OEiFoJdzFChmt20++9e7fJK=Z1ujWQ@mail.gmail.com>

On Mon, 2016-10-24 at 22:17 +0200, Björn Smedman wrote:
> 
> 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

Maybe something that's usable with brcmsmac? Not sure I'd recommend
buying Broadcom NICs though at this point, with them having been bought
out and all (and their upstream support is somewhat spotty, so you
might have a hard time finding the right NIC)

johannes

^ permalink raw reply

* Re: [PATCH] staging: rtl8712: Free memory and return failure when kmalloc fails
From: Greg KH @ 2016-10-25  9:03 UTC (permalink / raw)
  To: Souptick Joarder; +Cc: linux-wireless, Larry.Finger, florian.c.schilhabel
In-Reply-To: <20161020065932.GA21705@symbol-HP-ZBook-15>

On Thu, Oct 20, 2016 at 12:29:33PM +0530, Souptick Joarder wrote:
> This patch is added to free memory and return failure when kmalloc fails

I'm sorry, but I can not parse that sentance.  Can you rephrase this a
bit better?  What exactly are you doing here?

> 
> Signed-off-by: Souptick joarder <jrdr.linux@gmail.com>
> ---
>  drivers/staging/rtl8712/os_intfs.c     | 3 ++-
>  drivers/staging/rtl8712/rtl871x_cmd.c  | 5 ++++-
>  drivers/staging/rtl8712/rtl871x_xmit.c | 5 ++++-
>  3 files changed, 10 insertions(+), 3 deletions(-)

Any reason why you didn't cc: the driverdevel mailing list?  I doubt
linux-wireless cares about staging drivers :(

> 
> diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
> index cbe4de0..aab3141 100644
> --- a/drivers/staging/rtl8712/os_intfs.c
> +++ b/drivers/staging/rtl8712/os_intfs.c
> @@ -313,7 +313,8 @@ u8 r8712_init_drv_sw(struct _adapter *padapter)
>  		return _FAIL;
>  	if (r8712_init_mlme_priv(padapter) == _FAIL)
>  		return _FAIL;
> -	_r8712_init_xmit_priv(&padapter->xmitpriv, padapter);
> +	if ((_r8712_init_xmit_priv(&padapter->xmitpriv, padapter)) != _SUCCESS)
> +		return _FAIL;

You don't have to unwind anything that r8712_init_mlme_priv() did?

>  	_r8712_init_recv_priv(&padapter->recvpriv, padapter);
>  	memset((unsigned char *)&padapter->securitypriv, 0,
>  	       sizeof(struct security_priv));

thanks,

greg k-h

^ permalink raw reply

* pull-request: iwlwifi 2016-10-25
From: Luca Coelho @ 2016-10-25  9:38 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, linuxwifi

[-- Attachment #1: Type: text/plain, Size: 2456 bytes --]

Hi Kalle,

Here are 7 patches intended for 4.9.  They fix some small issues, as
described in the tag itself.  I sent them out for review on 2016-10-19, 
and pushed to a pending branch.  Kbuildbot didn't find any issues.

Let me know if everything's fine (or not). :)

Luca.


The following changes since commit 1ea2643961b0d1b8d0e4a11af5aa69b0f92d0533:

  ath6kl: add Dell OEM SDIO I/O for the Venue 8 Pro (2016-10-13 14:16:33 +0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-for-kalle-2016-10-25

for you to fetch changes up to 5a143db8c4a28dab6423cb6197e9f1389da375f2:

  iwlwifi: mvm: fix netdetect starting/stopping for unified images (2016-10-19 09:54:45 +0300)

----------------------------------------------------------------
* some fixes for suspend/resume with unified FW images;
* a fix for a false-positive lockdep report;
* a fix for multi-queue that caused an unnecessary 1 second latency;
* a fix for an ACPI parsing bug that caused a misleading error message;

----------------------------------------------------------------
Haim Dreyfuss (1):
      iwlwifi: mvm: comply with fw_restart mod param on suspend

Johannes Berg (1):
      iwlwifi: pcie: mark command queue lock with separate lockdep class

Luca Coelho (4):
      iwlwifi: mvm: use ssize_t for len in iwl_debugfs_mem_read()
      iwlwifi: mvm: fix d3_test with unified D0/D3 images
      iwlwifi: pcie: fix SPLC structure parsing
      iwlwifi: mvm: fix netdetect starting/stopping for unified images

Sara Sharon (1):
      iwlwifi: mvm: wake the wait queue when the RX sync counter is zero

 drivers/net/wireless/intel/iwlwifi/mvm/d3.c       | 49 +++++++++++++++++++++++++++++++++++++-----------
 drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c  |  4 ++--
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |  3 +--
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h      |  1 +
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c      |  1 +
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c     |  3 ++-
 drivers/net/wireless/intel/iwlwifi/mvm/scan.c     | 33 +++++++++++++++++++++++++++------
 drivers/net/wireless/intel/iwlwifi/pcie/drv.c     | 79 +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c      |  8 ++++++++
 9 files changed, 128 insertions(+), 53 deletions(-)

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* pull-request: iwlwifi-next 2016-10-25
From: Luca Coelho @ 2016-10-25 10:04 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, linuxwifi

[-- Attachment #1: Type: text/plain, Size: 2966 bytes --]

Hi Kalle,

Here's my first pull-request intended for 4.10.  It contains the usual
improvements and bugfixes, with the major thing being that we have
finally enabled dynamic queue allocation.  Some more details in the tag
description.

These patches were sent out for review on 2016-10-19, and pushed to a
pending branch.  Kbuildbot didn't find any issues.

Let me know if everything's fine (or not). :)

Luca.


The following changes since commit 15b95a15950238eff4d7f24be1716086eea67835:

  Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git (2016-09-28 16:37:33 +0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git tags/iwlwifi-next-for-kalle-2016-10-25

for you to fetch changes up to a048dcc71e701cb1771b2e0aca23181a45658023:

  iwlwifi: mvm: use dev_coredumpsg() (2016-10-19 12:46:37 +0300)

----------------------------------------------------------------
* Finalize and enable dynamic queue allocation;
* Use dev_coredumpmsg() to prevent locking the driver;
* Small fix to pass the AID to the FW;
* Use FW PS decisions with multi-queue;

----------------------------------------------------------------
Aviya Erenfeld (1):
      iwlwifi: mvm: use dev_coredumpsg()

Emmanuel Grumbach (1):
      iwlwifi: mvm: tell the firmware about the AID of the peer

Johannes Berg (1):
      iwlwifi: mvm: use firmware station PM notification for AP_LINK_PS

Liad Kaufman (5):
      iwlwifi: mvm: update txq metadata to current owner
      iwlwifi: mvm: fix reserved txq freeing
      iwlwifi: mvm: support MONITOR vif in DQA mode
      iwlwifi: mvm: fix dqa deferred frames marking
      iwlwifi: mvm: operate in dqa mode

Sara Sharon (1):
      iwlwifi: mvm: assign cab queue to the correct station

Sharon Dvir (1):
      iwlwifi: pcie: give a meaningful name to interrupt request

 drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h    |   2 ++
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h  |  26 ++++++++++++++++++++
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h |   9 ++++---
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h     |   1 +
 drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c     | 100 +++++++++++++++++++++++++++++++++++++++++----------------------------------
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c   |  24 +++++++++---------
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c   |  86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h        |   6 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c        |   3 +++
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c        |  37 ++++++++++++++++++++++------
 drivers/net/wireless/intel/iwlwifi/mvm/sta.h        |   1 +
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c     |  29 +++++++++++++++++++++-
 12 files changed, 249 insertions(+), 75 deletions(-)

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* RE: [PATCH] cw1200: fix bogus maybe-uninitialized warning
From: David Laight @ 2016-10-25 13:24 UTC (permalink / raw)
  To: 'Arnd Bergmann', Solomon Peachy, Kalle Valo
  Cc: Johannes Berg, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20161024154215.2863586-1-arnd@arndb.de>

RnJvbTogT2YgQXJuZCBCZXJnbWFubg0KPiBTZW50OiAyNCBPY3RvYmVyIDIwMTYgMTY6NDINCiAN
Cj4gT24geDg2LCB0aGUgY3cxMjAwIGRyaXZlciBwcm9kdWNlcyBhIHJhdGhlciBzaWxseSB3YXJu
aW5nIGFib3V0IHRoZQ0KPiBwb3NzaWJsZSB1c2Ugb2YgdGhlICdyZXQnIHZhcmlhYmxlIHdpdGhv
dXQgYW4gaW5pdGlhbGl6YXRpb24NCj4gcHJlc3VtYWJseSBhZnRlciBiZWluZyBjb25mdXNlZCBi
eSB0aGUgYXJjaGl0ZWN0dXJlIHNwZWNpZmljIGRlZmluaXRpb24NCj4gb2YgV0FSTl9PTjoNCj4g
DQo+IGRyaXZlcnMvbmV0L3dpcmVsZXNzL3N0L2N3MTIwMC93c20uYzogSW4gZnVuY3Rpb24gd3Nt
X2hhbmRsZV9yeDoNCj4gZHJpdmVycy9uZXQvd2lyZWxlc3Mvc3QvY3cxMjAwL3dzbS5jOjE0NTc6
OTogZXJyb3I6IHJldCBtYXkgYmUgdXNlZCB1bmluaXRpYWxpemVkIGluIHRoaXMgZnVuY3Rpb24g
Wy0NCj4gV2Vycm9yPW1heWJlLXVuaW5pdGlhbGl6ZWRdDQo+IA0KPiBBcyB0aGUgZHJpdmVyIGp1
c3QgY2hlY2tzIHRoZSBzYW1lIHZhcmlhYmxlIHR3aWNlIGhlcmUsIHdlIGNhbiBzaW1wbGlmeQ0K
PiBpdCBieSByZW1vdmluZyB0aGUgc2Vjb25kIGNvbmRpdGlvbiwgd2hpY2ggbWFrZXMgaXQgbW9y
ZSByZWFkYWJsZSBhbmQNCj4gYXZvaWRzIHRoZSB3YXJuaW5nLg0KPiANCj4gU2lnbmVkLW9mZi1i
eTogQXJuZCBCZXJnbWFubiA8YXJuZEBhcm5kYi5kZT4NCj4gLS0tDQo+ICBkcml2ZXJzL25ldC93
aXJlbGVzcy9zdC9jdzEyMDAvd3NtLmMgfCAxNSArKysrKysrLS0tLS0tLS0NCj4gIDEgZmlsZSBj
aGFuZ2VkLCA3IGluc2VydGlvbnMoKyksIDggZGVsZXRpb25zKC0pDQo+IA0KPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mvc3QvY3cxMjAwL3dzbS5jIGIvZHJpdmVycy9uZXQvd2ly
ZWxlc3Mvc3QvY3cxMjAwL3dzbS5jDQo+IGluZGV4IDY4MGQ2MGVhYmM3NS4uMDk0ZTY2MzdhZGUy
IDEwMDY0NA0KPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9zdC9jdzEyMDAvd3NtLmMNCj4g
KysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mvc3QvY3cxMjAwL3dzbS5jDQo+IEBAIC0zODUsMTQg
KzM4NSwxMyBAQCBzdGF0aWMgaW50IHdzbV9tdWx0aV90eF9jb25maXJtKHN0cnVjdCBjdzEyMDBf
Y29tbW9uICpwcml2LA0KPiAgCWlmIChXQVJOX09OKGNvdW50IDw9IDApKQ0KPiAgCQlyZXR1cm4g
LUVJTlZBTDsNCj4gDQo+IC0JaWYgKGNvdW50ID4gMSkgew0KPiAtCQkvKiBXZSBhbHJlYWR5IHJl
bGVhc2VkIG9uZSBidWZmZXIsIG5vdyBmb3IgdGhlIHJlc3QgKi8NCj4gLQkJcmV0ID0gd3NtX3Jl
bGVhc2VfdHhfYnVmZmVyKHByaXYsIGNvdW50IC0gMSk7DQo+IC0JCWlmIChyZXQgPCAwKQ0KPiAt
CQkJcmV0dXJuIHJldDsNCj4gLQkJZWxzZSBpZiAocmV0ID4gMCkNCj4gLQkJCWN3MTIwMF9iaF93
YWtldXAocHJpdik7DQo+IC0JfQ0KPiArCS8qIFdlIGFscmVhZHkgcmVsZWFzZWQgb25lIGJ1ZmZl
ciwgbm93IGZvciB0aGUgcmVzdCAqLw0KPiArCXJldCA9IHdzbV9yZWxlYXNlX3R4X2J1ZmZlcihw
cml2LCBjb3VudCAtIDEpOw0KPiArCWlmIChyZXQgPCAwKQ0KPiArCQlyZXR1cm4gcmV0Ow0KPiAr
DQo+ICsJaWYgKHJldCA+IDApDQo+ICsJCWN3MTIwMF9iaF93YWtldXAocHJpdik7DQoNClRoYXQg
ZG9lc24ndCBsb29rIGVxdWl2YWxlbnQgdG8gbWUgKHdoZW4gY291bnQgPT0gMSkuDQoNCj4gDQo+
ICAJY3cxMjAwX2RlYnVnX3R4ZWRfbXVsdGkocHJpdiwgY291bnQpOw0KPiAgCWZvciAoaSA9IDA7
IGkgPCBjb3VudDsgKytpKSB7DQoNCkNvbnZlcnQgdGhpcyBsb29wIGludG8gYSBkbyAuLi4gd2hp
bGUgc28gdGhlIGJvZHkgZXhlY3V0ZXMgYXQgbGVhc3Qgb25jZS4NCg0KCURhdmlkDQoNCg==

^ permalink raw reply

* RE: [PATCH v4 1/3] mwifiex: reset card->adapter during device unregister
From: Amitkumar Karwar @ 2016-10-25 15:12 UTC (permalink / raw)
  To: Brian Norris
  Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
	rajatja@google.com, Xinming Hu, abhishekbh@google.com,
	Dmitry Torokhov
In-Reply-To: <20161025005150.GA84310@google.com>

Hi Brian,

Thanks for review.

> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Tuesday, October 25, 2016 6:22 AM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> rajatja@google.com; Xinming Hu; abhishekbh@google.com; Dmitry Torokhov
> Subject: Re: [PATCH v4 1/3] mwifiex: reset card->adapter during device
> unregister
> 
> Hi Amit,
> 
> On Thu, Oct 20, 2016 at 01:11:31PM +0000, Amitkumar Karwar wrote:
> > > From: Brian Norris [mailto:briannorris@chromium.org]
> > > Sent: Tuesday, October 11, 2016 5:53 AM
> > > To: Amitkumar Karwar
> > > Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> > > rajatja@google.com; Xinming Hu; abhishekbh@google.com; Dmitry
> > > Torokhov
> > > Subject: Re: [PATCH v4 1/3] mwifiex: reset card->adapter during
> > > device unregister
> > >
> > > On Mon, Oct 10, 2016 at 01:53:32PM -0700, Brian Norris wrote:
> > > > On Thu, Oct 06, 2016 at 11:36:24PM +0530, Amitkumar Karwar wrote:
> > > > > From: Xinming Hu <huxm@marvell.com>
> > > > >
> > > > > card->adapter gets initialized during device registration.
> > > > > As it's not cleared, we may end up accessing invalid memory in
> > > > > some corner cases. This patch fixes the problem.
> > > > >
> > > > > Signed-off-by: Xinming Hu <huxm@marvell.com>
> > > > > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> > > > > ---
> > > > > v4: Same as v1, v2, v3
> > > > > ---
> > > > >  drivers/net/wireless/marvell/mwifiex/pcie.c | 1 +
> > > > > drivers/net/wireless/marvell/mwifiex/sdio.c | 1 +
> > > > >  2 files changed, 2 insertions(+)
> > > > >
> > > > > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > > index f1eeb73..ba9e068 100644
> > > > > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > > > @@ -3042,6 +3042,7 @@ static void mwifiex_unregister_dev(struct
> > > mwifiex_adapter *adapter)
> > > > >  				pci_disable_msi(pdev);
> > > > >  	       }
> > > > >  	}
> > > > > +	card->adapter = NULL;
> > > > >  }
> > > > >
> > > > >  /* This function initializes the PCI-E host memory space, WCB
> > > rings, etc.
> > > > > diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > > b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > > index 8718950..4cad1c2 100644
> > > > > --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > > +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > > > > @@ -2066,6 +2066,7 @@ mwifiex_unregister_dev(struct
> > > > > mwifiex_adapter
> > > *adapter)
> > > > >  	struct sdio_mmc_card *card = adapter->card;
> > > > >
> > > > >  	if (adapter->card) {
> > > > > +		card->adapter = NULL;
> > > > >  		sdio_claim_host(card->func);
> > > > >  		sdio_disable_func(card->func);
> > > > >  		sdio_release_host(card->func);
> > > >
> > > > As discussed on v1, I had qualms about the raciness between
> > > > reads/writes of card->adapter, but I believe we:
> > > > (a) can't have any command activity while writing the ->adapter
> > > > field (either we're just init'ing the device, or we've disabled
> > > > interrupts and are tearing it down) and
> > > > (b) can't have a race between suspend()/resume() and
> > > > unregister_dev(), since unregister_dev() is called from device
> > > > remove() (which should not be concurrent with suspend()).
> > > >
> > > > Also, I thought you had the same problem in usb.c, but in fact,
> > > > you fixed that ages ago here:
> > > >
> > > > 353d2a69ea26 mwifiex: fix issues in driver unload path for USB
> > > > chipsets
> > > >
> > > > Would be nice if fixes were bettery synchronized across the three
> > > > interface drivers you support. We seem to be discovering
> > > > unnecessary divergence on a few points recently.
> > > >
> > > > At any rate:
> > > >
> > > > Reviewed-by: Brian Norris <briannorris@chromium.org>
> > > > Tested-by: Brian Norris <briannorris@chromium.org>
> > >
> > > Dmitry helped me re-realize my original qualms:
> > >
> > > mwifiex_unregister_dev() is called in the failure path for your
> > > async FW request, and so it may race with suspend(). So I retract my
> Reviewed-by.
> > > Sorry.
> >
> > Thanks for your comments.
> >
> > Actually description for this patch was ambiguous and incorrect. Sorry
> > for that. This patch doesn't fix any race. In fact, we don't have a
> > race between init and remove threads due to semaphore usage as per
> > design. This patch just adds missing "card->adapter=NULL" so that when
> > teardown/remove thread starts after init failure, it won't try freeing
> > already freed things.
> 
> So to be clear, you'r talking about mwifiex_fw_dpc(), which in the error
> path
> has:
> 
>        if (adapter->if_ops.unregister_dev)
>                 adapter->if_ops.unregister_dev(adapter); <--- POINT A:
> This is where you want to set ->adapter = NULL ...
>         if (init_failed)
>                 mwifiex_free_adapter(adapter);
>         up(sem); <--- POINT B: This is where you release the semaphore,
> which is supposed to guarantee that remove() isn't happening
>         return;
> }
> 
> But you *do* have a race between the above code and the remove code in
> some cases. Particularly, see this:
> 
> static void mwifiex_pcie_remove(struct pci_dev *pdev) {
>         struct pcie_service_card *card;
>         struct mwifiex_adapter *adapter;
>         struct mwifiex_private *priv;
> 
>         card = pci_get_drvdata(pdev);
>         if (!card)
>                 return;
> 
>         adapter = card->adapter; <--- POINT C: This can execute at the
> same time as unregister_dev()
>         if (!adapter || !adapter->priv_num)
>                 return;
> 
>         if (user_rmmod && !adapter->mfg_mode) { #ifdef CONFIG_PM_SLEEP
>                 if (adapter->is_suspended)
>                         mwifiex_pcie_resume(&pdev->dev); #endif
> 
>                 mwifiex_deauthenticate_all(adapter);
> 
>                 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
> 
>                 mwifiex_disable_auto_ds(priv);
> 
>                 mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
>         }
> 
>         mwifiex_remove_card(card->adapter, &add_remove_card_sem); <---
> POINT D: You only grab the semaphore here }
> 
> So IIUC, you have a race **even here, where you claim the semaphore
> should protect you** such that the adapter might be freed, but you still
> can access it anywhere between C and D. i.e., you can see this:
> 
> Thread 1                              Thread 2
>                                       (1) POINT C (retrieve adapter !=
> NULL)
> (2) POINT A (set adapter NULL)
> (3) POINT B (adapter has been freed)
>                                       (3) ....Keep accessing freed
> adapter structure
>                                       (4) POINT D - acquire semaphore,
> but we're too late
> 
> Step 3 is an error, and AFAICT, that's exactly what you're trying to
> solve in this patch. It essentially comes down to the same fact: you're
> getting a reference to the adapter structure *without* any protection at
> all. Your add_remove_card_sem is *almost* the right thing to resolve
> this, but you still don't have the ordering quite right.

Code between POINT C and POINT D won't come into picture for "init + reboot" scenario(Case 1 below) which we are talking here. Reason is "user_rmmod" flag will be false.

Basically we have 3 teardown cases
1) System shutdown (or manually remove wifi card) -- Only mwifiex_pcie_remove() gets called.
2) User unloading the driver -- mwifiex_pcie_cleanup_module() followed by mwifiex_pcie_remove() gets called.
3) Chip isn't connected. User unloaded the driver -- Only mwifiex_pcie_cleanup_module() gets 
called.

In case 2, we have already waited for semaphore in mwifiex_pcie_cleanup_module(). So by the time we execute mwifiex_pcie_remove(), "card->adapter" is NULL.
Case 3, doesn't use "card->adapter"

> 
> Maybe you could solve this all by acquiring the semaphore in suspend(),
> remove(), shutdown(), before you ever acquire the card->adapter? If you
> do that first (to fix the race), and only *then* do you submit the
> $subject patch, then you might have fixed all the races in question (at
> least between FW init and {suspend,resume,remove,shutdown} -- you have
> plenty of other races still, both known and unknown).

"add_remove_card_sem" is used only for init and teardown threads as per our design. 
V5 4/4 takes care of race between "init fail + suspend". Please let us know if you see any other race situation.

> 
> [[ Also, a side note on POINT D: it's possible that even though you're
> retrieving card->adapter in the argument to that function call, it's
> possible the compiler will notice that this is redundant with the
> retrieval at POINT C and just use that one. But even if not, there's a
> window between "retrieve function argument" and "grab semaphore in
> mwifiex_remove_card()". ]]

I had not considered that compiler will notice this is redundant and use "card->adapter" assigned at POINT C.
But this window is very small compared to the window between in "card->adapter = NULL" and releasing semaphore in other(mwifiex_fw_dpc()) thread.

Even if "card->adapter" is set to NULL in mwifiex_fw_dpc() after we checked it at POINT C, we will return from mwifiex_remove_card() without grabing semaphore. mwifiex_fw_dpc() wouldn't have released the semaphore at that point of time. mwifiex_fw_dpc() will take care of performing cleanup.

> 
> ---
> 
> BTW I'm gonna sidetrack us here... what's up with this code, in pcie.c?
> 
>         if (!down_interruptible(&add_remove_card_sem))
>                 up(&add_remove_card_sem);
> 
> I can understand that you want to grab the semaphore for the remove
> code, but why do you want to immediately release it? If you release it,
> that must mean that someone else is trying to get it. And they won't
> notice that you're tearing down the device... 

I don't see any problem in releasing the semaphore here. Only other thread which can acquire this semaphore is "init" thread.
"init" thread won't get called when user is unloading the driver.

The purpose of immediately releasing it is we just wanted to wait until init is completed if it's running.

>(Also, why aren't you
> handling the interrupted case?)

The cleanup performed in this function is done without touching hardware OR referring adapter/card etc. It can be done even for the interrupted case.

> 
> > I have updated patch description in v5 series.
> >
> > You are right. We may have a race between init failure and suspend
> > thread. I have prepared 4th patch in my v5 series to address this.
> >
> > >
> > > I'm going to look into converting to asynchronous device probing,
> > > which might remove the need for async FW request, and would
> > > therefore resolve both patch 1 and 3's races without any additional
> > > complicated hacks. But I'm not sure if that will satisfy all mwifiex
> > > users well enough. I'll have to give it a little more thought. Any
> > > thoughts from your side, Amit?
> > >
> >
> > This is not needed.
> 
> Yeah, I ended up deciding this really wasn't that great of a solution.
> For one, you also need to do firmware reloads for your PCIe reset
> handling, and this happens in parallel to any device suspend. So:
> (a) I'd bet that has plenty of race conditions and
> (b) that means we can't just "load the firmware synchronously once and
> forget about it"
> 
> > 4th patch in V5 series would take care of this race.
> 
> No, patch 4 does not handle this race, and it doesn't handle the race I
> point out above either. You still can get a pointer card->adapter and
> then see another thread subsequently free() it out from under you.

We have used spinlock in v5 4/4 to guard "card->adapter".
Please help me understand if it doesn't handle the race between "init fail" + suspend.

Regards,
Amitkumar Karwar.

^ permalink raw reply

* RE: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Amitkumar Karwar @ 2016-10-25 16:00 UTC (permalink / raw)
  To: Brian Norris, Dmitry Torokhov
  Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
	briannorris@google.com
In-Reply-To: <20161024235555.GA7745@localhost>

Hi Brian/Dmitry,

> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Tuesday, October 25, 2016 5:26 AM
> To: Dmitry Torokhov
> Cc: Amitkumar Karwar; linux-wireless@vger.kernel.org; Cathy Luo; Nishant
> Sarmukadam; briannorris@google.com
> Subject: Re: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing'
> in shutdown_drv
> 
> Hi,
> 
> On Mon, Oct 24, 2016 at 04:47:20PM -0700, Dmitry Torokhov wrote:
> > 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?
> 
> That's why I commented:
> 
> "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?"

If mwifiex_processing is true here, it means main_process is still running. We have set "adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING" in mwifiex_shutdown_drv().
Now we will wait until main_process() gets completed.

---------------------
if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
     wait_event_interruptible(adapter->init_wait_q,
				      adapter->init_wait_q_woken);
--------------

We have following logic at the end of main_process()
-------
exit_main_proc:
        if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
                mwifiex_shutdown_drv(adapter);
--------

Regards,
Amitkumar Karwar

^ permalink raw reply

* RE: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing' in shutdown_drv
From: Amitkumar Karwar @ 2016-10-25 16:11 UTC (permalink / raw)
  To: Dmitry Torokhov, Brian Norris
  Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam
In-Reply-To: <20161024235746.GC15034@dtor-ws>

Hi Dmitry,

> From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> Sent: Tuesday, October 25, 2016 5:28 AM
> To: Brian Norris
> Cc: Amitkumar Karwar; linux-wireless@vger.kernel.org; Cathy Luo; Nishant
> Sarmukadam
> Subject: Re: [PATCH 2/5] mwifiex: use spinlock for 'mwifiex_processing'
> in shutdown_drv
> 
> On Mon, Oct 24, 2016 at 12:19:15PM -0700, Brian Norris wrote:
> > 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:
> 
> No, this is definitely not right way to check it. What exactly does this
> spinlock protect? It seems that the intent is to make sure we do not
> call mwifiex_shutdown_drv() while mwifiex_main_process() is executing.
> It even says above that we are "waiting" for it (but we do not, we may
> bail out or we may not, depends on luck).
> 
> To implement this properly you not only need to take a lock and check
> the flag, but keep the lock until mwifiex_shutdown_drv() is done, or use
> some other way to let mwifiex_main_process() know it should not access
> the adapter while mwifiex_shutdown_drv() is running.
> 
> NACK.
> 

As I explained in other email, here is the sequence.
1) We find mwifiex_processing is true in mwifiex_shitdown_drv(). "-EINPROGRESS" is returned by the function and hw_status state is changed to MWIFIEX_HW_STATUS_CLOSING.
2) We wait until main_process is completed.

                if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
                        wait_event_interruptible(adapter->init_wait_q,
                                                 adapter->init_wait_q_woken);

3) We have following check at the end of main_process()

exit_main_proc:
        if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
                mwifiex_shutdown_drv(adapter);

4) Here at the end of mwifiex_shutdown_drv(), we are setting "adapter->init_wait_q_woken" and waking up the thread in point (2)

Regards,
Amitkumar

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox