aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorSergey Matyukevich <sergey.matyukevich.os@quantenna.com>2019-07-26 12:39:32 -0400
committerJohannes Berg <johannes.berg@intel.com>2019-07-29 10:23:13 -0400
commit3ab8227d3e7d1d2bf1829675d3197e3cb600e9f6 (patch)
tree59b3caf719a31d0f9a63086d636242894979f9e0 /net/wireless/scan.c
parentae6fa4d5e94ea520506b691140ebcb5dc6bf0a17 (diff)
cfg80211: refactor cfg80211_bss_update
This patch implements minor refactoring for cfg80211_bss_update function. Code path for updating known BSS is extracted into dedicated cfg80211_update_known_bss function. Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> Link: https://lore.kernel.org/r/20190726163922.27509-2-sergey.matyukevich.os@quantenna.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c171
1 files changed, 89 insertions, 82 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index a98dabab557a..9119f5ce3677 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss {
1091 u8 bssid_index; 1091 u8 bssid_index;
1092}; 1092};
1093 1093
1094static bool
1095cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
1096 struct cfg80211_internal_bss *known,
1097 struct cfg80211_internal_bss *new,
1098 bool signal_valid)
1099{
1100 lockdep_assert_held(&rdev->bss_lock);
1101
1102 /* Update IEs */
1103 if (rcu_access_pointer(new->pub.proberesp_ies)) {
1104 const struct cfg80211_bss_ies *old;
1105
1106 old = rcu_access_pointer(known->pub.proberesp_ies);
1107
1108 rcu_assign_pointer(known->pub.proberesp_ies,
1109 new->pub.proberesp_ies);
1110 /* Override possible earlier Beacon frame IEs */
1111 rcu_assign_pointer(known->pub.ies,
1112 new->pub.proberesp_ies);
1113 if (old)
1114 kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
1115 } else if (rcu_access_pointer(new->pub.beacon_ies)) {
1116 const struct cfg80211_bss_ies *old;
1117 struct cfg80211_internal_bss *bss;
1118
1119 if (known->pub.hidden_beacon_bss &&
1120 !list_empty(&known->hidden_list)) {
1121 const struct cfg80211_bss_ies *f;
1122
1123 /* The known BSS struct is one of the probe
1124 * response members of a group, but we're
1125 * receiving a beacon (beacon_ies in the new
1126 * bss is used). This can only mean that the
1127 * AP changed its beacon from not having an
1128 * SSID to showing it, which is confusing so
1129 * drop this information.
1130 */
1131
1132 f = rcu_access_pointer(new->pub.beacon_ies);
1133 kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
1134 return false;
1135 }
1136
1137 old = rcu_access_pointer(known->pub.beacon_ies);
1138
1139 rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies);
1140
1141 /* Override IEs if they were from a beacon before */
1142 if (old == rcu_access_pointer(known->pub.ies))
1143 rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies);
1144
1145 /* Assign beacon IEs to all sub entries */
1146 list_for_each_entry(bss, &known->hidden_list, hidden_list) {
1147 const struct cfg80211_bss_ies *ies;
1148
1149 ies = rcu_access_pointer(bss->pub.beacon_ies);
1150 WARN_ON(ies != old);
1151
1152 rcu_assign_pointer(bss->pub.beacon_ies,
1153 new->pub.beacon_ies);
1154 }
1155
1156 if (old)
1157 kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
1158 }
1159
1160 known->pub.beacon_interval = new->pub.beacon_interval;
1161
1162 /* don't update the signal if beacon was heard on
1163 * adjacent channel.
1164 */
1165 if (signal_valid)
1166 known->pub.signal = new->pub.signal;
1167 known->pub.capability = new->pub.capability;
1168 known->ts = new->ts;
1169 known->ts_boottime = new->ts_boottime;
1170 known->parent_tsf = new->parent_tsf;
1171 known->pub.chains = new->pub.chains;
1172 memcpy(known->pub.chain_signal, new->pub.chain_signal,
1173 IEEE80211_MAX_CHAINS);
1174 ether_addr_copy(known->parent_bssid, new->parent_bssid);
1175 known->pub.max_bssid_indicator = new->pub.max_bssid_indicator;
1176 known->pub.bssid_index = new->pub.bssid_index;
1177
1178 return true;
1179}
1180
1094/* Returned bss is reference counted and must be cleaned up appropriately. */ 1181/* Returned bss is reference counted and must be cleaned up appropriately. */
1095struct cfg80211_internal_bss * 1182struct cfg80211_internal_bss *
1096cfg80211_bss_update(struct cfg80211_registered_device *rdev, 1183cfg80211_bss_update(struct cfg80211_registered_device *rdev,
@@ -1114,88 +1201,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
1114 found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR); 1201 found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR);
1115 1202
1116 if (found) { 1203 if (found) {
1117 /* Update IEs */ 1204 if (!cfg80211_update_known_bss(rdev, found, tmp, signal_valid))
1118 if (rcu_access_pointer(tmp->pub.proberesp_ies)) { 1205 goto drop;
1119 const struct cfg80211_bss_ies *old;
1120
1121 old = rcu_access_pointer(found->pub.proberesp_ies);
1122
1123 rcu_assign_pointer(found->pub.proberesp_ies,
1124 tmp->pub.proberesp_ies);
1125 /* Override possible earlier Beacon frame IEs */
1126 rcu_assign_pointer(found->pub.ies,
1127 tmp->pub.proberesp_ies);
1128 if (old)
1129 kfree_rcu((struct cfg80211_bss_ies *)old,
1130 rcu_head);
1131 } else if (rcu_access_pointer(tmp->pub.beacon_ies)) {
1132 const struct cfg80211_bss_ies *old;
1133 struct cfg80211_internal_bss *bss;
1134
1135 if (found->pub.hidden_beacon_bss &&
1136 !list_empty(&found->hidden_list)) {
1137 const struct cfg80211_bss_ies *f;
1138
1139 /*
1140 * The found BSS struct is one of the probe
1141 * response members of a group, but we're
1142 * receiving a beacon (beacon_ies in the tmp
1143 * bss is used). This can only mean that the
1144 * AP changed its beacon from not having an
1145 * SSID to showing it, which is confusing so
1146 * drop this information.
1147 */
1148
1149 f = rcu_access_pointer(tmp->pub.beacon_ies);
1150 kfree_rcu((struct cfg80211_bss_ies *)f,
1151 rcu_head);
1152 goto drop;
1153 }
1154
1155 old = rcu_access_pointer(found->pub.beacon_ies);
1156
1157 rcu_assign_pointer(found->pub.beacon_ies,
1158 tmp->pub.beacon_ies);
1159
1160 /* Override IEs if they were from a beacon before */
1161 if (old == rcu_access_pointer(found->pub.ies))
1162 rcu_assign_pointer(found->pub.ies,
1163 tmp->pub.beacon_ies);
1164
1165 /* Assign beacon IEs to all sub entries */
1166 list_for_each_entry(bss, &found->hidden_list,
1167 hidden_list) {
1168 const struct cfg80211_bss_ies *ies;
1169
1170 ies = rcu_access_pointer(bss->pub.beacon_ies);
1171 WARN_ON(ies != old);
1172
1173 rcu_assign_pointer(bss->pub.beacon_ies,
1174 tmp->pub.beacon_ies);
1175 }
1176
1177 if (old)
1178 kfree_rcu((struct cfg80211_bss_ies *)old,
1179 rcu_head);
1180 }
1181
1182 found->pub.beacon_interval = tmp->pub.beacon_interval;
1183 /*
1184 * don't update the signal if beacon was heard on
1185 * adjacent channel.
1186 */
1187 if (signal_valid)
1188 found->pub.signal = tmp->pub.signal;
1189 found->pub.capability = tmp->pub.capability;
1190 found->ts = tmp->ts;
1191 found->ts_boottime = tmp->ts_boottime;
1192 found->parent_tsf = tmp->parent_tsf;
1193 found->pub.chains = tmp->pub.chains;
1194 memcpy(found->pub.chain_signal, tmp->pub.chain_signal,
1195 IEEE80211_MAX_CHAINS);
1196 ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
1197 found->pub.max_bssid_indicator = tmp->pub.max_bssid_indicator;
1198 found->pub.bssid_index = tmp->pub.bssid_index;
1199 } else { 1206 } else {
1200 struct cfg80211_internal_bss *new; 1207 struct cfg80211_internal_bss *new;
1201 struct cfg80211_internal_bss *hidden; 1208 struct cfg80211_internal_bss *hidden;