mwifiex: fix IRQ enable/disable
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
@@ -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
@@ -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
@@ -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
@@ -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
Hi Daniel,
Thanks for the patch.
Quoted 13 lines
During tear down (e.g.
mwifiex_sdio_removeduring 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_sdiowhich 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.
Signed-off-by Daniel Drake <[email protected]>
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