Skip to contentSkip to conversation

mwifiex: fix IRQ enable/disable

PATCH In review Daniel Drake 2 participants 2 messages Jul 13, 2013 – Jul 18, 2013 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mwifiex: fix IRQ enable/disable

During tear down (e.g. mwifiex_sdio_remove during system suspend), mwifiex left IRQs enabled for a significant period of time when it was unable to handle them correctly. This caused interrupt storms and interfered with the bluetooth interface on the same SDIO card.

Solve this by disabling interrupts at the point when they can no longer be handled correctly, which is at the start of mwifiex_remove_card().

For cleanliness, we now enable interrupts in the mwifiex_add_card() path, to be symmetrical with the disabling of interrupts. We also couple the registration of the sdio IRQ handler with the actual enable/disable of interrupts at the hardware level.

I also removed a write to this register in mwifiex_init_sdio which seemed pointless and won't cause any ill effects now that we only register the SDIO IRQ handler when we are ready to accept interrupts.

Includes some corrections from Amitkumar Karwar.

---
 drivers/net/wireless/mwifiex/init.c | 10 +---
 drivers/net/wireless/mwifiex/main.c | 13 +++++-
 drivers/net/wireless/mwifiex/main.h |  1 +
 drivers/net/wireless/mwifiex/sdio.c | 91 +++++++++++++++++--------------------
 drivers/net/wireless/mwifiex/sdio.h |  3 --
 5 files changed, 57 insertions(+), 61 deletions(-)

Replaces the previous patch:
mwifiex: don't ignore SDIO interrupts during shutdown

drivers/net/wireless/mwifiex/init.c +2 -8
index caaf4bd..2cf8b96 100644
@@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
 		if (!ret) {
 			dev_notice(adapter->dev,
 				   "WLAN FW already running! Skip FW dnld\n");
-			goto done;
+			return 0;
 		}
 
 		poll_num = MAX_FIRMWARE_POLL_TRIES;
@@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
 poll_fw:
 	/* Check if the firmware is downloaded successfully or not */
 	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
-	if (ret) {
+	if (ret)
 		dev_err(adapter->dev, "FW failed to be active in time\n");
-		return -1;
-	}
-done:
-	/* re-enable host interrupt for mwifiex after fw dnld is successful */
-	if (adapter->if_ops.enable_int)
-		adapter->if_ops.enable_int(adapter);
 
 	return ret;
 }
drivers/net/wireless/mwifiex/main.c +12 -1
index e15ab72..1753431 100644
@@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 				"Cal data request_firmware() failed\n");
 	}
 
+	/* enable host interrupt after fw dnld is successful */
+	if (adapter->if_ops.enable_int)
+		adapter->if_ops.enable_int(adapter);
+
 	adapter->init_wait_q_woken = false;
 	ret = mwifiex_init_fw(adapter);
 	if (ret == -1) {
@@ -478,6 +482,8 @@ err_add_intf:
 	mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
 	rtnl_unlock();
 err_init_fw:
+	if (adapter->if_ops.disable_int)
+		adapter->if_ops.disable_int(adapter);
 	pr_debug("info: %s: unregister device\n", __func__);
 	adapter->if_ops.unregister_dev(adapter);
 done:
@@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
 	INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
 
 	/* Register the device. Fill up the private data structure with relevant
-	   information from the card and request for the required IRQ. */
+	   information from the card. */
 	if (adapter->if_ops.register_dev(adapter)) {
 		pr_err("%s: failed to register mwifiex device\n", __func__);
 		goto err_registerdev;
@@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	if (!adapter)
 		goto exit_remove;
 
+	/* We can no longer handle interrupts once we start doing the teardown
+	 * below. */
+	if (adapter->if_ops.disable_int)
+		adapter->if_ops.disable_int(adapter);
+
 	adapter->surprise_removed = true;
 
 	/* Stop data */
drivers/net/wireless/mwifiex/main.h +1 -0
index 3da73d3..253e0bd 100644
@@ -601,6 +601,7 @@ struct mwifiex_if_ops {
 	int (*register_dev) (struct mwifiex_adapter *);
 	void (*unregister_dev) (struct mwifiex_adapter *);
 	int (*enable_int) (struct mwifiex_adapter *);
+	void (*disable_int) (struct mwifiex_adapter *);
 	int (*process_int_status) (struct mwifiex_adapter *);
 	int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
 			     struct mwifiex_tx_param *);
drivers/net/wireless/mwifiex/sdio.c +42 -49

178 lines not on this page · raw message

drivers/net/wireless/mwifiex/sdio.h +0 -3
index 6d51dfd..532ae0a 100644
@@ -92,9 +92,6 @@
 /* Host Control Registers : Download host interrupt mask */
 #define DN_LD_HOST_INT_MASK		(0x2U)
 
-/* Disable Host interrupt mask */
-#define	HOST_INT_DISABLE		0xff
-
 /* Host Control Registers : Host interrupt status */
 #define HOST_INTSTATUS_REG		0x03
 /* Host Control Registers : Upload host interrupt status */
Signature · 1 line
1.8.1.4
Acked-by on v1 1/1
#1 lore raw

Hi Daniel,

Thanks for the patch.

Quoted 13 lines

During tear down (e.g. mwifiex_sdio_remove during system suspend), mwifiex left IRQs enabled for a significant period of time when it was unable to handle them correctly. This caused interrupt storms and interfered with the bluetooth interface on the same SDIO card.

Solve this by disabling interrupts at the point when they can no longer be handled correctly, which is at the start of mwifiex_remove_card().

For cleanliness, we now enable interrupts in the mwifiex_add_card() path, to be symmetrical with the disabling of interrupts. We also couple the registration of the sdio IRQ handler with the actual enable/disable of interrupts at the hardware level.

Quoted 7 lines

I also removed a write to this register in mwifiex_init_sdio which seemed pointless and won't cause any ill effects now that we only register the SDIO IRQ handler when we are ready to accept interrupts.

Includes some corrections from Amitkumar Karwar.

Regards,
Bing

Quoted 11 lines
---
 drivers/net/wireless/mwifiex/init.c | 10 +---
drivers/net/wireless/mwifiex/main.c | 13 +++++-
drivers/net/wireless/mwifiex/main.h |  1 +
drivers/net/wireless/mwifiex/sdio.c | 91 +++++++++++++++++----------------
----
 drivers/net/wireless/mwifiex/sdio.h |  3 --
 5 files changed, 57 insertions(+), 61 deletions(-)

Replaces the previous patch:
mwifiex: don't ignore SDIO interrupts during shutdown