qtnfmac: improve control path timeout handling
authorDmitry Lebed <dlebed@quantenna.com>
Tue, 29 May 2018 12:00:01 +0000 (15:00 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 30 May 2018 19:20:05 +0000 (22:20 +0300)
Control path will not be operational after firmware failure. Change bus
state to QTNF_FW_STATE_EP_DEAD after the control path timeout.
Don't wait for timeout if control path is already dead.

Signed-off-by: Dmitry Lebed <dlebed@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/quantenna/qtnfmac/bus.h
drivers/net/wireless/quantenna/qtnfmac/core.c
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c

index 0a1604683babefa1a7ac6e9c6f38a7806fe47442..323e47cea1e2ff579f8f0b392b44536d74b8d5db 100644 (file)
@@ -27,7 +27,8 @@ enum qtnf_fw_state {
        QTNF_FW_STATE_FW_DNLD_DONE,
        QTNF_FW_STATE_BOOT_DONE,
        QTNF_FW_STATE_ACTIVE,
-       QTNF_FW_STATE_DEAD,
+       QTNF_FW_STATE_DETACHED,
+       QTNF_FW_STATE_EP_DEAD,
 };
 
 struct qtnf_bus;
index 3ccbc427cf56c04e5933bad8814c9bd2c1da26b0..a6a450984f9acf63924343cae5a08d63d335b48d 100644 (file)
@@ -628,7 +628,7 @@ void qtnf_core_detach(struct qtnf_bus *bus)
        if (bus->fw_state == QTNF_FW_STATE_ACTIVE)
                qtnf_cmd_send_deinit_fw(bus);
 
-       bus->fw_state = QTNF_FW_STATE_DEAD;
+       bus->fw_state = QTNF_FW_STATE_DETACHED;
 
        if (bus->workqueue) {
                flush_workqueue(bus->workqueue);
index 6c1e139bb8f7731d76225560ab271d27e7bbf15b..3120d49df565dc86b5ae94ce6a77b9cb4f8c6380 100644 (file)
@@ -751,8 +751,16 @@ tx_done:
 static int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
 {
        struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+       int ret;
+
+       ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
 
-       return qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
+       if (ret == -ETIMEDOUT) {
+               pr_err("EP firmware is dead\n");
+               bus->fw_state = QTNF_FW_STATE_EP_DEAD;
+       }
+
+       return ret;
 }
 
 static irqreturn_t qtnf_interrupt(int irq, void *data)
@@ -1238,7 +1246,7 @@ static void qtnf_fw_work_handler(struct work_struct *work)
        goto fw_load_exit;
 
 fw_load_fail:
-       bus->fw_state = QTNF_FW_STATE_DEAD;
+       bus->fw_state = QTNF_FW_STATE_DETACHED;
 
 fw_load_exit:
        complete(&bus->firmware_init_complete);
@@ -1408,7 +1416,8 @@ static void qtnf_pcie_remove(struct pci_dev *pdev)
 
        wait_for_completion(&bus->firmware_init_complete);
 
-       if (bus->fw_state == QTNF_FW_STATE_ACTIVE)
+       if (bus->fw_state == QTNF_FW_STATE_ACTIVE ||
+           bus->fw_state == QTNF_FW_STATE_EP_DEAD)
                qtnf_core_detach(bus);
 
        priv = get_bus_priv(bus);