@@ -97,29 +97,25 @@ void wilc_mac_indicate(struct wilc *wilc)
97
97
static struct net_device * get_if_handler (struct wilc * wilc , u8 * mac_header )
98
98
{
99
99
u8 * bssid , * bssid1 ;
100
- int i = 0 ;
101
100
struct net_device * ndev = NULL ;
101
+ struct wilc_vif * vif ;
102
102
103
103
bssid = mac_header + 10 ;
104
104
bssid1 = mac_header + 4 ;
105
105
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 ;
112
110
goto out ;
113
111
}
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 ;
118
115
goto out ;
119
116
}
120
117
}
121
118
out :
122
- mutex_unlock (& wilc -> vif_mutex );
123
119
return ndev ;
124
120
}
125
121
@@ -137,13 +133,16 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
137
133
138
134
int wilc_wlan_get_num_conn_ifcs (struct wilc * wilc )
139
135
{
140
- u8 i = 0 ;
136
+ int srcu_idx ;
141
137
u8 ret_val = 0 ;
138
+ struct wilc_vif * vif ;
142
139
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 ))
145
143
ret_val ++ ;
146
-
144
+ }
145
+ srcu_read_unlock (& wilc -> srcu , srcu_idx );
147
146
return ret_val ;
148
147
}
149
148
@@ -167,16 +166,16 @@ static int wilc_txq_task(void *vp)
167
166
do {
168
167
ret = wilc_wlan_handle_txq (wl , & txq_count );
169
168
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD ) {
170
- int i ;
169
+ int srcu_idx ;
171
170
struct wilc_vif * ifc ;
172
171
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 ) {
176
175
if (ifc -> mac_opened && ifc -> ndev )
177
176
netif_wake_queue (ifc -> ndev );
178
177
}
179
- mutex_unlock (& wl -> vif_mutex );
178
+ srcu_read_unlock (& wl -> srcu , srcu_idx );
180
179
}
181
180
} while (ret == - ENOBUFS && !wl -> close );
182
181
}
@@ -725,14 +724,15 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
725
724
wilc_tx_complete );
726
725
727
726
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD ) {
728
- int i ;
727
+ int srcu_idx ;
728
+ struct wilc_vif * vif ;
729
729
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 );
734
734
}
735
- mutex_unlock (& wilc -> vif_mutex );
735
+ srcu_read_unlock (& wilc -> srcu , srcu_idx );
736
736
}
737
737
738
738
return 0 ;
@@ -810,14 +810,13 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
810
810
811
811
void wilc_wfi_mgmt_rx (struct wilc * wilc , u8 * buff , u32 size )
812
812
{
813
- int i = 0 ;
813
+ int srcu_idx ;
814
814
struct wilc_vif * vif ;
815
815
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 ) {
818
818
u16 type = le16_to_cpup ((__le16 * )buff );
819
819
820
- vif = netdev_priv (wilc -> vif [i ]-> ndev );
821
820
if ((type == vif -> frame_reg [0 ].type && vif -> frame_reg [0 ].reg ) ||
822
821
(type == vif -> frame_reg [1 ].type && vif -> frame_reg [1 ].reg )) {
823
822
wilc_wfi_p2p_rx (vif , buff , size );
@@ -829,7 +828,7 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
829
828
break ;
830
829
}
831
830
}
832
- mutex_unlock (& wilc -> vif_mutex );
831
+ srcu_read_unlock (& wilc -> srcu , srcu_idx );
833
832
}
834
833
835
834
static const struct net_device_ops wilc_netdev_ops = {
@@ -843,7 +842,8 @@ static const struct net_device_ops wilc_netdev_ops = {
843
842
844
843
void wilc_netdev_cleanup (struct wilc * wilc )
845
844
{
846
- int i ;
845
+ struct wilc_vif * vif ;
846
+ int srcu_idx ;
847
847
848
848
if (!wilc )
849
849
return ;
@@ -853,14 +853,32 @@ void wilc_netdev_cleanup(struct wilc *wilc)
853
853
wilc -> firmware = NULL ;
854
854
}
855
855
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 );
859
860
}
861
+ srcu_read_unlock (& wilc -> srcu , srcu_idx );
860
862
861
863
wilc_wfi_deinit_mon_interface (wilc , false);
862
864
flush_workqueue (wilc -> hif_workqueue );
863
865
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
+
864
882
wilc_wlan_cfg_deinit (wilc );
865
883
wlan_deinit_locks (wilc );
866
884
kfree (wilc -> bus_data );
@@ -869,6 +887,23 @@ void wilc_netdev_cleanup(struct wilc *wilc)
869
887
}
870
888
EXPORT_SYMBOL_GPL (wilc_netdev_cleanup );
871
889
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
+
872
907
struct wilc_vif * wilc_netdev_ifc_init (struct wilc * wl , const char * name ,
873
908
int vif_type , enum nl80211_iftype type ,
874
909
bool rtnl_locked )
@@ -909,10 +944,14 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
909
944
910
945
ndev -> needs_free_netdev = true;
911
946
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 );
915
948
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
+
916
955
return vif ;
917
956
}
918
957
0 commit comments