diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-10-15 16:11:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-10-15 16:11:56 -0400 |
commit | c64557d666eb62eb5f296c6b93bd0a5525ed1e36 (patch) | |
tree | 1e25cc32521d06ae876de18bb8e48b3cf9d30808 /net/wireless | |
parent | 1a63c353c856c9f6d44a533afb6ad6dbbcdea683 (diff) | |
parent | 0d91f22b75347d9503b17a42b6c74d3f7750acd6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 54 | ||||
-rw-r--r-- | net/wireless/mlme.c | 23 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 15 | ||||
-rw-r--r-- | net/wireless/radiotap.c | 58 | ||||
-rw-r--r-- | net/wireless/sysfs.c | 9 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 4 |
6 files changed, 104 insertions, 59 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 1684ad91763c..9c21ebf9780e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -178,10 +178,26 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
178 | char *newname) | 178 | char *newname) |
179 | { | 179 | { |
180 | struct cfg80211_registered_device *rdev2; | 180 | struct cfg80211_registered_device *rdev2; |
181 | int result; | 181 | int wiphy_idx, taken = -1, result, digits; |
182 | 182 | ||
183 | assert_cfg80211_lock(); | 183 | assert_cfg80211_lock(); |
184 | 184 | ||
185 | /* prohibit calling the thing phy%d when %d is not its number */ | ||
186 | sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); | ||
187 | if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { | ||
188 | /* count number of places needed to print wiphy_idx */ | ||
189 | digits = 1; | ||
190 | while (wiphy_idx /= 10) | ||
191 | digits++; | ||
192 | /* | ||
193 | * deny the name if it is phy<idx> where <idx> is printed | ||
194 | * without leading zeroes. taken == strlen(newname) here | ||
195 | */ | ||
196 | if (taken == strlen(PHY_NAME) + digits) | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | |||
185 | /* Ignore nop renames */ | 201 | /* Ignore nop renames */ |
186 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) | 202 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) |
187 | return 0; | 203 | return 0; |
@@ -189,7 +205,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
189 | /* Ensure another device does not already have this name. */ | 205 | /* Ensure another device does not already have this name. */ |
190 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) | 206 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) |
191 | if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) | 207 | if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) |
192 | return -EEXIST; | 208 | return -EINVAL; |
193 | 209 | ||
194 | result = device_rename(&rdev->wiphy.dev, newname); | 210 | result = device_rename(&rdev->wiphy.dev, newname); |
195 | if (result) | 211 | if (result) |
@@ -304,11 +320,9 @@ static void cfg80211_event_work(struct work_struct *work) | |||
304 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | 320 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) |
305 | { | 321 | { |
306 | static int wiphy_counter; | 322 | static int wiphy_counter; |
307 | int i; | 323 | |
308 | struct cfg80211_registered_device *rdev, *rdev2; | 324 | struct cfg80211_registered_device *rdev; |
309 | int alloc_size; | 325 | int alloc_size; |
310 | char nname[IFNAMSIZ + 1]; | ||
311 | bool found = false; | ||
312 | 326 | ||
313 | WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); | 327 | WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); |
314 | WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); | 328 | WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); |
@@ -332,37 +346,17 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
332 | 346 | ||
333 | if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { | 347 | if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { |
334 | wiphy_counter--; | 348 | wiphy_counter--; |
335 | goto too_many_devs; | ||
336 | } | ||
337 | |||
338 | /* 64k wiphy devices is enough for anyone! */ | ||
339 | for (i = 0; i < 0xFFFF; i++) { | ||
340 | found = false; | ||
341 | snprintf(nname, sizeof(nname)-1, PHY_NAME "%d", i); | ||
342 | nname[sizeof(nname)-1] = 0; | ||
343 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) | ||
344 | if (strcmp(nname, dev_name(&rdev2->wiphy.dev)) == 0) { | ||
345 | found = true; | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | if (!found) | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | if (unlikely(found)) { | ||
354 | too_many_devs: | ||
355 | mutex_unlock(&cfg80211_mutex); | 349 | mutex_unlock(&cfg80211_mutex); |
356 | /* ugh, too many devices already! */ | 350 | /* ugh, wrapped! */ |
357 | kfree(rdev); | 351 | kfree(rdev); |
358 | return NULL; | 352 | return NULL; |
359 | } | 353 | } |
360 | 354 | ||
361 | /* give it a proper name */ | ||
362 | dev_set_name(&rdev->wiphy.dev, "%s", nname); | ||
363 | |||
364 | mutex_unlock(&cfg80211_mutex); | 355 | mutex_unlock(&cfg80211_mutex); |
365 | 356 | ||
357 | /* give it a proper name */ | ||
358 | dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); | ||
359 | |||
366 | mutex_init(&rdev->mtx); | 360 | mutex_init(&rdev->mtx); |
367 | mutex_init(&rdev->devlist_mtx); | 361 | mutex_init(&rdev->devlist_mtx); |
368 | INIT_LIST_HEAD(&rdev->netdev_list); | 362 | INIT_LIST_HEAD(&rdev->netdev_list); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index caf11a427507..26838d903b9a 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -764,6 +764,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, | |||
764 | u16 frame_type, const u8 *match_data, | 764 | u16 frame_type, const u8 *match_data, |
765 | int match_len) | 765 | int match_len) |
766 | { | 766 | { |
767 | struct wiphy *wiphy = wdev->wiphy; | ||
768 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
767 | struct cfg80211_mgmt_registration *reg, *nreg; | 769 | struct cfg80211_mgmt_registration *reg, *nreg; |
768 | int err = 0; | 770 | int err = 0; |
769 | u16 mgmt_type; | 771 | u16 mgmt_type; |
@@ -810,22 +812,37 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, | |||
810 | nreg->frame_type = cpu_to_le16(frame_type); | 812 | nreg->frame_type = cpu_to_le16(frame_type); |
811 | list_add(&nreg->list, &wdev->mgmt_registrations); | 813 | list_add(&nreg->list, &wdev->mgmt_registrations); |
812 | 814 | ||
815 | if (rdev->ops->mgmt_frame_register) | ||
816 | rdev->ops->mgmt_frame_register(wiphy, wdev->netdev, | ||
817 | frame_type, true); | ||
818 | |||
813 | out: | 819 | out: |
814 | spin_unlock_bh(&wdev->mgmt_registrations_lock); | 820 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
821 | |||
815 | return err; | 822 | return err; |
816 | } | 823 | } |
817 | 824 | ||
818 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) | 825 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) |
819 | { | 826 | { |
827 | struct wiphy *wiphy = wdev->wiphy; | ||
828 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
820 | struct cfg80211_mgmt_registration *reg, *tmp; | 829 | struct cfg80211_mgmt_registration *reg, *tmp; |
821 | 830 | ||
822 | spin_lock_bh(&wdev->mgmt_registrations_lock); | 831 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
823 | 832 | ||
824 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { | 833 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
825 | if (reg->nlpid == nlpid) { | 834 | if (reg->nlpid != nlpid) |
826 | list_del(®->list); | 835 | continue; |
827 | kfree(reg); | 836 | |
837 | if (rdev->ops->mgmt_frame_register) { | ||
838 | u16 frame_type = le16_to_cpu(reg->frame_type); | ||
839 | |||
840 | rdev->ops->mgmt_frame_register(wiphy, wdev->netdev, | ||
841 | frame_type, false); | ||
828 | } | 842 | } |
843 | |||
844 | list_del(®->list); | ||
845 | kfree(reg); | ||
829 | } | 846 | } |
830 | 847 | ||
831 | spin_unlock_bh(&wdev->mgmt_registrations_lock); | 848 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 882dc921103b..c506241f8637 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3153,6 +3153,21 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, | |||
3153 | survey->noise); | 3153 | survey->noise); |
3154 | if (survey->filled & SURVEY_INFO_IN_USE) | 3154 | if (survey->filled & SURVEY_INFO_IN_USE) |
3155 | NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); | 3155 | NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); |
3156 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME) | ||
3157 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, | ||
3158 | survey->channel_time); | ||
3159 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) | ||
3160 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, | ||
3161 | survey->channel_time_busy); | ||
3162 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) | ||
3163 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, | ||
3164 | survey->channel_time_ext_busy); | ||
3165 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) | ||
3166 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, | ||
3167 | survey->channel_time_rx); | ||
3168 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) | ||
3169 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, | ||
3170 | survey->channel_time_tx); | ||
3156 | 3171 | ||
3157 | nla_nest_end(msg, infoattr); | 3172 | nla_nest_end(msg, infoattr); |
3158 | 3173 | ||
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c774bc0f155e..dbe35e138e94 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -201,7 +201,7 @@ int ieee80211_radiotap_iterator_next( | |||
201 | { | 201 | { |
202 | while (1) { | 202 | while (1) { |
203 | int hit = 0; | 203 | int hit = 0; |
204 | int pad, align, size, subns, vnslen; | 204 | int pad, align, size, subns; |
205 | uint32_t oui; | 205 | uint32_t oui; |
206 | 206 | ||
207 | /* if no more EXT bits, that's it */ | 207 | /* if no more EXT bits, that's it */ |
@@ -261,6 +261,27 @@ int ieee80211_radiotap_iterator_next( | |||
261 | if (pad) | 261 | if (pad) |
262 | iterator->_arg += align - pad; | 262 | iterator->_arg += align - pad; |
263 | 263 | ||
264 | if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { | ||
265 | int vnslen; | ||
266 | |||
267 | if ((unsigned long)iterator->_arg + size - | ||
268 | (unsigned long)iterator->_rtheader > | ||
269 | (unsigned long)iterator->_max_length) | ||
270 | return -EINVAL; | ||
271 | |||
272 | oui = (*iterator->_arg << 16) | | ||
273 | (*(iterator->_arg + 1) << 8) | | ||
274 | *(iterator->_arg + 2); | ||
275 | subns = *(iterator->_arg + 3); | ||
276 | |||
277 | find_ns(iterator, oui, subns); | ||
278 | |||
279 | vnslen = get_unaligned_le16(iterator->_arg + 4); | ||
280 | iterator->_next_ns_data = iterator->_arg + size + vnslen; | ||
281 | if (!iterator->current_namespace) | ||
282 | size += vnslen; | ||
283 | } | ||
284 | |||
264 | /* | 285 | /* |
265 | * this is what we will return to user, but we need to | 286 | * this is what we will return to user, but we need to |
266 | * move on first so next call has something fresh to test | 287 | * move on first so next call has something fresh to test |
@@ -287,40 +308,25 @@ int ieee80211_radiotap_iterator_next( | |||
287 | /* these special ones are valid in each bitmap word */ | 308 | /* these special ones are valid in each bitmap word */ |
288 | switch (iterator->_arg_index % 32) { | 309 | switch (iterator->_arg_index % 32) { |
289 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: | 310 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: |
290 | iterator->_bitmap_shifter >>= 1; | ||
291 | iterator->_arg_index++; | ||
292 | |||
293 | iterator->_reset_on_ext = 1; | 311 | iterator->_reset_on_ext = 1; |
294 | 312 | ||
295 | vnslen = get_unaligned_le16(iterator->this_arg + 4); | ||
296 | iterator->_next_ns_data = iterator->_arg + vnslen; | ||
297 | oui = (*iterator->this_arg << 16) | | ||
298 | (*(iterator->this_arg + 1) << 8) | | ||
299 | *(iterator->this_arg + 2); | ||
300 | subns = *(iterator->this_arg + 3); | ||
301 | |||
302 | find_ns(iterator, oui, subns); | ||
303 | |||
304 | iterator->is_radiotap_ns = 0; | 313 | iterator->is_radiotap_ns = 0; |
305 | /* allow parsers to show this information */ | 314 | /* |
315 | * If parser didn't register this vendor | ||
316 | * namespace with us, allow it to show it | ||
317 | * as 'raw. Do do that, set argument index | ||
318 | * to vendor namespace. | ||
319 | */ | ||
306 | iterator->this_arg_index = | 320 | iterator->this_arg_index = |
307 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE; | 321 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE; |
308 | iterator->this_arg_size += vnslen; | 322 | if (!iterator->current_namespace) |
309 | if ((unsigned long)iterator->this_arg + | 323 | hit = 1; |
310 | iterator->this_arg_size - | 324 | goto next_entry; |
311 | (unsigned long)iterator->_rtheader > | ||
312 | (unsigned long)(unsigned long)iterator->_max_length) | ||
313 | return -EINVAL; | ||
314 | hit = 1; | ||
315 | break; | ||
316 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: | 325 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: |
317 | iterator->_bitmap_shifter >>= 1; | ||
318 | iterator->_arg_index++; | ||
319 | |||
320 | iterator->_reset_on_ext = 1; | 326 | iterator->_reset_on_ext = 1; |
321 | iterator->current_namespace = &radiotap_ns; | 327 | iterator->current_namespace = &radiotap_ns; |
322 | iterator->is_radiotap_ns = 1; | 328 | iterator->is_radiotap_ns = 1; |
323 | break; | 329 | goto next_entry; |
324 | case IEEE80211_RADIOTAP_EXT: | 330 | case IEEE80211_RADIOTAP_EXT: |
325 | /* | 331 | /* |
326 | * bit 31 was set, there is more | 332 | * bit 31 was set, there is more |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 74a9e3cce452..4294fa22bb2d 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -35,6 +35,14 @@ SHOW_FMT(index, "%d", wiphy_idx); | |||
35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); | 35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); |
36 | SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); | 36 | SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); |
37 | 37 | ||
38 | static ssize_t name_show(struct device *dev, | ||
39 | struct device_attribute *attr, | ||
40 | char *buf) { | ||
41 | struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; | ||
42 | return sprintf(buf, "%s\n", dev_name(&wiphy->dev)); | ||
43 | } | ||
44 | |||
45 | |||
38 | static ssize_t addresses_show(struct device *dev, | 46 | static ssize_t addresses_show(struct device *dev, |
39 | struct device_attribute *attr, | 47 | struct device_attribute *attr, |
40 | char *buf) | 48 | char *buf) |
@@ -57,6 +65,7 @@ static struct device_attribute ieee80211_dev_attrs[] = { | |||
57 | __ATTR_RO(macaddress), | 65 | __ATTR_RO(macaddress), |
58 | __ATTR_RO(address_mask), | 66 | __ATTR_RO(address_mask), |
59 | __ATTR_RO(addresses), | 67 | __ATTR_RO(addresses), |
68 | __ATTR_RO(name), | ||
60 | {} | 69 | {} |
61 | }; | 70 | }; |
62 | 71 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6002265289c6..12222ee6ebf2 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1366,6 +1366,10 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; | 1368 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; |
1369 | if (sinfo.filled & STATION_INFO_RX_DROP_MISC) | ||
1370 | wstats.discard.misc = sinfo.rx_dropped_misc; | ||
1371 | if (sinfo.filled & STATION_INFO_TX_FAILED) | ||
1372 | wstats.discard.retries = sinfo.tx_failed; | ||
1369 | 1373 | ||
1370 | return &wstats; | 1374 | return &wstats; |
1371 | } | 1375 | } |