staging: wilc1000: avoid mutex unlock without lock in wilc_wlan_handle_txq()
authorAjay Singh <ajay.kathat@microchip.com>
Thu, 23 Jan 2020 12:50:49 +0000 (12:50 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Jan 2020 18:16:12 +0000 (19:16 +0100)
In wilc_wlan_handle_txq(), mutex unlock was called without acquiring
it. Also error code for full VMM condition was incorrect as discussed in
[1]. Now used a proper code to indicate VMM is full, for which transfer
to VMM is required again. 'wilc_wlan_handle_txq()' should be called
again if the VMM space was full earlier or otherwise based on
'txq_event' signal.

1. https://lore.kernel.org/driverdev-devel/20191113183322.a54mh2w6dulklgsd@kili.mountain/

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
Link: https://lore.kernel.org/r/20200123182129.4053-2-ajay.kathat@microchip.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/wilc1000/netdev.c
drivers/staging/wilc1000/wlan.c
drivers/staging/wilc1000/wlan.h

index 0f48e74..fce5bf2 100644 (file)
@@ -174,7 +174,7 @@ static int wilc_txq_task(void *vp)
                                }
                                srcu_read_unlock(&wl->srcu, srcu_idx);
                        }
-               } while (ret == -ENOBUFS && !wl->close);
+               } while (ret == WILC_VMM_ENTRY_FULL_RETRY && !wl->close);
        }
        return 0;
 }
index b904eda..601e4d1 100644 (file)
@@ -489,12 +489,12 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
        struct wilc_vif *vif;
 
        if (wilc->quit)
-               goto out;
+               goto out_update_cnt;
 
        mutex_lock(&wilc->txq_add_to_head_cs);
        tqe = wilc_wlan_txq_get_first(wilc);
        if (!tqe)
-               goto out;
+               goto out_unlock;
        dev = tqe->vif->ndev;
        wilc_wlan_txq_filter_dup_tcp_ack(dev);
        i = 0;
@@ -526,7 +526,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
        }
 
        if (i == 0)
-               goto out;
+               goto out_unlock;
        vmm_table[i] = 0x0;
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
@@ -595,7 +595,11 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
                goto out_release_bus;
 
        if (entries == 0) {
-               ret = -ENOBUFS;
+               /*
+                * No VMM space available in firmware so retry to transmit
+                * the packet from tx queue.
+                */
+               ret = WILC_VMM_ENTRY_FULL_RETRY;
                goto out_release_bus;
        }
 
@@ -662,9 +666,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
 out_release_bus:
        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 
-out:
+out_unlock:
        mutex_unlock(&wilc->txq_add_to_head_cs);
 
+out_update_cnt:
        *txq_count = wilc->txq_entries;
        return ret;
 }
index 44ae6ed..8c46342 100644 (file)
 #define IS_MGMT_STATUS_SUCCES  0x040
 
 #define WILC_WID_TYPE          GENMASK(15, 12)
+#define WILC_VMM_ENTRY_FULL_RETRY      1
 /********************************************
  *
  *      Tx/Rx Queue Structure