Skip to content

Commit 8399918

Browse files
ajaykathatgregkh
authored andcommitted
staging: wilc1000: use RCU list to maintain vif interfaces list
Make use of RCU list to maintain virtual interfaces instead of an array. The update operation on 'vif' list is less compare to the read operations. Mostly the 'vif' list elements are accessed for the read operation, so RCU list is more suited for this requirement. The shifting of interface index id's during the delete interface is not required. As the firmware only supports 2 interfaces so make use of available free slot index id during add interface. Signed-off-by: Ajay Singh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fb2d743 commit 8399918

File tree

5 files changed

+148
-123
lines changed

5 files changed

+148
-123
lines changed

drivers/staging/wilc1000/wilc_hif.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,17 @@ int wilc_get_vif_idx(struct wilc_vif *vif)
183183
static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
184184
{
185185
int index = idx - 1;
186+
struct wilc_vif *vif;
186187

187188
if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
188189
return NULL;
189190

190-
return wilc->vif[index];
191+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
192+
if (vif->idx == index)
193+
return vif;
194+
}
195+
196+
return NULL;
191197
}
192198

193199
static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)

drivers/staging/wilc1000/wilc_netdev.c

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,25 @@ void wilc_mac_indicate(struct wilc *wilc)
9797
static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
9898
{
9999
u8 *bssid, *bssid1;
100-
int i = 0;
101100
struct net_device *ndev = NULL;
101+
struct wilc_vif *vif;
102102

103103
bssid = mac_header + 10;
104104
bssid1 = mac_header + 4;
105105

106-
mutex_lock(&wilc->vif_mutex);
107-
for (i = 0; i < wilc->vif_num; i++) {
108-
if (wilc->vif[i]->mode == WILC_STATION_MODE)
109-
if (ether_addr_equal_unaligned(bssid,
110-
wilc->vif[i]->bssid)) {
111-
ndev = wilc->vif[i]->ndev;
106+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
107+
if (vif->mode == WILC_STATION_MODE)
108+
if (ether_addr_equal_unaligned(bssid, vif->bssid)) {
109+
ndev = vif->ndev;
112110
goto out;
113111
}
114-
if (wilc->vif[i]->mode == WILC_AP_MODE)
115-
if (ether_addr_equal_unaligned(bssid1,
116-
wilc->vif[i]->bssid)) {
117-
ndev = wilc->vif[i]->ndev;
112+
if (vif->mode == WILC_AP_MODE)
113+
if (ether_addr_equal_unaligned(bssid1, vif->bssid)) {
114+
ndev = vif->ndev;
118115
goto out;
119116
}
120117
}
121118
out:
122-
mutex_unlock(&wilc->vif_mutex);
123119
return ndev;
124120
}
125121

@@ -137,13 +133,16 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
137133

138134
int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
139135
{
140-
u8 i = 0;
136+
int srcu_idx;
141137
u8 ret_val = 0;
138+
struct wilc_vif *vif;
142139

143-
for (i = 0; i < wilc->vif_num; i++)
144-
if (!is_zero_ether_addr(wilc->vif[i]->bssid))
140+
srcu_idx = srcu_read_lock(&wilc->srcu);
141+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
142+
if (!is_zero_ether_addr(vif->bssid))
145143
ret_val++;
146-
144+
}
145+
srcu_read_unlock(&wilc->srcu, srcu_idx);
147146
return ret_val;
148147
}
149148

@@ -167,16 +166,16 @@ static int wilc_txq_task(void *vp)
167166
do {
168167
ret = wilc_wlan_handle_txq(wl, &txq_count);
169168
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
170-
int i;
169+
int srcu_idx;
171170
struct wilc_vif *ifc;
172171

173-
mutex_lock(&wl->vif_mutex);
174-
for (i = 0; i < wl->vif_num; i++) {
175-
ifc = wl->vif[i];
172+
srcu_idx = srcu_read_lock(&wl->srcu);
173+
list_for_each_entry_rcu(ifc, &wl->vif_list,
174+
list) {
176175
if (ifc->mac_opened && ifc->ndev)
177176
netif_wake_queue(ifc->ndev);
178177
}
179-
mutex_unlock(&wl->vif_mutex);
178+
srcu_read_unlock(&wl->srcu, srcu_idx);
180179
}
181180
} while (ret == -ENOBUFS && !wl->close);
182181
}
@@ -725,14 +724,15 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
725724
wilc_tx_complete);
726725

727726
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
728-
int i;
727+
int srcu_idx;
728+
struct wilc_vif *vif;
729729

730-
mutex_lock(&wilc->vif_mutex);
731-
for (i = 0; i < wilc->vif_num; i++) {
732-
if (wilc->vif[i]->mac_opened)
733-
netif_stop_queue(wilc->vif[i]->ndev);
730+
srcu_idx = srcu_read_lock(&wilc->srcu);
731+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
732+
if (vif->mac_opened)
733+
netif_stop_queue(vif->ndev);
734734
}
735-
mutex_unlock(&wilc->vif_mutex);
735+
srcu_read_unlock(&wilc->srcu, srcu_idx);
736736
}
737737

738738
return 0;
@@ -810,14 +810,13 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
810810

811811
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
812812
{
813-
int i = 0;
813+
int srcu_idx;
814814
struct wilc_vif *vif;
815815

816-
mutex_lock(&wilc->vif_mutex);
817-
for (i = 0; i < wilc->vif_num; i++) {
816+
srcu_idx = srcu_read_lock(&wilc->srcu);
817+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
818818
u16 type = le16_to_cpup((__le16 *)buff);
819819

820-
vif = netdev_priv(wilc->vif[i]->ndev);
821820
if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
822821
(type == vif->frame_reg[1].type && vif->frame_reg[1].reg)) {
823822
wilc_wfi_p2p_rx(vif, buff, size);
@@ -829,7 +828,7 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
829828
break;
830829
}
831830
}
832-
mutex_unlock(&wilc->vif_mutex);
831+
srcu_read_unlock(&wilc->srcu, srcu_idx);
833832
}
834833

835834
static const struct net_device_ops wilc_netdev_ops = {
@@ -843,7 +842,8 @@ static const struct net_device_ops wilc_netdev_ops = {
843842

844843
void wilc_netdev_cleanup(struct wilc *wilc)
845844
{
846-
int i;
845+
struct wilc_vif *vif;
846+
int srcu_idx;
847847

848848
if (!wilc)
849849
return;
@@ -853,14 +853,32 @@ void wilc_netdev_cleanup(struct wilc *wilc)
853853
wilc->firmware = NULL;
854854
}
855855

856-
for (i = 0; i < wilc->vif_num; i++) {
857-
if (wilc->vif[i] && wilc->vif[i]->ndev)
858-
unregister_netdev(wilc->vif[i]->ndev);
856+
srcu_idx = srcu_read_lock(&wilc->srcu);
857+
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
858+
if (vif->ndev)
859+
unregister_netdev(vif->ndev);
859860
}
861+
srcu_read_unlock(&wilc->srcu, srcu_idx);
860862

861863
wilc_wfi_deinit_mon_interface(wilc, false);
862864
flush_workqueue(wilc->hif_workqueue);
863865
destroy_workqueue(wilc->hif_workqueue);
866+
867+
do {
868+
mutex_lock(&wilc->vif_mutex);
869+
if (wilc->vif_num <= 0) {
870+
mutex_unlock(&wilc->vif_mutex);
871+
break;
872+
}
873+
vif = wilc_get_wl_to_vif(wilc);
874+
if (!IS_ERR(vif))
875+
list_del_rcu(&vif->list);
876+
877+
wilc->vif_num--;
878+
mutex_unlock(&wilc->vif_mutex);
879+
synchronize_srcu(&wilc->srcu);
880+
} while (1);
881+
864882
wilc_wlan_cfg_deinit(wilc);
865883
wlan_deinit_locks(wilc);
866884
kfree(wilc->bus_data);
@@ -869,6 +887,23 @@ void wilc_netdev_cleanup(struct wilc *wilc)
869887
}
870888
EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
871889

890+
static u8 wilc_get_available_idx(struct wilc *wl)
891+
{
892+
int idx = 0;
893+
struct wilc_vif *vif;
894+
int srcu_idx;
895+
896+
srcu_idx = srcu_read_lock(&wl->srcu);
897+
list_for_each_entry_rcu(vif, &wl->vif_list, list) {
898+
if (vif->idx == 0)
899+
idx = 1;
900+
else
901+
idx = 0;
902+
}
903+
srcu_read_unlock(&wl->srcu, srcu_idx);
904+
return idx;
905+
}
906+
872907
struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
873908
int vif_type, enum nl80211_iftype type,
874909
bool rtnl_locked)
@@ -909,10 +944,14 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
909944

910945
ndev->needs_free_netdev = true;
911946
vif->iftype = vif_type;
912-
vif->wilc->vif[wl->vif_num] = vif;
913-
vif->idx = wl->vif_num;
914-
wl->vif_num += 1;
947+
vif->idx = wilc_get_available_idx(wl);
915948
vif->mac_opened = 0;
949+
mutex_lock(&wl->vif_mutex);
950+
list_add_tail_rcu(&vif->list, &wl->vif_list);
951+
wl->vif_num += 1;
952+
mutex_unlock(&wl->vif_mutex);
953+
synchronize_srcu(&wl->srcu);
954+
916955
return vif;
917956
}
918957

0 commit comments

Comments
 (0)