diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-06-12 14:25:04 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-12 14:25:04 -0400 |
commit | 0440507bbc44149e63bbfb9df730ba3820371904 (patch) | |
tree | 7275e41aa1aa7e4d19d0503f1c15f07991c1a120 /net | |
parent | 8d242488ce4627dd7e6333caab56df11ea25e239 (diff) | |
parent | 7f0d9f430dc99303558adc30a75eef10c43f7bec (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net')
46 files changed, 1644 insertions, 1633 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index fdf9e61d0651..72607174ea5a 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -417,72 +417,6 @@ static struct attribute_group netstat_group = { | |||
417 | .name = "statistics", | 417 | .name = "statistics", |
418 | .attrs = netstat_attrs, | 418 | .attrs = netstat_attrs, |
419 | }; | 419 | }; |
420 | |||
421 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | ||
422 | /* helper function that does all the locking etc for wireless stats */ | ||
423 | static ssize_t wireless_show(struct device *d, char *buf, | ||
424 | ssize_t (*format)(const struct iw_statistics *, | ||
425 | char *)) | ||
426 | { | ||
427 | struct net_device *dev = to_net_dev(d); | ||
428 | const struct iw_statistics *iw; | ||
429 | ssize_t ret = -EINVAL; | ||
430 | |||
431 | if (!rtnl_trylock()) | ||
432 | return restart_syscall(); | ||
433 | if (dev_isalive(dev)) { | ||
434 | iw = get_wireless_stats(dev); | ||
435 | if (iw) | ||
436 | ret = (*format)(iw, buf); | ||
437 | } | ||
438 | rtnl_unlock(); | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | /* show function template for wireless fields */ | ||
444 | #define WIRELESS_SHOW(name, field, format_string) \ | ||
445 | static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \ | ||
446 | { \ | ||
447 | return sprintf(buf, format_string, iw->field); \ | ||
448 | } \ | ||
449 | static ssize_t show_iw_##name(struct device *d, \ | ||
450 | struct device_attribute *attr, char *buf) \ | ||
451 | { \ | ||
452 | return wireless_show(d, buf, format_iw_##name); \ | ||
453 | } \ | ||
454 | static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) | ||
455 | |||
456 | WIRELESS_SHOW(status, status, fmt_hex); | ||
457 | WIRELESS_SHOW(link, qual.qual, fmt_dec); | ||
458 | WIRELESS_SHOW(level, qual.level, fmt_dec); | ||
459 | WIRELESS_SHOW(noise, qual.noise, fmt_dec); | ||
460 | WIRELESS_SHOW(nwid, discard.nwid, fmt_dec); | ||
461 | WIRELESS_SHOW(crypt, discard.code, fmt_dec); | ||
462 | WIRELESS_SHOW(fragment, discard.fragment, fmt_dec); | ||
463 | WIRELESS_SHOW(misc, discard.misc, fmt_dec); | ||
464 | WIRELESS_SHOW(retries, discard.retries, fmt_dec); | ||
465 | WIRELESS_SHOW(beacon, miss.beacon, fmt_dec); | ||
466 | |||
467 | static struct attribute *wireless_attrs[] = { | ||
468 | &dev_attr_status.attr, | ||
469 | &dev_attr_link.attr, | ||
470 | &dev_attr_level.attr, | ||
471 | &dev_attr_noise.attr, | ||
472 | &dev_attr_nwid.attr, | ||
473 | &dev_attr_crypt.attr, | ||
474 | &dev_attr_fragment.attr, | ||
475 | &dev_attr_retries.attr, | ||
476 | &dev_attr_misc.attr, | ||
477 | &dev_attr_beacon.attr, | ||
478 | NULL | ||
479 | }; | ||
480 | |||
481 | static struct attribute_group wireless_group = { | ||
482 | .name = "wireless", | ||
483 | .attrs = wireless_attrs, | ||
484 | }; | ||
485 | #endif | ||
486 | #endif /* CONFIG_SYSFS */ | 420 | #endif /* CONFIG_SYSFS */ |
487 | 421 | ||
488 | #ifdef CONFIG_RPS | 422 | #ifdef CONFIG_RPS |
@@ -1463,14 +1397,6 @@ int netdev_register_kobject(struct net_device *net) | |||
1463 | groups++; | 1397 | groups++; |
1464 | 1398 | ||
1465 | *groups++ = &netstat_group; | 1399 | *groups++ = &netstat_group; |
1466 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | ||
1467 | if (net->ieee80211_ptr) | ||
1468 | *groups++ = &wireless_group; | ||
1469 | #ifdef CONFIG_WIRELESS_EXT | ||
1470 | else if (net->wireless_handlers) | ||
1471 | *groups++ = &wireless_group; | ||
1472 | #endif | ||
1473 | #endif | ||
1474 | #endif /* CONFIG_SYSFS */ | 1400 | #endif /* CONFIG_SYSFS */ |
1475 | 1401 | ||
1476 | error = device_add(dev); | 1402 | error = device_add(dev); |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 3e9d931bba35..2b1470bac178 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -9,7 +9,6 @@ mac80211-y := \ | |||
9 | scan.o offchannel.o \ | 9 | scan.o offchannel.o \ |
10 | ht.o agg-tx.o agg-rx.o \ | 10 | ht.o agg-tx.o agg-rx.o \ |
11 | ibss.o \ | 11 | ibss.o \ |
12 | work.o \ | ||
13 | iface.o \ | 12 | iface.o \ |
14 | rate.o \ | 13 | rate.o \ |
15 | michael.o \ | 14 | michael.o \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index c649188314cc..32ef11d69798 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -74,18 +74,15 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
74 | 74 | ||
75 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); | 75 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); |
76 | 76 | ||
77 | #ifdef CONFIG_MAC80211_HT_DEBUG | 77 | ht_vdbg("Rx BA session stop requested for %pM tid %u %s reason: %d\n", |
78 | printk(KERN_DEBUG | 78 | sta->sta.addr, tid, |
79 | "Rx BA session stop requested for %pM tid %u %s reason: %d\n", | 79 | initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", |
80 | sta->sta.addr, tid, | 80 | (int)reason); |
81 | initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", | ||
82 | (int)reason); | ||
83 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
84 | 81 | ||
85 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 82 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
86 | &sta->sta, tid, NULL, 0)) | 83 | &sta->sta, tid, NULL, 0)) |
87 | printk(KERN_DEBUG "HW problem - can not stop rx " | 84 | pr_debug("HW problem - can not stop rx aggregation for tid %d\n", |
88 | "aggregation for tid %d\n", tid); | 85 | tid); |
89 | 86 | ||
90 | /* check if this is a self generated aggregation halt */ | 87 | /* check if this is a self generated aggregation halt */ |
91 | if (initiator == WLAN_BACK_RECIPIENT && tx) | 88 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
@@ -160,9 +157,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
160 | } | 157 | } |
161 | rcu_read_unlock(); | 158 | rcu_read_unlock(); |
162 | 159 | ||
163 | #ifdef CONFIG_MAC80211_HT_DEBUG | 160 | ht_vdbg("rx session timer expired on tid %d\n", (u16)*ptid); |
164 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 161 | |
165 | #endif | ||
166 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); | 162 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); |
167 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 163 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
168 | } | 164 | } |
@@ -249,10 +245,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
249 | status = WLAN_STATUS_REQUEST_DECLINED; | 245 | status = WLAN_STATUS_REQUEST_DECLINED; |
250 | 246 | ||
251 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 247 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
252 | #ifdef CONFIG_MAC80211_HT_DEBUG | 248 | ht_vdbg("Suspend in progress - Denying ADDBA request\n"); |
253 | printk(KERN_DEBUG "Suspend in progress. " | ||
254 | "Denying ADDBA request\n"); | ||
255 | #endif | ||
256 | goto end_no_lock; | 249 | goto end_no_lock; |
257 | } | 250 | } |
258 | 251 | ||
@@ -324,10 +317,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
324 | 317 | ||
325 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 318 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
326 | &sta->sta, tid, &start_seq_num, 0); | 319 | &sta->sta, tid, &start_seq_num, 0); |
327 | #ifdef CONFIG_MAC80211_HT_DEBUG | 320 | ht_vdbg("Rx A-MPDU request on tid %d result %d\n", tid, ret); |
328 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
329 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
330 | |||
331 | if (ret) { | 321 | if (ret) { |
332 | kfree(tid_agg_rx->reorder_buf); | 322 | kfree(tid_agg_rx->reorder_buf); |
333 | kfree(tid_agg_rx->reorder_time); | 323 | kfree(tid_agg_rx->reorder_time); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 7cf07158805c..da07f01cfe4d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -184,10 +184,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
184 | 184 | ||
185 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
186 | 186 | ||
187 | #ifdef CONFIG_MAC80211_HT_DEBUG | 187 | ht_vdbg("Tx BA session stop requested for %pM tid %u\n", |
188 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", | 188 | sta->sta.addr, tid); |
189 | sta->sta.addr, tid); | ||
190 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
191 | 189 | ||
192 | del_timer_sync(&tid_tx->addba_resp_timer); | 190 | del_timer_sync(&tid_tx->addba_resp_timer); |
193 | del_timer_sync(&tid_tx->session_timer); | 191 | del_timer_sync(&tid_tx->session_timer); |
@@ -253,17 +251,12 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
253 | if (!tid_tx || | 251 | if (!tid_tx || |
254 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { | 252 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { |
255 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
256 | #ifdef CONFIG_MAC80211_HT_DEBUG | 254 | ht_vdbg("timer expired on tid %d but we are not (or no longer) expecting addBA response there\n", |
257 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
258 | "(or no longer) expecting addBA response there\n", | ||
259 | tid); | 255 | tid); |
260 | #endif | ||
261 | return; | 256 | return; |
262 | } | 257 | } |
263 | 258 | ||
264 | #ifdef CONFIG_MAC80211_HT_DEBUG | 259 | ht_vdbg("addBA response timer expired on tid %d\n", tid); |
265 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
266 | #endif | ||
267 | 260 | ||
268 | ieee80211_stop_tx_ba_session(&sta->sta, tid); | 261 | ieee80211_stop_tx_ba_session(&sta->sta, tid); |
269 | rcu_read_unlock(); | 262 | rcu_read_unlock(); |
@@ -372,10 +365,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
372 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 365 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
373 | &sta->sta, tid, &start_seq_num, 0); | 366 | &sta->sta, tid, &start_seq_num, 0); |
374 | if (ret) { | 367 | if (ret) { |
375 | #ifdef CONFIG_MAC80211_HT_DEBUG | 368 | ht_vdbg("BA request denied - HW unavailable for tid %d\n", tid); |
376 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
377 | " tid %d\n", tid); | ||
378 | #endif | ||
379 | spin_lock_bh(&sta->lock); | 369 | spin_lock_bh(&sta->lock); |
380 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); | 370 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
381 | ieee80211_assign_tid_tx(sta, tid, NULL); | 371 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -388,9 +378,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
388 | 378 | ||
389 | /* activate the timer for the recipient's addBA response */ | 379 | /* activate the timer for the recipient's addBA response */ |
390 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 380 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
391 | #ifdef CONFIG_MAC80211_HT_DEBUG | 381 | ht_vdbg("activated addBA response timer on tid %d\n", tid); |
392 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
393 | #endif | ||
394 | 382 | ||
395 | spin_lock_bh(&sta->lock); | 383 | spin_lock_bh(&sta->lock); |
396 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; | 384 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; |
@@ -437,9 +425,7 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
437 | 425 | ||
438 | rcu_read_unlock(); | 426 | rcu_read_unlock(); |
439 | 427 | ||
440 | #ifdef CONFIG_MAC80211_HT_DEBUG | 428 | ht_vdbg("tx session timer expired on tid %d\n", (u16)*ptid); |
441 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | ||
442 | #endif | ||
443 | 429 | ||
444 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); | 430 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); |
445 | } | 431 | } |
@@ -463,10 +449,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
463 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) | 449 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) |
464 | return -EINVAL; | 450 | return -EINVAL; |
465 | 451 | ||
466 | #ifdef CONFIG_MAC80211_HT_DEBUG | 452 | ht_vdbg("Open BA session requested for %pM tid %u\n", |
467 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", | 453 | pubsta->addr, tid); |
468 | pubsta->addr, tid); | ||
469 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
470 | 454 | ||
471 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 455 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
472 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 456 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
@@ -476,10 +460,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
476 | return -EINVAL; | 460 | return -EINVAL; |
477 | 461 | ||
478 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 462 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
479 | #ifdef CONFIG_MAC80211_HT_DEBUG | 463 | ht_vdbg("BA sessions blocked - Denying BA session request\n"); |
480 | printk(KERN_DEBUG "BA sessions blocked. " | ||
481 | "Denying BA session request\n"); | ||
482 | #endif | ||
483 | return -EINVAL; | 464 | return -EINVAL; |
484 | } | 465 | } |
485 | 466 | ||
@@ -497,10 +478,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
497 | */ | 478 | */ |
498 | if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && | 479 | if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && |
499 | !sta->sta.ht_cap.ht_supported) { | 480 | !sta->sta.ht_cap.ht_supported) { |
500 | #ifdef CONFIG_MAC80211_HT_DEBUG | 481 | ht_vdbg("BA request denied - IBSS STA %pM does not advertise HT support\n", |
501 | printk(KERN_DEBUG "BA request denied - IBSS STA %pM" | 482 | pubsta->addr); |
502 | "does not advertise HT support\n", pubsta->addr); | ||
503 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
504 | return -EINVAL; | 483 | return -EINVAL; |
505 | } | 484 | } |
506 | 485 | ||
@@ -520,12 +499,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
520 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES && | 499 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES && |
521 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + | 500 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + |
522 | HT_AGG_RETRIES_PERIOD)) { | 501 | HT_AGG_RETRIES_PERIOD)) { |
523 | #ifdef CONFIG_MAC80211_HT_DEBUG | 502 | ht_vdbg("BA request denied - waiting a grace period after %d failed requests on tid %u\n", |
524 | printk(KERN_DEBUG "BA request denied - " | 503 | sta->ampdu_mlme.addba_req_num[tid], tid); |
525 | "waiting a grace period after %d failed requests " | ||
526 | "on tid %u\n", | ||
527 | sta->ampdu_mlme.addba_req_num[tid], tid); | ||
528 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
529 | ret = -EBUSY; | 504 | ret = -EBUSY; |
530 | goto err_unlock_sta; | 505 | goto err_unlock_sta; |
531 | } | 506 | } |
@@ -533,10 +508,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
533 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 508 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
534 | /* check if the TID is not in aggregation flow already */ | 509 | /* check if the TID is not in aggregation flow already */ |
535 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { | 510 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
536 | #ifdef CONFIG_MAC80211_HT_DEBUG | 511 | ht_vdbg("BA request denied - session is not idle on tid %u\n", |
537 | printk(KERN_DEBUG "BA request denied - session is not " | 512 | tid); |
538 | "idle on tid %u\n", tid); | ||
539 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
540 | ret = -EAGAIN; | 513 | ret = -EAGAIN; |
541 | goto err_unlock_sta; | 514 | goto err_unlock_sta; |
542 | } | 515 | } |
@@ -591,9 +564,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
591 | 564 | ||
592 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 565 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
593 | 566 | ||
594 | #ifdef CONFIG_MAC80211_HT_DEBUG | 567 | ht_vdbg("Aggregation is on for tid %d\n", tid); |
595 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); | ||
596 | #endif | ||
597 | 568 | ||
598 | drv_ampdu_action(local, sta->sdata, | 569 | drv_ampdu_action(local, sta->sdata, |
599 | IEEE80211_AMPDU_TX_OPERATIONAL, | 570 | IEEE80211_AMPDU_TX_OPERATIONAL, |
@@ -627,10 +598,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
627 | trace_api_start_tx_ba_cb(sdata, ra, tid); | 598 | trace_api_start_tx_ba_cb(sdata, ra, tid); |
628 | 599 | ||
629 | if (tid >= STA_TID_NUM) { | 600 | if (tid >= STA_TID_NUM) { |
630 | #ifdef CONFIG_MAC80211_HT_DEBUG | 601 | ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); |
631 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
632 | tid, STA_TID_NUM); | ||
633 | #endif | ||
634 | return; | 602 | return; |
635 | } | 603 | } |
636 | 604 | ||
@@ -638,9 +606,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
638 | sta = sta_info_get_bss(sdata, ra); | 606 | sta = sta_info_get_bss(sdata, ra); |
639 | if (!sta) { | 607 | if (!sta) { |
640 | mutex_unlock(&local->sta_mtx); | 608 | mutex_unlock(&local->sta_mtx); |
641 | #ifdef CONFIG_MAC80211_HT_DEBUG | 609 | ht_vdbg("Could not find station: %pM\n", ra); |
642 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
643 | #endif | ||
644 | return; | 610 | return; |
645 | } | 611 | } |
646 | 612 | ||
@@ -648,9 +614,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
648 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 614 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
649 | 615 | ||
650 | if (WARN_ON(!tid_tx)) { | 616 | if (WARN_ON(!tid_tx)) { |
651 | #ifdef CONFIG_MAC80211_HT_DEBUG | 617 | ht_vdbg("addBA was not requested!\n"); |
652 | printk(KERN_DEBUG "addBA was not requested!\n"); | ||
653 | #endif | ||
654 | goto unlock; | 618 | goto unlock; |
655 | } | 619 | } |
656 | 620 | ||
@@ -750,25 +714,17 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
750 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | 714 | trace_api_stop_tx_ba_cb(sdata, ra, tid); |
751 | 715 | ||
752 | if (tid >= STA_TID_NUM) { | 716 | if (tid >= STA_TID_NUM) { |
753 | #ifdef CONFIG_MAC80211_HT_DEBUG | 717 | ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); |
754 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
755 | tid, STA_TID_NUM); | ||
756 | #endif | ||
757 | return; | 718 | return; |
758 | } | 719 | } |
759 | 720 | ||
760 | #ifdef CONFIG_MAC80211_HT_DEBUG | 721 | ht_vdbg("Stopping Tx BA session for %pM tid %d\n", ra, tid); |
761 | printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", | ||
762 | ra, tid); | ||
763 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
764 | 722 | ||
765 | mutex_lock(&local->sta_mtx); | 723 | mutex_lock(&local->sta_mtx); |
766 | 724 | ||
767 | sta = sta_info_get_bss(sdata, ra); | 725 | sta = sta_info_get_bss(sdata, ra); |
768 | if (!sta) { | 726 | if (!sta) { |
769 | #ifdef CONFIG_MAC80211_HT_DEBUG | 727 | ht_vdbg("Could not find station: %pM\n", ra); |
770 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
771 | #endif | ||
772 | goto unlock; | 728 | goto unlock; |
773 | } | 729 | } |
774 | 730 | ||
@@ -777,9 +733,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
777 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 733 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
778 | 734 | ||
779 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 735 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
780 | #ifdef CONFIG_MAC80211_HT_DEBUG | 736 | ht_vdbg("unexpected callback to A-MPDU stop\n"); |
781 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
782 | #endif | ||
783 | goto unlock_sta; | 737 | goto unlock_sta; |
784 | } | 738 | } |
785 | 739 | ||
@@ -855,17 +809,13 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
855 | goto out; | 809 | goto out; |
856 | 810 | ||
857 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { | 811 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { |
858 | #ifdef CONFIG_MAC80211_HT_DEBUG | 812 | ht_vdbg("wrong addBA response token, tid %d\n", tid); |
859 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
860 | #endif | ||
861 | goto out; | 813 | goto out; |
862 | } | 814 | } |
863 | 815 | ||
864 | del_timer_sync(&tid_tx->addba_resp_timer); | 816 | del_timer_sync(&tid_tx->addba_resp_timer); |
865 | 817 | ||
866 | #ifdef CONFIG_MAC80211_HT_DEBUG | 818 | ht_vdbg("switched off addBA timer for tid %d\n", tid); |
867 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | ||
868 | #endif | ||
869 | 819 | ||
870 | /* | 820 | /* |
871 | * addba_resp_timer may have fired before we got here, and | 821 | * addba_resp_timer may have fired before we got here, and |
@@ -874,11 +824,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
874 | */ | 824 | */ |
875 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | 825 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || |
876 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 826 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
877 | #ifdef CONFIG_MAC80211_HT_DEBUG | 827 | ht_vdbg("got addBA resp for tid %d but we already gave up\n", |
878 | printk(KERN_DEBUG | 828 | tid); |
879 | "got addBA resp for tid %d but we already gave up\n", | ||
880 | tid); | ||
881 | #endif | ||
882 | goto out; | 829 | goto out; |
883 | } | 830 | } |
884 | 831 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e9cecca5c44d..498c94e34427 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -674,6 +674,48 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
674 | return ret; | 674 | return ret; |
675 | } | 675 | } |
676 | 676 | ||
677 | static int ieee80211_set_channel(struct wiphy *wiphy, | ||
678 | struct net_device *netdev, | ||
679 | struct ieee80211_channel *chan, | ||
680 | enum nl80211_channel_type channel_type) | ||
681 | { | ||
682 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
683 | struct ieee80211_sub_if_data *sdata = NULL; | ||
684 | |||
685 | if (netdev) | ||
686 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
687 | |||
688 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
689 | case CHAN_MODE_HOPPING: | ||
690 | return -EBUSY; | ||
691 | case CHAN_MODE_FIXED: | ||
692 | if (local->oper_channel != chan) | ||
693 | return -EBUSY; | ||
694 | if (!sdata && local->_oper_channel_type == channel_type) | ||
695 | return 0; | ||
696 | break; | ||
697 | case CHAN_MODE_UNDEFINED: | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | ||
702 | return -EBUSY; | ||
703 | |||
704 | local->oper_channel = chan; | ||
705 | |||
706 | /* auto-detects changes */ | ||
707 | ieee80211_hw_config(local, 0); | ||
708 | |||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | ||
713 | struct ieee80211_channel *chan, | ||
714 | enum nl80211_channel_type channel_type) | ||
715 | { | ||
716 | return ieee80211_set_channel(wiphy, NULL, chan, channel_type); | ||
717 | } | ||
718 | |||
677 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 719 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
678 | const u8 *resp, size_t resp_len) | 720 | const u8 *resp, size_t resp_len) |
679 | { | 721 | { |
@@ -788,6 +830,11 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
788 | if (old) | 830 | if (old) |
789 | return -EALREADY; | 831 | return -EALREADY; |
790 | 832 | ||
833 | err = ieee80211_set_channel(wiphy, dev, params->channel, | ||
834 | params->channel_type); | ||
835 | if (err) | ||
836 | return err; | ||
837 | |||
791 | /* | 838 | /* |
792 | * Apply control port protocol, this allows us to | 839 | * Apply control port protocol, this allows us to |
793 | * not encrypt dynamic WEP control frames. | 840 | * not encrypt dynamic WEP control frames. |
@@ -1558,6 +1605,12 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1558 | err = copy_mesh_setup(ifmsh, setup); | 1605 | err = copy_mesh_setup(ifmsh, setup); |
1559 | if (err) | 1606 | if (err) |
1560 | return err; | 1607 | return err; |
1608 | |||
1609 | err = ieee80211_set_channel(wiphy, dev, setup->channel, | ||
1610 | setup->channel_type); | ||
1611 | if (err) | ||
1612 | return err; | ||
1613 | |||
1561 | ieee80211_start_mesh(sdata); | 1614 | ieee80211_start_mesh(sdata); |
1562 | 1615 | ||
1563 | return 0; | 1616 | return 0; |
@@ -1677,55 +1730,6 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1677 | return 0; | 1730 | return 0; |
1678 | } | 1731 | } |
1679 | 1732 | ||
1680 | static int ieee80211_set_channel(struct wiphy *wiphy, | ||
1681 | struct net_device *netdev, | ||
1682 | struct ieee80211_channel *chan, | ||
1683 | enum nl80211_channel_type channel_type) | ||
1684 | { | ||
1685 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1686 | struct ieee80211_sub_if_data *sdata = NULL; | ||
1687 | struct ieee80211_channel *old_oper; | ||
1688 | enum nl80211_channel_type old_oper_type; | ||
1689 | enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT; | ||
1690 | |||
1691 | if (netdev) | ||
1692 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
1693 | |||
1694 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
1695 | case CHAN_MODE_HOPPING: | ||
1696 | return -EBUSY; | ||
1697 | case CHAN_MODE_FIXED: | ||
1698 | if (local->oper_channel != chan) | ||
1699 | return -EBUSY; | ||
1700 | if (!sdata && local->_oper_channel_type == channel_type) | ||
1701 | return 0; | ||
1702 | break; | ||
1703 | case CHAN_MODE_UNDEFINED: | ||
1704 | break; | ||
1705 | } | ||
1706 | |||
1707 | if (sdata) | ||
1708 | old_vif_oper_type = sdata->vif.bss_conf.channel_type; | ||
1709 | old_oper_type = local->_oper_channel_type; | ||
1710 | |||
1711 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | ||
1712 | return -EBUSY; | ||
1713 | |||
1714 | old_oper = local->oper_channel; | ||
1715 | local->oper_channel = chan; | ||
1716 | |||
1717 | /* Update driver if changes were actually made. */ | ||
1718 | if ((old_oper != local->oper_channel) || | ||
1719 | (old_oper_type != local->_oper_channel_type)) | ||
1720 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1721 | |||
1722 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
1723 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) | ||
1724 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | ||
1725 | |||
1726 | return 0; | ||
1727 | } | ||
1728 | |||
1729 | #ifdef CONFIG_PM | 1733 | #ifdef CONFIG_PM |
1730 | static int ieee80211_suspend(struct wiphy *wiphy, | 1734 | static int ieee80211_suspend(struct wiphy *wiphy, |
1731 | struct cfg80211_wowlan *wowlan) | 1735 | struct cfg80211_wowlan *wowlan) |
@@ -2108,35 +2112,171 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2108 | return 0; | 2112 | return 0; |
2109 | } | 2113 | } |
2110 | 2114 | ||
2111 | static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, | 2115 | static int ieee80211_start_roc_work(struct ieee80211_local *local, |
2112 | struct net_device *dev, | 2116 | struct ieee80211_sub_if_data *sdata, |
2113 | struct ieee80211_channel *chan, | 2117 | struct ieee80211_channel *channel, |
2114 | enum nl80211_channel_type chantype, | 2118 | enum nl80211_channel_type channel_type, |
2115 | unsigned int duration, u64 *cookie) | 2119 | unsigned int duration, u64 *cookie, |
2120 | struct sk_buff *txskb) | ||
2116 | { | 2121 | { |
2122 | struct ieee80211_roc_work *roc, *tmp; | ||
2123 | bool queued = false; | ||
2117 | int ret; | 2124 | int ret; |
2118 | u32 random_cookie; | ||
2119 | 2125 | ||
2120 | lockdep_assert_held(&local->mtx); | 2126 | lockdep_assert_held(&local->mtx); |
2121 | 2127 | ||
2122 | if (local->hw_roc_cookie) | 2128 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); |
2123 | return -EBUSY; | 2129 | if (!roc) |
2124 | /* must be nonzero */ | 2130 | return -ENOMEM; |
2125 | random_cookie = random32() | 1; | 2131 | |
2126 | 2132 | roc->chan = channel; | |
2127 | *cookie = random_cookie; | 2133 | roc->chan_type = channel_type; |
2128 | local->hw_roc_dev = dev; | 2134 | roc->duration = duration; |
2129 | local->hw_roc_cookie = random_cookie; | 2135 | roc->req_duration = duration; |
2130 | local->hw_roc_channel = chan; | 2136 | roc->frame = txskb; |
2131 | local->hw_roc_channel_type = chantype; | 2137 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2132 | local->hw_roc_duration = duration; | 2138 | roc->sdata = sdata; |
2133 | ret = drv_remain_on_channel(local, chan, chantype, duration); | 2139 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
2140 | INIT_LIST_HEAD(&roc->dependents); | ||
2141 | |||
2142 | /* if there's one pending or we're scanning, queue this one */ | ||
2143 | if (!list_empty(&local->roc_list) || local->scanning) | ||
2144 | goto out_check_combine; | ||
2145 | |||
2146 | /* if not HW assist, just queue & schedule work */ | ||
2147 | if (!local->ops->remain_on_channel) { | ||
2148 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | ||
2149 | goto out_queue; | ||
2150 | } | ||
2151 | |||
2152 | /* otherwise actually kick it off here (for error handling) */ | ||
2153 | |||
2154 | /* | ||
2155 | * If the duration is zero, then the driver | ||
2156 | * wouldn't actually do anything. Set it to | ||
2157 | * 10 for now. | ||
2158 | * | ||
2159 | * TODO: cancel the off-channel operation | ||
2160 | * when we get the SKB's TX status and | ||
2161 | * the wait time was zero before. | ||
2162 | */ | ||
2163 | if (!duration) | ||
2164 | duration = 10; | ||
2165 | |||
2166 | ret = drv_remain_on_channel(local, channel, channel_type, duration); | ||
2134 | if (ret) { | 2167 | if (ret) { |
2135 | local->hw_roc_channel = NULL; | 2168 | kfree(roc); |
2136 | local->hw_roc_cookie = 0; | 2169 | return ret; |
2137 | } | 2170 | } |
2138 | 2171 | ||
2139 | return ret; | 2172 | roc->started = true; |
2173 | goto out_queue; | ||
2174 | |||
2175 | out_check_combine: | ||
2176 | list_for_each_entry(tmp, &local->roc_list, list) { | ||
2177 | if (tmp->chan != channel || tmp->chan_type != channel_type) | ||
2178 | continue; | ||
2179 | |||
2180 | /* | ||
2181 | * Extend this ROC if possible: | ||
2182 | * | ||
2183 | * If it hasn't started yet, just increase the duration | ||
2184 | * and add the new one to the list of dependents. | ||
2185 | */ | ||
2186 | if (!tmp->started) { | ||
2187 | list_add_tail(&roc->list, &tmp->dependents); | ||
2188 | tmp->duration = max(tmp->duration, roc->duration); | ||
2189 | queued = true; | ||
2190 | break; | ||
2191 | } | ||
2192 | |||
2193 | /* If it has already started, it's more difficult ... */ | ||
2194 | if (local->ops->remain_on_channel) { | ||
2195 | unsigned long j = jiffies; | ||
2196 | |||
2197 | /* | ||
2198 | * In the offloaded ROC case, if it hasn't begun, add | ||
2199 | * this new one to the dependent list to be handled | ||
2200 | * when the the master one begins. If it has begun, | ||
2201 | * check that there's still a minimum time left and | ||
2202 | * if so, start this one, transmitting the frame, but | ||
2203 | * add it to the list directly after this one with a | ||
2204 | * a reduced time so we'll ask the driver to execute | ||
2205 | * it right after finishing the previous one, in the | ||
2206 | * hope that it'll also be executed right afterwards, | ||
2207 | * effectively extending the old one. | ||
2208 | * If there's no minimum time left, just add it to the | ||
2209 | * normal list. | ||
2210 | */ | ||
2211 | if (!tmp->hw_begun) { | ||
2212 | list_add_tail(&roc->list, &tmp->dependents); | ||
2213 | queued = true; | ||
2214 | break; | ||
2215 | } | ||
2216 | |||
2217 | if (time_before(j + IEEE80211_ROC_MIN_LEFT, | ||
2218 | tmp->hw_start_time + | ||
2219 | msecs_to_jiffies(tmp->duration))) { | ||
2220 | int new_dur; | ||
2221 | |||
2222 | ieee80211_handle_roc_started(roc); | ||
2223 | |||
2224 | new_dur = roc->duration - | ||
2225 | jiffies_to_msecs(tmp->hw_start_time + | ||
2226 | msecs_to_jiffies( | ||
2227 | tmp->duration) - | ||
2228 | j); | ||
2229 | |||
2230 | if (new_dur > 0) { | ||
2231 | /* add right after tmp */ | ||
2232 | list_add(&roc->list, &tmp->list); | ||
2233 | } else { | ||
2234 | list_add_tail(&roc->list, | ||
2235 | &tmp->dependents); | ||
2236 | } | ||
2237 | queued = true; | ||
2238 | } | ||
2239 | } else if (del_timer_sync(&tmp->work.timer)) { | ||
2240 | unsigned long new_end; | ||
2241 | |||
2242 | /* | ||
2243 | * In the software ROC case, cancel the timer, if | ||
2244 | * that fails then the finish work is already | ||
2245 | * queued/pending and thus we queue the new ROC | ||
2246 | * normally, if that succeeds then we can extend | ||
2247 | * the timer duration and TX the frame (if any.) | ||
2248 | */ | ||
2249 | |||
2250 | list_add_tail(&roc->list, &tmp->dependents); | ||
2251 | queued = true; | ||
2252 | |||
2253 | new_end = jiffies + msecs_to_jiffies(roc->duration); | ||
2254 | |||
2255 | /* ok, it was started & we canceled timer */ | ||
2256 | if (time_after(new_end, tmp->work.timer.expires)) | ||
2257 | mod_timer(&tmp->work.timer, new_end); | ||
2258 | else | ||
2259 | add_timer(&tmp->work.timer); | ||
2260 | |||
2261 | ieee80211_handle_roc_started(roc); | ||
2262 | } | ||
2263 | break; | ||
2264 | } | ||
2265 | |||
2266 | out_queue: | ||
2267 | if (!queued) | ||
2268 | list_add_tail(&roc->list, &local->roc_list); | ||
2269 | |||
2270 | /* | ||
2271 | * cookie is either the roc (for normal roc) | ||
2272 | * or the SKB (for mgmt TX) | ||
2273 | */ | ||
2274 | if (txskb) | ||
2275 | *cookie = (unsigned long)txskb; | ||
2276 | else | ||
2277 | *cookie = (unsigned long)roc; | ||
2278 | |||
2279 | return 0; | ||
2140 | } | 2280 | } |
2141 | 2281 | ||
2142 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2282 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
@@ -2148,42 +2288,64 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2148 | { | 2288 | { |
2149 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2289 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2150 | struct ieee80211_local *local = sdata->local; | 2290 | struct ieee80211_local *local = sdata->local; |
2291 | int ret; | ||
2151 | 2292 | ||
2152 | if (local->ops->remain_on_channel) { | 2293 | mutex_lock(&local->mtx); |
2153 | int ret; | 2294 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, |
2154 | 2295 | duration, cookie, NULL); | |
2155 | mutex_lock(&local->mtx); | 2296 | mutex_unlock(&local->mtx); |
2156 | ret = ieee80211_remain_on_channel_hw(local, dev, | ||
2157 | chan, channel_type, | ||
2158 | duration, cookie); | ||
2159 | local->hw_roc_for_tx = false; | ||
2160 | mutex_unlock(&local->mtx); | ||
2161 | |||
2162 | return ret; | ||
2163 | } | ||
2164 | 2297 | ||
2165 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, | 2298 | return ret; |
2166 | duration, cookie); | ||
2167 | } | 2299 | } |
2168 | 2300 | ||
2169 | static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, | 2301 | static int ieee80211_cancel_roc(struct ieee80211_local *local, |
2170 | u64 cookie) | 2302 | u64 cookie, bool mgmt_tx) |
2171 | { | 2303 | { |
2304 | struct ieee80211_roc_work *roc, *tmp, *found = NULL; | ||
2172 | int ret; | 2305 | int ret; |
2173 | 2306 | ||
2174 | lockdep_assert_held(&local->mtx); | 2307 | mutex_lock(&local->mtx); |
2308 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
2309 | if (!mgmt_tx && (unsigned long)roc != cookie) | ||
2310 | continue; | ||
2311 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | ||
2312 | continue; | ||
2313 | |||
2314 | found = roc; | ||
2315 | break; | ||
2316 | } | ||
2175 | 2317 | ||
2176 | if (local->hw_roc_cookie != cookie) | 2318 | if (!found) { |
2319 | mutex_unlock(&local->mtx); | ||
2177 | return -ENOENT; | 2320 | return -ENOENT; |
2321 | } | ||
2178 | 2322 | ||
2179 | ret = drv_cancel_remain_on_channel(local); | 2323 | if (local->ops->remain_on_channel) { |
2180 | if (ret) | 2324 | if (found->started) { |
2181 | return ret; | 2325 | ret = drv_cancel_remain_on_channel(local); |
2326 | if (WARN_ON_ONCE(ret)) { | ||
2327 | mutex_unlock(&local->mtx); | ||
2328 | return ret; | ||
2329 | } | ||
2330 | } | ||
2182 | 2331 | ||
2183 | local->hw_roc_cookie = 0; | 2332 | list_del(&found->list); |
2184 | local->hw_roc_channel = NULL; | ||
2185 | 2333 | ||
2186 | ieee80211_recalc_idle(local); | 2334 | ieee80211_run_deferred_scan(local); |
2335 | ieee80211_start_next_roc(local); | ||
2336 | mutex_unlock(&local->mtx); | ||
2337 | |||
2338 | ieee80211_roc_notify_destroy(found); | ||
2339 | } else { | ||
2340 | /* work may be pending so use it all the time */ | ||
2341 | found->abort = true; | ||
2342 | ieee80211_queue_delayed_work(&local->hw, &found->work, 0); | ||
2343 | |||
2344 | mutex_unlock(&local->mtx); | ||
2345 | |||
2346 | /* work will clean up etc */ | ||
2347 | flush_delayed_work(&found->work); | ||
2348 | } | ||
2187 | 2349 | ||
2188 | return 0; | 2350 | return 0; |
2189 | } | 2351 | } |
@@ -2195,39 +2357,7 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
2195 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2357 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2196 | struct ieee80211_local *local = sdata->local; | 2358 | struct ieee80211_local *local = sdata->local; |
2197 | 2359 | ||
2198 | if (local->ops->cancel_remain_on_channel) { | 2360 | return ieee80211_cancel_roc(local, cookie, false); |
2199 | int ret; | ||
2200 | |||
2201 | mutex_lock(&local->mtx); | ||
2202 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
2203 | mutex_unlock(&local->mtx); | ||
2204 | |||
2205 | return ret; | ||
2206 | } | ||
2207 | |||
2208 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | ||
2209 | } | ||
2210 | |||
2211 | static enum work_done_result | ||
2212 | ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | ||
2213 | { | ||
2214 | /* | ||
2215 | * Use the data embedded in the work struct for reporting | ||
2216 | * here so if the driver mangled the SKB before dropping | ||
2217 | * it (which is the only way we really should get here) | ||
2218 | * then we don't report mangled data. | ||
2219 | * | ||
2220 | * If there was no wait time, then by the time we get here | ||
2221 | * the driver will likely not have reported the status yet, | ||
2222 | * so in that case userspace will have to deal with it. | ||
2223 | */ | ||
2224 | |||
2225 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) | ||
2226 | cfg80211_mgmt_tx_status(wk->sdata->dev, | ||
2227 | (unsigned long) wk->offchan_tx.frame, | ||
2228 | wk->data, wk->data_len, false, GFP_KERNEL); | ||
2229 | |||
2230 | return WORK_DONE_DESTROY; | ||
2231 | } | 2361 | } |
2232 | 2362 | ||
2233 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 2363 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
@@ -2241,10 +2371,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2241 | struct ieee80211_local *local = sdata->local; | 2371 | struct ieee80211_local *local = sdata->local; |
2242 | struct sk_buff *skb; | 2372 | struct sk_buff *skb; |
2243 | struct sta_info *sta; | 2373 | struct sta_info *sta; |
2244 | struct ieee80211_work *wk; | ||
2245 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 2374 | const struct ieee80211_mgmt *mgmt = (void *)buf; |
2375 | bool need_offchan = false; | ||
2246 | u32 flags; | 2376 | u32 flags; |
2247 | bool is_offchan = false; | 2377 | int ret; |
2248 | 2378 | ||
2249 | if (dont_wait_for_ack) | 2379 | if (dont_wait_for_ack) |
2250 | flags = IEEE80211_TX_CTL_NO_ACK; | 2380 | flags = IEEE80211_TX_CTL_NO_ACK; |
@@ -2252,33 +2382,28 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2252 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 2382 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
2253 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 2383 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
2254 | 2384 | ||
2255 | /* Check that we are on the requested channel for transmission */ | ||
2256 | if (chan != local->tmp_channel && | ||
2257 | chan != local->oper_channel) | ||
2258 | is_offchan = true; | ||
2259 | if (channel_type_valid && | ||
2260 | (channel_type != local->tmp_channel_type && | ||
2261 | channel_type != local->_oper_channel_type)) | ||
2262 | is_offchan = true; | ||
2263 | |||
2264 | if (chan == local->hw_roc_channel) { | ||
2265 | /* TODO: check channel type? */ | ||
2266 | is_offchan = false; | ||
2267 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
2268 | } | ||
2269 | |||
2270 | if (no_cck) | 2385 | if (no_cck) |
2271 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 2386 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
2272 | 2387 | ||
2273 | if (is_offchan && !offchan) | ||
2274 | return -EBUSY; | ||
2275 | |||
2276 | switch (sdata->vif.type) { | 2388 | switch (sdata->vif.type) { |
2277 | case NL80211_IFTYPE_ADHOC: | 2389 | case NL80211_IFTYPE_ADHOC: |
2390 | if (!sdata->vif.bss_conf.ibss_joined) | ||
2391 | need_offchan = true; | ||
2392 | /* fall through */ | ||
2393 | #ifdef CONFIG_MAC80211_MESH | ||
2394 | case NL80211_IFTYPE_MESH_POINT: | ||
2395 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
2396 | !sdata->u.mesh.mesh_id_len) | ||
2397 | need_offchan = true; | ||
2398 | /* fall through */ | ||
2399 | #endif | ||
2278 | case NL80211_IFTYPE_AP: | 2400 | case NL80211_IFTYPE_AP: |
2279 | case NL80211_IFTYPE_AP_VLAN: | 2401 | case NL80211_IFTYPE_AP_VLAN: |
2280 | case NL80211_IFTYPE_P2P_GO: | 2402 | case NL80211_IFTYPE_P2P_GO: |
2281 | case NL80211_IFTYPE_MESH_POINT: | 2403 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2404 | !ieee80211_vif_is_mesh(&sdata->vif) && | ||
2405 | !rcu_access_pointer(sdata->bss->beacon)) | ||
2406 | need_offchan = true; | ||
2282 | if (!ieee80211_is_action(mgmt->frame_control) || | 2407 | if (!ieee80211_is_action(mgmt->frame_control) || |
2283 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 2408 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
2284 | break; | 2409 | break; |
@@ -2290,103 +2415,60 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2290 | break; | 2415 | break; |
2291 | case NL80211_IFTYPE_STATION: | 2416 | case NL80211_IFTYPE_STATION: |
2292 | case NL80211_IFTYPE_P2P_CLIENT: | 2417 | case NL80211_IFTYPE_P2P_CLIENT: |
2418 | if (!sdata->u.mgd.associated) | ||
2419 | need_offchan = true; | ||
2293 | break; | 2420 | break; |
2294 | default: | 2421 | default: |
2295 | return -EOPNOTSUPP; | 2422 | return -EOPNOTSUPP; |
2296 | } | 2423 | } |
2297 | 2424 | ||
2425 | mutex_lock(&local->mtx); | ||
2426 | |||
2427 | /* Check if the operating channel is the requested channel */ | ||
2428 | if (!need_offchan) { | ||
2429 | need_offchan = chan != local->oper_channel; | ||
2430 | if (channel_type_valid && | ||
2431 | channel_type != local->_oper_channel_type) | ||
2432 | need_offchan = true; | ||
2433 | } | ||
2434 | |||
2435 | if (need_offchan && !offchan) { | ||
2436 | ret = -EBUSY; | ||
2437 | goto out_unlock; | ||
2438 | } | ||
2439 | |||
2298 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 2440 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); |
2299 | if (!skb) | 2441 | if (!skb) { |
2300 | return -ENOMEM; | 2442 | ret = -ENOMEM; |
2443 | goto out_unlock; | ||
2444 | } | ||
2301 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2445 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2302 | 2446 | ||
2303 | memcpy(skb_put(skb, len), buf, len); | 2447 | memcpy(skb_put(skb, len), buf, len); |
2304 | 2448 | ||
2305 | IEEE80211_SKB_CB(skb)->flags = flags; | 2449 | IEEE80211_SKB_CB(skb)->flags = flags; |
2306 | 2450 | ||
2307 | if (flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
2308 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
2309 | local->hw.offchannel_tx_hw_queue; | ||
2310 | |||
2311 | skb->dev = sdata->dev; | 2451 | skb->dev = sdata->dev; |
2312 | 2452 | ||
2313 | *cookie = (unsigned long) skb; | 2453 | if (!need_offchan) { |
2314 | 2454 | ieee80211_tx_skb(sdata, skb); | |
2315 | if (is_offchan && local->ops->remain_on_channel) { | 2455 | ret = 0; |
2316 | unsigned int duration; | 2456 | goto out_unlock; |
2317 | int ret; | 2457 | } |
2318 | |||
2319 | mutex_lock(&local->mtx); | ||
2320 | /* | ||
2321 | * If the duration is zero, then the driver | ||
2322 | * wouldn't actually do anything. Set it to | ||
2323 | * 100 for now. | ||
2324 | * | ||
2325 | * TODO: cancel the off-channel operation | ||
2326 | * when we get the SKB's TX status and | ||
2327 | * the wait time was zero before. | ||
2328 | */ | ||
2329 | duration = 100; | ||
2330 | if (wait) | ||
2331 | duration = wait; | ||
2332 | ret = ieee80211_remain_on_channel_hw(local, dev, chan, | ||
2333 | channel_type, | ||
2334 | duration, cookie); | ||
2335 | if (ret) { | ||
2336 | kfree_skb(skb); | ||
2337 | mutex_unlock(&local->mtx); | ||
2338 | return ret; | ||
2339 | } | ||
2340 | |||
2341 | local->hw_roc_for_tx = true; | ||
2342 | local->hw_roc_duration = wait; | ||
2343 | |||
2344 | /* | ||
2345 | * queue up frame for transmission after | ||
2346 | * ieee80211_ready_on_channel call | ||
2347 | */ | ||
2348 | 2458 | ||
2349 | /* modify cookie to prevent API mismatches */ | 2459 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; |
2350 | *cookie ^= 2; | 2460 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) |
2351 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
2352 | IEEE80211_SKB_CB(skb)->hw_queue = | 2461 | IEEE80211_SKB_CB(skb)->hw_queue = |
2353 | local->hw.offchannel_tx_hw_queue; | 2462 | local->hw.offchannel_tx_hw_queue; |
2354 | local->hw_roc_skb = skb; | ||
2355 | local->hw_roc_skb_for_status = skb; | ||
2356 | mutex_unlock(&local->mtx); | ||
2357 | |||
2358 | return 0; | ||
2359 | } | ||
2360 | |||
2361 | /* | ||
2362 | * Can transmit right away if the channel was the | ||
2363 | * right one and there's no wait involved... If a | ||
2364 | * wait is involved, we might otherwise not be on | ||
2365 | * the right channel for long enough! | ||
2366 | */ | ||
2367 | if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { | ||
2368 | ieee80211_tx_skb(sdata, skb); | ||
2369 | return 0; | ||
2370 | } | ||
2371 | 2463 | ||
2372 | wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); | 2464 | /* This will handle all kinds of coalescing and immediate TX */ |
2373 | if (!wk) { | 2465 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, |
2466 | wait, cookie, skb); | ||
2467 | if (ret) | ||
2374 | kfree_skb(skb); | 2468 | kfree_skb(skb); |
2375 | return -ENOMEM; | 2469 | out_unlock: |
2376 | } | 2470 | mutex_unlock(&local->mtx); |
2377 | 2471 | return ret; | |
2378 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; | ||
2379 | wk->chan = chan; | ||
2380 | wk->chan_type = channel_type; | ||
2381 | wk->sdata = sdata; | ||
2382 | wk->done = ieee80211_offchan_tx_done; | ||
2383 | wk->offchan_tx.frame = skb; | ||
2384 | wk->offchan_tx.wait = wait; | ||
2385 | wk->data_len = len; | ||
2386 | memcpy(wk->data, buf, len); | ||
2387 | |||
2388 | ieee80211_add_work(wk); | ||
2389 | return 0; | ||
2390 | } | 2472 | } |
2391 | 2473 | ||
2392 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | 2474 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, |
@@ -2395,45 +2477,8 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | |||
2395 | { | 2477 | { |
2396 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2478 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2397 | struct ieee80211_local *local = sdata->local; | 2479 | struct ieee80211_local *local = sdata->local; |
2398 | struct ieee80211_work *wk; | ||
2399 | int ret = -ENOENT; | ||
2400 | |||
2401 | mutex_lock(&local->mtx); | ||
2402 | |||
2403 | if (local->ops->cancel_remain_on_channel) { | ||
2404 | cookie ^= 2; | ||
2405 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
2406 | |||
2407 | if (ret == 0) { | ||
2408 | kfree_skb(local->hw_roc_skb); | ||
2409 | local->hw_roc_skb = NULL; | ||
2410 | local->hw_roc_skb_for_status = NULL; | ||
2411 | } | ||
2412 | |||
2413 | mutex_unlock(&local->mtx); | ||
2414 | 2480 | ||
2415 | return ret; | 2481 | return ieee80211_cancel_roc(local, cookie, true); |
2416 | } | ||
2417 | |||
2418 | list_for_each_entry(wk, &local->work_list, list) { | ||
2419 | if (wk->sdata != sdata) | ||
2420 | continue; | ||
2421 | |||
2422 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
2423 | continue; | ||
2424 | |||
2425 | if (cookie != (unsigned long) wk->offchan_tx.frame) | ||
2426 | continue; | ||
2427 | |||
2428 | wk->timeout = jiffies; | ||
2429 | |||
2430 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
2431 | ret = 0; | ||
2432 | break; | ||
2433 | } | ||
2434 | mutex_unlock(&local->mtx); | ||
2435 | |||
2436 | return ret; | ||
2437 | } | 2482 | } |
2438 | 2483 | ||
2439 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 2484 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
@@ -2677,7 +2722,7 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2677 | return -EINVAL; | 2722 | return -EINVAL; |
2678 | 2723 | ||
2679 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2724 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG |
2680 | printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer); | 2725 | pr_debug("TDLS mgmt action %d peer %pM\n", action_code, peer); |
2681 | #endif | 2726 | #endif |
2682 | 2727 | ||
2683 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 2728 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
@@ -2788,7 +2833,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
2788 | return -EINVAL; | 2833 | return -EINVAL; |
2789 | 2834 | ||
2790 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2835 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG |
2791 | printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer); | 2836 | pr_debug("TDLS oper %d peer %pM\n", oper, peer); |
2792 | #endif | 2837 | #endif |
2793 | 2838 | ||
2794 | switch (oper) { | 2839 | switch (oper) { |
@@ -2933,7 +2978,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2933 | #endif | 2978 | #endif |
2934 | .change_bss = ieee80211_change_bss, | 2979 | .change_bss = ieee80211_change_bss, |
2935 | .set_txq_params = ieee80211_set_txq_params, | 2980 | .set_txq_params = ieee80211_set_txq_params, |
2936 | .set_channel = ieee80211_set_channel, | 2981 | .set_monitor_channel = ieee80211_set_monitor_channel, |
2937 | .suspend = ieee80211_suspend, | 2982 | .suspend = ieee80211_suspend, |
2938 | .resume = ieee80211_resume, | 2983 | .resume = ieee80211_resume, |
2939 | .scan = ieee80211_scan, | 2984 | .scan = ieee80211_scan, |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index c76cf7230c7d..f0f87e5a1d35 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -41,6 +41,10 @@ __ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
41 | if (!sdata->u.ap.beacon) | 41 | if (!sdata->u.ap.beacon) |
42 | continue; | 42 | continue; |
43 | break; | 43 | break; |
44 | case NL80211_IFTYPE_MESH_POINT: | ||
45 | if (!sdata->wdev.mesh_id_len) | ||
46 | continue; | ||
47 | break; | ||
44 | default: | 48 | default: |
45 | break; | 49 | break; |
46 | } | 50 | } |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 7ed433c66d68..d4272ff43f71 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -607,6 +607,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
607 | MESHPARAMS_ADD(min_discovery_timeout); | 607 | MESHPARAMS_ADD(min_discovery_timeout); |
608 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); | 608 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); |
609 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); | 609 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); |
610 | MESHPARAMS_ADD(dot11MeshForwarding); | ||
610 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); | 611 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); |
611 | MESHPARAMS_ADD(rssi_threshold); | 612 | MESHPARAMS_ADD(rssi_threshold); |
612 | MESHPARAMS_ADD(ht_opmode); | 613 | MESHPARAMS_ADD(ht_opmode); |
@@ -685,6 +686,6 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | |||
685 | 686 | ||
686 | sprintf(buf, "netdev:%s", sdata->name); | 687 | sprintf(buf, "netdev:%s", sdata->name); |
687 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 688 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
688 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 689 | pr_err("mac80211: debugfs: failed to rename debugfs " |
689 | "dir to %s\n", buf); | 690 | "dir to %s\n", buf); |
690 | } | 691 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33d9d0c3e3d0..725cb4be229d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -82,8 +82,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
82 | 82 | ||
83 | local->oper_channel = chan; | 83 | local->oper_channel = chan; |
84 | channel_type = ifibss->channel_type; | 84 | channel_type = ifibss->channel_type; |
85 | if (channel_type > NL80211_CHAN_HT20 && | 85 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) |
86 | !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | ||
87 | channel_type = NL80211_CHAN_HT20; | 86 | channel_type = NL80211_CHAN_HT20; |
88 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 87 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
89 | /* can only fail due to HT40+/- mismatch */ | 88 | /* can only fail due to HT40+/- mismatch */ |
@@ -281,11 +280,8 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
281 | if (sta_info_insert_rcu(sta)) | 280 | if (sta_info_insert_rcu(sta)) |
282 | return sta_info_get(sdata, addr); | 281 | return sta_info_get(sdata, addr); |
283 | if (auth) { | 282 | if (auth) { |
284 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 283 | ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", |
285 | printk(KERN_DEBUG "TX Auth SA=%pM DA=%pM BSSID=%pM" | 284 | sdata->vif.addr, sdata->u.ibss.bssid, addr); |
286 | "(auth_transaction=1)\n", sdata->vif.addr, | ||
287 | sdata->u.ibss.bssid, addr); | ||
288 | #endif | ||
289 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, | 285 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, |
290 | addr, sdata->u.ibss.bssid, NULL, 0, 0); | 286 | addr, sdata->u.ibss.bssid, NULL, 0, 0); |
291 | } | 287 | } |
@@ -355,11 +351,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
355 | 351 | ||
356 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | 352 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) |
357 | return; | 353 | return; |
358 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 354 | ibss_vdbg("%s: RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", |
359 | printk(KERN_DEBUG "%s: RX Auth SA=%pM DA=%pM BSSID=%pM." | 355 | sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, |
360 | "(auth_transaction=%d)\n", | 356 | auth_transaction); |
361 | sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | ||
362 | #endif | ||
363 | sta_info_destroy_addr(sdata, mgmt->sa); | 357 | sta_info_destroy_addr(sdata, mgmt->sa); |
364 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | 358 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); |
365 | rcu_read_unlock(); | 359 | rcu_read_unlock(); |
@@ -422,15 +416,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
422 | ieee80211_mandatory_rates(local, band); | 416 | ieee80211_mandatory_rates(local, band); |
423 | 417 | ||
424 | if (sta->sta.supp_rates[band] != prev_rates) { | 418 | if (sta->sta.supp_rates[band] != prev_rates) { |
425 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 419 | ibss_vdbg("%s: updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n", |
426 | printk(KERN_DEBUG | 420 | sdata->name, sta->sta.addr, |
427 | "%s: updated supp_rates set " | 421 | prev_rates, |
428 | "for %pM based on beacon" | 422 | sta->sta.supp_rates[band]); |
429 | "/probe_resp (0x%x -> 0x%x)\n", | ||
430 | sdata->name, sta->sta.addr, | ||
431 | prev_rates, | ||
432 | sta->sta.supp_rates[band]); | ||
433 | #endif | ||
434 | rates_updated = true; | 423 | rates_updated = true; |
435 | } | 424 | } |
436 | } else { | 425 | } else { |
@@ -545,22 +534,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
545 | rx_timestamp = drv_get_tsf(local, sdata); | 534 | rx_timestamp = drv_get_tsf(local, sdata); |
546 | } | 535 | } |
547 | 536 | ||
548 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 537 | ibss_vdbg("RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", |
549 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" | 538 | mgmt->sa, mgmt->bssid, |
550 | "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", | 539 | (unsigned long long)rx_timestamp, |
551 | mgmt->sa, mgmt->bssid, | 540 | (unsigned long long)beacon_timestamp, |
552 | (unsigned long long)rx_timestamp, | 541 | (unsigned long long)(rx_timestamp - beacon_timestamp), |
553 | (unsigned long long)beacon_timestamp, | 542 | jiffies); |
554 | (unsigned long long)(rx_timestamp - beacon_timestamp), | ||
555 | jiffies); | ||
556 | #endif | ||
557 | 543 | ||
558 | if (beacon_timestamp > rx_timestamp) { | 544 | if (beacon_timestamp > rx_timestamp) { |
559 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 545 | ibss_vdbg("%s: beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", |
560 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 546 | sdata->name, mgmt->bssid); |
561 | "local TSF - IBSS merge with BSSID %pM\n", | ||
562 | sdata->name, mgmt->bssid); | ||
563 | #endif | ||
564 | ieee80211_sta_join_ibss(sdata, bss); | 547 | ieee80211_sta_join_ibss(sdata, bss); |
565 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); | 548 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); |
566 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 549 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
@@ -662,8 +645,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
662 | if (ifibss->fixed_channel) | 645 | if (ifibss->fixed_channel) |
663 | return; | 646 | return; |
664 | 647 | ||
665 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 648 | pr_debug("%s: No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n", |
666 | "IBSS networks with same SSID (merge)\n", sdata->name); | 649 | sdata->name); |
667 | 650 | ||
668 | ieee80211_request_internal_scan(sdata, | 651 | ieee80211_request_internal_scan(sdata, |
669 | ifibss->ssid, ifibss->ssid_len, NULL); | 652 | ifibss->ssid, ifibss->ssid_len, NULL); |
@@ -691,8 +674,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
691 | bssid[0] |= 0x02; | 674 | bssid[0] |= 0x02; |
692 | } | 675 | } |
693 | 676 | ||
694 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 677 | pr_debug("%s: Creating new IBSS network, BSSID %pM\n", |
695 | sdata->name, bssid); | 678 | sdata->name, bssid); |
696 | 679 | ||
697 | capability = WLAN_CAPABILITY_IBSS; | 680 | capability = WLAN_CAPABILITY_IBSS; |
698 | 681 | ||
@@ -723,10 +706,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
723 | lockdep_assert_held(&ifibss->mtx); | 706 | lockdep_assert_held(&ifibss->mtx); |
724 | 707 | ||
725 | active_ibss = ieee80211_sta_active_ibss(sdata); | 708 | active_ibss = ieee80211_sta_active_ibss(sdata); |
726 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 709 | ibss_vdbg("%s: sta_find_ibss (active_ibss=%d)\n", |
727 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 710 | sdata->name, active_ibss); |
728 | sdata->name, active_ibss); | ||
729 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
730 | 711 | ||
731 | if (active_ibss) | 712 | if (active_ibss) |
732 | return; | 713 | return; |
@@ -749,29 +730,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
749 | struct ieee80211_bss *bss; | 730 | struct ieee80211_bss *bss; |
750 | 731 | ||
751 | bss = (void *)cbss->priv; | 732 | bss = (void *)cbss->priv; |
752 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 733 | ibss_vdbg(" sta_find_ibss: selected %pM current %pM\n", |
753 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " | 734 | cbss->bssid, ifibss->bssid); |
754 | "%pM\n", cbss->bssid, ifibss->bssid); | 735 | pr_debug("%s: Selected IBSS BSSID %pM based on configured SSID\n", |
755 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 736 | sdata->name, cbss->bssid); |
756 | |||
757 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | ||
758 | " based on configured SSID\n", | ||
759 | sdata->name, cbss->bssid); | ||
760 | 737 | ||
761 | ieee80211_sta_join_ibss(sdata, bss); | 738 | ieee80211_sta_join_ibss(sdata, bss); |
762 | ieee80211_rx_bss_put(local, bss); | 739 | ieee80211_rx_bss_put(local, bss); |
763 | return; | 740 | return; |
764 | } | 741 | } |
765 | 742 | ||
766 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 743 | ibss_vdbg(" did not try to join ibss\n"); |
767 | printk(KERN_DEBUG " did not try to join ibss\n"); | ||
768 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
769 | 744 | ||
770 | /* Selected IBSS not found in current scan results - try to scan */ | 745 | /* Selected IBSS not found in current scan results - try to scan */ |
771 | if (time_after(jiffies, ifibss->last_scan_completed + | 746 | if (time_after(jiffies, ifibss->last_scan_completed + |
772 | IEEE80211_SCAN_INTERVAL)) { | 747 | IEEE80211_SCAN_INTERVAL)) { |
773 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 748 | pr_debug("%s: Trigger new scan to find an IBSS to join\n", |
774 | "join\n", sdata->name); | 749 | sdata->name); |
775 | 750 | ||
776 | ieee80211_request_internal_scan(sdata, | 751 | ieee80211_request_internal_scan(sdata, |
777 | ifibss->ssid, ifibss->ssid_len, | 752 | ifibss->ssid, ifibss->ssid_len, |
@@ -785,9 +760,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
785 | ieee80211_sta_create_ibss(sdata); | 760 | ieee80211_sta_create_ibss(sdata); |
786 | return; | 761 | return; |
787 | } | 762 | } |
788 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 763 | pr_debug("%s: IBSS not allowed on %d MHz\n", |
789 | " %d MHz\n", sdata->name, | 764 | sdata->name, |
790 | local->hw.conf.channel->center_freq); | 765 | local->hw.conf.channel->center_freq); |
791 | 766 | ||
792 | /* No IBSS found - decrease scan interval and continue | 767 | /* No IBSS found - decrease scan interval and continue |
793 | * scanning. */ | 768 | * scanning. */ |
@@ -822,12 +797,9 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
822 | 797 | ||
823 | tx_last_beacon = drv_tx_last_beacon(local); | 798 | tx_last_beacon = drv_tx_last_beacon(local); |
824 | 799 | ||
825 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 800 | ibss_vdbg("%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n", |
826 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" | 801 | sdata->name, mgmt->sa, mgmt->da, |
827 | " (tx_last_beacon=%d)\n", | 802 | mgmt->bssid, tx_last_beacon); |
828 | sdata->name, mgmt->sa, mgmt->da, | ||
829 | mgmt->bssid, tx_last_beacon); | ||
830 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
831 | 803 | ||
832 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) | 804 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) |
833 | return; | 805 | return; |
@@ -840,11 +812,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
840 | pos = mgmt->u.probe_req.variable; | 812 | pos = mgmt->u.probe_req.variable; |
841 | if (pos[0] != WLAN_EID_SSID || | 813 | if (pos[0] != WLAN_EID_SSID || |
842 | pos + 2 + pos[1] > end) { | 814 | pos + 2 + pos[1] > end) { |
843 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 815 | ibss_vdbg("%s: Invalid SSID IE in ProbeReq from %pM\n", |
844 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 816 | sdata->name, mgmt->sa); |
845 | "from %pM\n", | ||
846 | sdata->name, mgmt->sa); | ||
847 | #endif | ||
848 | return; | 817 | return; |
849 | } | 818 | } |
850 | if (pos[1] != 0 && | 819 | if (pos[1] != 0 && |
@@ -861,10 +830,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
861 | 830 | ||
862 | resp = (struct ieee80211_mgmt *) skb->data; | 831 | resp = (struct ieee80211_mgmt *) skb->data; |
863 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 832 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
864 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 833 | ibss_vdbg("%s: Sending ProbeResp to %pM\n", sdata->name, resp->da); |
865 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", | ||
866 | sdata->name, resp->da); | ||
867 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
868 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 834 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
869 | ieee80211_tx_skb(sdata, skb); | 835 | ieee80211_tx_skb(sdata, skb); |
870 | } | 836 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3f3cd50fff16..e6cbf5b68c89 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,55 +317,30 @@ struct mesh_preq_queue { | |||
317 | u8 flags; | 317 | u8 flags; |
318 | }; | 318 | }; |
319 | 319 | ||
320 | enum ieee80211_work_type { | 320 | #if HZ/100 == 0 |
321 | IEEE80211_WORK_ABORT, | 321 | #define IEEE80211_ROC_MIN_LEFT 1 |
322 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | 322 | #else |
323 | IEEE80211_WORK_OFFCHANNEL_TX, | 323 | #define IEEE80211_ROC_MIN_LEFT (HZ/100) |
324 | }; | 324 | #endif |
325 | |||
326 | /** | ||
327 | * enum work_done_result - indicates what to do after work was done | ||
328 | * | ||
329 | * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. | ||
330 | * @WORK_DONE_REQUEUE: This work item was reset to be reused, and | ||
331 | * should be requeued. | ||
332 | */ | ||
333 | enum work_done_result { | ||
334 | WORK_DONE_DESTROY, | ||
335 | WORK_DONE_REQUEUE, | ||
336 | }; | ||
337 | 325 | ||
338 | struct ieee80211_work { | 326 | struct ieee80211_roc_work { |
339 | struct list_head list; | 327 | struct list_head list; |
328 | struct list_head dependents; | ||
340 | 329 | ||
341 | struct rcu_head rcu_head; | 330 | struct delayed_work work; |
342 | 331 | ||
343 | struct ieee80211_sub_if_data *sdata; | 332 | struct ieee80211_sub_if_data *sdata; |
344 | 333 | ||
345 | enum work_done_result (*done)(struct ieee80211_work *wk, | ||
346 | struct sk_buff *skb); | ||
347 | |||
348 | struct ieee80211_channel *chan; | 334 | struct ieee80211_channel *chan; |
349 | enum nl80211_channel_type chan_type; | 335 | enum nl80211_channel_type chan_type; |
350 | 336 | ||
351 | unsigned long timeout; | 337 | bool started, abort, hw_begun, notified; |
352 | enum ieee80211_work_type type; | ||
353 | 338 | ||
354 | bool started; | 339 | unsigned long hw_start_time; |
355 | 340 | ||
356 | union { | 341 | u32 duration, req_duration; |
357 | struct { | 342 | struct sk_buff *frame; |
358 | u32 duration; | 343 | u64 mgmt_tx_cookie; |
359 | } remain; | ||
360 | struct { | ||
361 | struct sk_buff *frame; | ||
362 | u32 wait; | ||
363 | bool status; | ||
364 | } offchan_tx; | ||
365 | }; | ||
366 | |||
367 | size_t data_len; | ||
368 | u8 data[]; | ||
369 | }; | 344 | }; |
370 | 345 | ||
371 | /* flags used in struct ieee80211_if_managed.flags */ | 346 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -399,7 +374,6 @@ struct ieee80211_mgd_auth_data { | |||
399 | struct ieee80211_mgd_assoc_data { | 374 | struct ieee80211_mgd_assoc_data { |
400 | struct cfg80211_bss *bss; | 375 | struct cfg80211_bss *bss; |
401 | const u8 *supp_rates; | 376 | const u8 *supp_rates; |
402 | const u8 *ht_operation_ie; | ||
403 | 377 | ||
404 | unsigned long timeout; | 378 | unsigned long timeout; |
405 | int tries; | 379 | int tries; |
@@ -414,6 +388,8 @@ struct ieee80211_mgd_assoc_data { | |||
414 | bool sent_assoc; | 388 | bool sent_assoc; |
415 | bool synced; | 389 | bool synced; |
416 | 390 | ||
391 | u8 ap_ht_param; | ||
392 | |||
417 | size_t ie_len; | 393 | size_t ie_len; |
418 | u8 ie[]; | 394 | u8 ie[]; |
419 | }; | 395 | }; |
@@ -847,13 +823,6 @@ struct ieee80211_local { | |||
847 | const struct ieee80211_ops *ops; | 823 | const struct ieee80211_ops *ops; |
848 | 824 | ||
849 | /* | 825 | /* |
850 | * work stuff, potentially off-channel (in the future) | ||
851 | */ | ||
852 | struct list_head work_list; | ||
853 | struct timer_list work_timer; | ||
854 | struct work_struct work_work; | ||
855 | |||
856 | /* | ||
857 | * private workqueue to mac80211. mac80211 makes this accessible | 826 | * private workqueue to mac80211. mac80211 makes this accessible |
858 | * via ieee80211_queue_work() | 827 | * via ieee80211_queue_work() |
859 | */ | 828 | */ |
@@ -1087,14 +1056,12 @@ struct ieee80211_local { | |||
1087 | } debugfs; | 1056 | } debugfs; |
1088 | #endif | 1057 | #endif |
1089 | 1058 | ||
1090 | struct ieee80211_channel *hw_roc_channel; | 1059 | /* |
1091 | struct net_device *hw_roc_dev; | 1060 | * Remain-on-channel support |
1092 | struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status; | 1061 | */ |
1062 | struct list_head roc_list; | ||
1093 | struct work_struct hw_roc_start, hw_roc_done; | 1063 | struct work_struct hw_roc_start, hw_roc_done; |
1094 | enum nl80211_channel_type hw_roc_channel_type; | 1064 | unsigned long hw_roc_start_time; |
1095 | unsigned int hw_roc_duration; | ||
1096 | u32 hw_roc_cookie; | ||
1097 | bool hw_roc_for_tx; | ||
1098 | 1065 | ||
1099 | struct idr ack_status_frames; | 1066 | struct idr ack_status_frames; |
1100 | spinlock_t ack_status_lock; | 1067 | spinlock_t ack_status_lock; |
@@ -1290,7 +1257,12 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
1290 | bool offchannel_ps_enable); | 1257 | bool offchannel_ps_enable); |
1291 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1258 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1292 | bool offchannel_ps_disable); | 1259 | bool offchannel_ps_disable); |
1293 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | 1260 | void ieee80211_roc_setup(struct ieee80211_local *local); |
1261 | void ieee80211_start_next_roc(struct ieee80211_local *local); | ||
1262 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); | ||
1263 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); | ||
1264 | void ieee80211_sw_roc_work(struct work_struct *work); | ||
1265 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | ||
1294 | 1266 | ||
1295 | /* interface handling */ | 1267 | /* interface handling */ |
1296 | int ieee80211_iface_init(void); | 1268 | int ieee80211_iface_init(void); |
@@ -1500,18 +1472,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1500 | enum nl80211_channel_type channel_type, | 1472 | enum nl80211_channel_type channel_type, |
1501 | u16 prot_mode); | 1473 | u16 prot_mode); |
1502 | 1474 | ||
1503 | /* internal work items */ | ||
1504 | void ieee80211_work_init(struct ieee80211_local *local); | ||
1505 | void ieee80211_add_work(struct ieee80211_work *wk); | ||
1506 | void free_work(struct ieee80211_work *wk); | ||
1507 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); | ||
1508 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1509 | struct ieee80211_channel *chan, | ||
1510 | enum nl80211_channel_type channel_type, | ||
1511 | unsigned int duration, u64 *cookie); | ||
1512 | int ieee80211_wk_cancel_remain_on_channel( | ||
1513 | struct ieee80211_sub_if_data *sdata, u64 cookie); | ||
1514 | |||
1515 | /* channel management */ | 1475 | /* channel management */ |
1516 | enum ieee80211_chan_mode { | 1476 | enum ieee80211_chan_mode { |
1517 | CHAN_MODE_UNDEFINED, | 1477 | CHAN_MODE_UNDEFINED, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8664111d0566..87aeb4f21ffd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -58,7 +58,7 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
58 | } | 58 | } |
59 | 59 | ||
60 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 60 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
61 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | 61 | pr_debug("%s: setting MTU %d\n", dev->name, new_mtu); |
62 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 62 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
63 | dev->mtu = new_mtu; | 63 | dev->mtu = new_mtu; |
64 | return 0; | 64 | return 0; |
@@ -528,10 +528,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
528 | */ | 528 | */ |
529 | netif_tx_stop_all_queues(sdata->dev); | 529 | netif_tx_stop_all_queues(sdata->dev); |
530 | 530 | ||
531 | /* | 531 | ieee80211_roc_purge(sdata); |
532 | * Purge work for this interface. | ||
533 | */ | ||
534 | ieee80211_work_purge(sdata); | ||
535 | 532 | ||
536 | /* | 533 | /* |
537 | * Remove all stations associated with this interface. | 534 | * Remove all stations associated with this interface. |
@@ -637,18 +634,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
637 | ieee80211_configure_filter(local); | 634 | ieee80211_configure_filter(local); |
638 | break; | 635 | break; |
639 | default: | 636 | default: |
640 | mutex_lock(&local->mtx); | ||
641 | if (local->hw_roc_dev == sdata->dev && | ||
642 | local->hw_roc_channel) { | ||
643 | /* ignore return value since this is racy */ | ||
644 | drv_cancel_remain_on_channel(local); | ||
645 | ieee80211_queue_work(&local->hw, &local->hw_roc_done); | ||
646 | } | ||
647 | mutex_unlock(&local->mtx); | ||
648 | |||
649 | flush_work(&local->hw_roc_start); | ||
650 | flush_work(&local->hw_roc_done); | ||
651 | |||
652 | flush_work(&sdata->work); | 637 | flush_work(&sdata->work); |
653 | /* | 638 | /* |
654 | * When we get here, the interface is marked down. | 639 | * When we get here, the interface is marked down. |
@@ -1238,7 +1223,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1238 | 1223 | ||
1239 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { | 1224 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { |
1240 | /* not a contiguous mask ... not handled now! */ | 1225 | /* not a contiguous mask ... not handled now! */ |
1241 | printk(KERN_DEBUG "not contiguous\n"); | 1226 | pr_debug("not contiguous\n"); |
1242 | break; | 1227 | break; |
1243 | } | 1228 | } |
1244 | 1229 | ||
@@ -1364,6 +1349,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1364 | sdata->u.mgd.use_4addr = params->use_4addr; | 1349 | sdata->u.mgd.use_4addr = params->use_4addr; |
1365 | } | 1350 | } |
1366 | 1351 | ||
1352 | ndev->features |= local->hw.netdev_features; | ||
1353 | |||
1367 | ret = register_netdevice(ndev); | 1354 | ret = register_netdevice(ndev); |
1368 | if (ret) | 1355 | if (ret) |
1369 | goto fail; | 1356 | goto fail; |
@@ -1454,9 +1441,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1454 | { | 1441 | { |
1455 | struct ieee80211_sub_if_data *sdata; | 1442 | struct ieee80211_sub_if_data *sdata; |
1456 | int count = 0; | 1443 | int count = 0; |
1457 | bool working = false, scanning = false, hw_roc = false; | 1444 | bool working = false, scanning = false; |
1458 | struct ieee80211_work *wk; | ||
1459 | unsigned int led_trig_start = 0, led_trig_stop = 0; | 1445 | unsigned int led_trig_start = 0, led_trig_stop = 0; |
1446 | struct ieee80211_roc_work *roc; | ||
1460 | 1447 | ||
1461 | #ifdef CONFIG_PROVE_LOCKING | 1448 | #ifdef CONFIG_PROVE_LOCKING |
1462 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | 1449 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
@@ -1491,9 +1478,11 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1491 | count++; | 1478 | count++; |
1492 | } | 1479 | } |
1493 | 1480 | ||
1494 | list_for_each_entry(wk, &local->work_list, list) { | 1481 | if (!local->ops->remain_on_channel) { |
1495 | working = true; | 1482 | list_for_each_entry(roc, &local->roc_list, list) { |
1496 | wk->sdata->vif.bss_conf.idle = false; | 1483 | working = true; |
1484 | roc->sdata->vif.bss_conf.idle = false; | ||
1485 | } | ||
1497 | } | 1486 | } |
1498 | 1487 | ||
1499 | if (local->scan_sdata && | 1488 | if (local->scan_sdata && |
@@ -1502,9 +1491,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1502 | local->scan_sdata->vif.bss_conf.idle = false; | 1491 | local->scan_sdata->vif.bss_conf.idle = false; |
1503 | } | 1492 | } |
1504 | 1493 | ||
1505 | if (local->hw_roc_channel) | ||
1506 | hw_roc = true; | ||
1507 | |||
1508 | list_for_each_entry(sdata, &local->interfaces, list) { | 1494 | list_for_each_entry(sdata, &local->interfaces, list) { |
1509 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 1495 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
1510 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1496 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -1516,7 +1502,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1516 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | 1502 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); |
1517 | } | 1503 | } |
1518 | 1504 | ||
1519 | if (working || scanning || hw_roc) | 1505 | if (working || scanning) |
1520 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 1506 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
1521 | else | 1507 | else |
1522 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 1508 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
@@ -1528,8 +1514,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1528 | 1514 | ||
1529 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | 1515 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); |
1530 | 1516 | ||
1531 | if (hw_roc) | ||
1532 | return ieee80211_idle_off(local, "hw remain-on-channel"); | ||
1533 | if (working) | 1517 | if (working) |
1534 | return ieee80211_idle_off(local, "working"); | 1518 | return ieee80211_idle_off(local, "working"); |
1535 | if (scanning) | 1519 | if (scanning) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f5548e953259..d81c178c7712 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -625,8 +625,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
625 | 625 | ||
626 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 626 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
627 | 627 | ||
628 | ieee80211_work_init(local); | ||
629 | |||
630 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 628 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
631 | 629 | ||
632 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 630 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
@@ -669,7 +667,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
669 | 667 | ||
670 | ieee80211_led_names(local); | 668 | ieee80211_led_names(local); |
671 | 669 | ||
672 | ieee80211_hw_roc_setup(local); | 670 | ieee80211_roc_setup(local); |
673 | 671 | ||
674 | return &local->hw; | 672 | return &local->hw; |
675 | } | 673 | } |
@@ -682,6 +680,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
682 | enum ieee80211_band band; | 680 | enum ieee80211_band band; |
683 | int channels, max_bitrates; | 681 | int channels, max_bitrates; |
684 | bool supp_ht; | 682 | bool supp_ht; |
683 | netdev_features_t feature_whitelist; | ||
685 | static const u32 cipher_suites[] = { | 684 | static const u32 cipher_suites[] = { |
686 | /* keep WEP first, it may be removed below */ | 685 | /* keep WEP first, it may be removed below */ |
687 | WLAN_CIPHER_SUITE_WEP40, | 686 | WLAN_CIPHER_SUITE_WEP40, |
@@ -708,6 +707,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
708 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) | 707 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) |
709 | return -EINVAL; | 708 | return -EINVAL; |
710 | 709 | ||
710 | /* Only HW csum features are currently compatible with mac80211 */ | ||
711 | feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
712 | NETIF_F_HW_CSUM; | ||
713 | if (WARN_ON(hw->netdev_features & ~feature_whitelist)) | ||
714 | return -EINVAL; | ||
715 | |||
711 | if (hw->max_report_rates == 0) | 716 | if (hw->max_report_rates == 0) |
712 | hw->max_report_rates = hw->max_rates; | 717 | hw->max_report_rates = hw->max_rates; |
713 | 718 | ||
@@ -1009,12 +1014,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1009 | 1014 | ||
1010 | rtnl_unlock(); | 1015 | rtnl_unlock(); |
1011 | 1016 | ||
1012 | /* | ||
1013 | * Now all work items will be gone, but the | ||
1014 | * timer might still be armed, so delete it | ||
1015 | */ | ||
1016 | del_timer_sync(&local->work_timer); | ||
1017 | |||
1018 | cancel_work_sync(&local->restart_work); | 1017 | cancel_work_sync(&local->restart_work); |
1019 | cancel_work_sync(&local->reconfig_filter); | 1018 | cancel_work_sync(&local->reconfig_filter); |
1020 | 1019 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2913113c5833..7cf19509fb68 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -524,8 +524,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
524 | bool free_plinks; | 524 | bool free_plinks; |
525 | 525 | ||
526 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 526 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
527 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 527 | pr_debug("%s: running mesh housekeeping\n", sdata->name); |
528 | sdata->name); | ||
529 | #endif | 528 | #endif |
530 | 529 | ||
531 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 530 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 9b59658e8650..fa7c58035246 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG | 16 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG |
17 | #define mhwmp_dbg(fmt, args...) \ | 17 | #define mhwmp_dbg(fmt, args...) \ |
18 | printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) | 18 | pr_debug("Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) |
19 | #else | 19 | #else |
20 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) | 20 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) |
21 | #endif | 21 | #endif |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index b39224d8255c..572f706fd65b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "mesh.h" | 19 | #include "mesh.h" |
20 | 20 | ||
21 | #ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG | 21 | #ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG |
22 | #define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 22 | #define mpath_dbg(fmt, args...) pr_debug(fmt, ##args) |
23 | #else | 23 | #else |
24 | #define mpath_dbg(fmt, args...) do { (void)(0); } while (0) | 24 | #define mpath_dbg(fmt, args...) do { (void)(0); } while (0) |
25 | #endif | 25 | #endif |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 60ef235c9d9b..be4fad128c34 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 16 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
17 | #define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 17 | #define mpl_dbg(fmt, args...) pr_debug(fmt, ##args) |
18 | #else | 18 | #else |
19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) | 19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) |
20 | #endif | 20 | #endif |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 38d30e8ce6dc..0ccdad49f987 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG | 15 | #ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG |
16 | #define msync_dbg(fmt, args...) \ | 16 | #define msync_dbg(fmt, args...) \ |
17 | printk(KERN_DEBUG "Mesh sync (%s): " fmt "\n", sdata->name, ##args) | 17 | pr_debug("Mesh sync (%s): " fmt "\n", sdata->name, ##args) |
18 | #else | 18 | #else |
19 | #define msync_dbg(fmt, args...) do { (void)(0); } while (0) | 19 | #define msync_dbg(fmt, args...) do { (void)(0); } while (0) |
20 | #endif | 20 | #endif |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d94627c2929c..0f45d02e0ba7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -258,12 +258,11 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
258 | } | 258 | } |
259 | 259 | ||
260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
261 | struct sk_buff *skb, const u8 *ht_oper_ie, | 261 | struct sk_buff *skb, u8 ap_ht_param, |
262 | struct ieee80211_supported_band *sband, | 262 | struct ieee80211_supported_band *sband, |
263 | struct ieee80211_channel *channel, | 263 | struct ieee80211_channel *channel, |
264 | enum ieee80211_smps_mode smps) | 264 | enum ieee80211_smps_mode smps) |
265 | { | 265 | { |
266 | struct ieee80211_ht_operation *ht_oper; | ||
267 | u8 *pos; | 266 | u8 *pos; |
268 | u32 flags = channel->flags; | 267 | u32 flags = channel->flags; |
269 | u16 cap; | 268 | u16 cap; |
@@ -271,21 +270,13 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
271 | 270 | ||
272 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | 271 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); |
273 | 272 | ||
274 | if (!ht_oper_ie) | ||
275 | return; | ||
276 | |||
277 | if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation)) | ||
278 | return; | ||
279 | |||
280 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | 273 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); |
281 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | 274 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); |
282 | 275 | ||
283 | ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2); | ||
284 | |||
285 | /* determine capability flags */ | 276 | /* determine capability flags */ |
286 | cap = ht_cap.cap; | 277 | cap = ht_cap.cap; |
287 | 278 | ||
288 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 279 | switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
289 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 280 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
290 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 281 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
291 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 282 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -509,7 +500,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
509 | } | 500 | } |
510 | 501 | ||
511 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 502 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
512 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie, | 503 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
513 | sband, local->oper_channel, ifmgd->ap_smps); | 504 | sband, local->oper_channel, ifmgd->ap_smps); |
514 | 505 | ||
515 | /* if present, add any custom non-vendor IEs that go after HT */ | 506 | /* if present, add any custom non-vendor IEs that go after HT */ |
@@ -939,11 +930,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
939 | return; | 930 | return; |
940 | } | 931 | } |
941 | 932 | ||
942 | if (!list_empty(&local->work_list)) { | ||
943 | local->ps_sdata = NULL; | ||
944 | goto change; | ||
945 | } | ||
946 | |||
947 | list_for_each_entry(sdata, &local->interfaces, list) { | 933 | list_for_each_entry(sdata, &local->interfaces, list) { |
948 | if (!ieee80211_sdata_running(sdata)) | 934 | if (!ieee80211_sdata_running(sdata)) |
949 | continue; | 935 | continue; |
@@ -1016,7 +1002,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1016 | local->ps_sdata = NULL; | 1002 | local->ps_sdata = NULL; |
1017 | } | 1003 | } |
1018 | 1004 | ||
1019 | change: | ||
1020 | ieee80211_change_ps(local); | 1005 | ieee80211_change_ps(local); |
1021 | } | 1006 | } |
1022 | 1007 | ||
@@ -1585,6 +1570,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1585 | net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n", | 1570 | net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n", |
1586 | sdata->name); | 1571 | sdata->name); |
1587 | #endif | 1572 | #endif |
1573 | ieee80211_cqm_rssi_notify(&sdata->vif, | ||
1574 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); | ||
1588 | 1575 | ||
1589 | /* | 1576 | /* |
1590 | * The driver/our work has already reported this event or the | 1577 | * The driver/our work has already reported this event or the |
@@ -1667,8 +1654,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1667 | 1654 | ||
1668 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1655 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1669 | 1656 | ||
1670 | printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", | 1657 | pr_debug("%s: Connection to AP %pM lost\n", sdata->name, bssid); |
1671 | sdata->name, bssid); | ||
1672 | 1658 | ||
1673 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 1659 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
1674 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1660 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
@@ -1802,9 +1788,10 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1802 | return RX_MGMT_NONE; | 1788 | return RX_MGMT_NONE; |
1803 | 1789 | ||
1804 | if (status_code != WLAN_STATUS_SUCCESS) { | 1790 | if (status_code != WLAN_STATUS_SUCCESS) { |
1805 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | 1791 | pr_debug("%s: %pM denied authentication (status %d)\n", |
1806 | sdata->name, mgmt->sa, status_code); | 1792 | sdata->name, mgmt->sa, status_code); |
1807 | goto out; | 1793 | ieee80211_destroy_auth_data(sdata, false); |
1794 | return RX_MGMT_CFG80211_RX_AUTH; | ||
1808 | } | 1795 | } |
1809 | 1796 | ||
1810 | switch (ifmgd->auth_data->algorithm) { | 1797 | switch (ifmgd->auth_data->algorithm) { |
@@ -1825,8 +1812,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1825 | return RX_MGMT_NONE; | 1812 | return RX_MGMT_NONE; |
1826 | } | 1813 | } |
1827 | 1814 | ||
1828 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | 1815 | pr_debug("%s: authenticated\n", sdata->name); |
1829 | out: | ||
1830 | ifmgd->auth_data->done = true; | 1816 | ifmgd->auth_data->done = true; |
1831 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | 1817 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; |
1832 | run_again(ifmgd, ifmgd->auth_data->timeout); | 1818 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -1839,8 +1825,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1839 | goto out_err; | 1825 | goto out_err; |
1840 | } | 1826 | } |
1841 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { | 1827 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { |
1842 | printk(KERN_DEBUG "%s: failed moving %pM to auth\n", | 1828 | pr_debug("%s: failed moving %pM to auth\n", sdata->name, bssid); |
1843 | sdata->name, bssid); | ||
1844 | goto out_err; | 1829 | goto out_err; |
1845 | } | 1830 | } |
1846 | mutex_unlock(&sdata->local->sta_mtx); | 1831 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -1874,8 +1859,8 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1874 | 1859 | ||
1875 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1860 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1876 | 1861 | ||
1877 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1862 | pr_debug("%s: deauthenticated from %pM (Reason: %u)\n", |
1878 | sdata->name, bssid, reason_code); | 1863 | sdata->name, bssid, reason_code); |
1879 | 1864 | ||
1880 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1865 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1881 | 1866 | ||
@@ -1905,8 +1890,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1905 | 1890 | ||
1906 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1891 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1907 | 1892 | ||
1908 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1893 | pr_debug("%s: disassociated from %pM (Reason: %u)\n", |
1909 | sdata->name, mgmt->sa, reason_code); | 1894 | sdata->name, mgmt->sa, reason_code); |
1910 | 1895 | ||
1911 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1896 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1912 | 1897 | ||
@@ -1998,17 +1983,15 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
1998 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | 1983 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
1999 | 1984 | ||
2000 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1985 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
2001 | printk(KERN_DEBUG | 1986 | pr_debug("%s: invalid AID value 0x%x; bits 15:14 not set\n", |
2002 | "%s: invalid AID value 0x%x; bits 15:14 not set\n", | 1987 | sdata->name, aid); |
2003 | sdata->name, aid); | ||
2004 | aid &= ~(BIT(15) | BIT(14)); | 1988 | aid &= ~(BIT(15) | BIT(14)); |
2005 | 1989 | ||
2006 | ifmgd->broken_ap = false; | 1990 | ifmgd->broken_ap = false; |
2007 | 1991 | ||
2008 | if (aid == 0 || aid > IEEE80211_MAX_AID) { | 1992 | if (aid == 0 || aid > IEEE80211_MAX_AID) { |
2009 | printk(KERN_DEBUG | 1993 | pr_debug("%s: invalid AID value %d (out of range), turn off PS\n", |
2010 | "%s: invalid AID value %d (out of range), turn off PS\n", | 1994 | sdata->name, aid); |
2011 | sdata->name, aid); | ||
2012 | aid = 0; | 1995 | aid = 0; |
2013 | ifmgd->broken_ap = true; | 1996 | ifmgd->broken_ap = true; |
2014 | } | 1997 | } |
@@ -2017,8 +2000,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2017 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2000 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
2018 | 2001 | ||
2019 | if (!elems.supp_rates) { | 2002 | if (!elems.supp_rates) { |
2020 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 2003 | pr_debug("%s: no SuppRates element in AssocResp\n", |
2021 | sdata->name); | 2004 | sdata->name); |
2022 | return false; | 2005 | return false; |
2023 | } | 2006 | } |
2024 | 2007 | ||
@@ -2058,9 +2041,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2058 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 2041 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
2059 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 2042 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
2060 | if (err) { | 2043 | if (err) { |
2061 | printk(KERN_DEBUG | 2044 | pr_debug("%s: failed to move station %pM to desired state\n", |
2062 | "%s: failed to move station %pM to desired state\n", | 2045 | sdata->name, sta->sta.addr); |
2063 | sdata->name, sta->sta.addr); | ||
2064 | WARN_ON(__sta_info_destroy(sta)); | 2046 | WARN_ON(__sta_info_destroy(sta)); |
2065 | mutex_unlock(&sdata->local->sta_mtx); | 2047 | mutex_unlock(&sdata->local->sta_mtx); |
2066 | return false; | 2048 | return false; |
@@ -2143,10 +2125,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2143 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 2125 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2144 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 2126 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
2145 | 2127 | ||
2146 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | 2128 | pr_debug("%s: RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n", |
2147 | "status=%d aid=%d)\n", | 2129 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, |
2148 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | 2130 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
2149 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
2150 | 2131 | ||
2151 | pos = mgmt->u.assoc_resp.variable; | 2132 | pos = mgmt->u.assoc_resp.variable; |
2152 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2133 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
@@ -2157,9 +2138,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2157 | u32 tu, ms; | 2138 | u32 tu, ms; |
2158 | tu = get_unaligned_le32(elems.timeout_int + 1); | 2139 | tu = get_unaligned_le32(elems.timeout_int + 1); |
2159 | ms = tu * 1024 / 1000; | 2140 | ms = tu * 1024 / 1000; |
2160 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | 2141 | pr_debug("%s: %pM rejected association temporarily; comeback duration %u TU (%u ms)\n", |
2161 | "comeback duration %u TU (%u ms)\n", | 2142 | sdata->name, mgmt->sa, tu, ms); |
2162 | sdata->name, mgmt->sa, tu, ms); | ||
2163 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); | 2143 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); |
2164 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 2144 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
2165 | run_again(ifmgd, assoc_data->timeout); | 2145 | run_again(ifmgd, assoc_data->timeout); |
@@ -2169,11 +2149,11 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2169 | *bss = assoc_data->bss; | 2149 | *bss = assoc_data->bss; |
2170 | 2150 | ||
2171 | if (status_code != WLAN_STATUS_SUCCESS) { | 2151 | if (status_code != WLAN_STATUS_SUCCESS) { |
2172 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | 2152 | pr_debug("%s: %pM denied association (code=%d)\n", |
2173 | sdata->name, mgmt->sa, status_code); | 2153 | sdata->name, mgmt->sa, status_code); |
2174 | ieee80211_destroy_assoc_data(sdata, false); | 2154 | ieee80211_destroy_assoc_data(sdata, false); |
2175 | } else { | 2155 | } else { |
2176 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | 2156 | pr_debug("%s: associated\n", sdata->name); |
2177 | 2157 | ||
2178 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | 2158 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { |
2179 | /* oops -- internal error -- send timeout for now */ | 2159 | /* oops -- internal error -- send timeout for now */ |
@@ -2281,7 +2261,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2281 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | 2261 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && |
2282 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { | 2262 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { |
2283 | /* got probe response, continue with auth */ | 2263 | /* got probe response, continue with auth */ |
2284 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | 2264 | pr_debug("%s: direct probe responded\n", sdata->name); |
2285 | ifmgd->auth_data->tries = 0; | 2265 | ifmgd->auth_data->tries = 0; |
2286 | ifmgd->auth_data->timeout = jiffies; | 2266 | ifmgd->auth_data->timeout = jiffies; |
2287 | run_again(ifmgd, ifmgd->auth_data->timeout); | 2267 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -2645,8 +2625,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2645 | auth_data->tries++; | 2625 | auth_data->tries++; |
2646 | 2626 | ||
2647 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 2627 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
2648 | printk(KERN_DEBUG "%s: authentication with %pM timed out\n", | 2628 | pr_debug("%s: authentication with %pM timed out\n", |
2649 | sdata->name, auth_data->bss->bssid); | 2629 | sdata->name, auth_data->bss->bssid); |
2650 | 2630 | ||
2651 | /* | 2631 | /* |
2652 | * Most likely AP is not in the range so remove the | 2632 | * Most likely AP is not in the range so remove the |
@@ -2658,9 +2638,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2658 | } | 2638 | } |
2659 | 2639 | ||
2660 | if (auth_data->bss->proberesp_ies) { | 2640 | if (auth_data->bss->proberesp_ies) { |
2661 | printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n", | 2641 | pr_debug("%s: send auth to %pM (try %d/%d)\n", |
2662 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2642 | sdata->name, auth_data->bss->bssid, auth_data->tries, |
2663 | IEEE80211_AUTH_MAX_TRIES); | 2643 | IEEE80211_AUTH_MAX_TRIES); |
2664 | 2644 | ||
2665 | auth_data->expected_transaction = 2; | 2645 | auth_data->expected_transaction = 2; |
2666 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, | 2646 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, |
@@ -2670,9 +2650,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2670 | } else { | 2650 | } else { |
2671 | const u8 *ssidie; | 2651 | const u8 *ssidie; |
2672 | 2652 | ||
2673 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", | 2653 | pr_debug("%s: direct probe to %pM (try %d/%i)\n", |
2674 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2654 | sdata->name, auth_data->bss->bssid, auth_data->tries, |
2675 | IEEE80211_AUTH_MAX_TRIES); | 2655 | IEEE80211_AUTH_MAX_TRIES); |
2676 | 2656 | ||
2677 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | 2657 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); |
2678 | if (!ssidie) | 2658 | if (!ssidie) |
@@ -2700,8 +2680,8 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2700 | 2680 | ||
2701 | assoc_data->tries++; | 2681 | assoc_data->tries++; |
2702 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { | 2682 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { |
2703 | printk(KERN_DEBUG "%s: association with %pM timed out\n", | 2683 | pr_debug("%s: association with %pM timed out\n", |
2704 | sdata->name, assoc_data->bss->bssid); | 2684 | sdata->name, assoc_data->bss->bssid); |
2705 | 2685 | ||
2706 | /* | 2686 | /* |
2707 | * Most likely AP is not in the range so remove the | 2687 | * Most likely AP is not in the range so remove the |
@@ -2712,9 +2692,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2712 | return -ETIMEDOUT; | 2692 | return -ETIMEDOUT; |
2713 | } | 2693 | } |
2714 | 2694 | ||
2715 | printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n", | 2695 | pr_debug("%s: associate with %pM (try %d/%d)\n", |
2716 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, | 2696 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, |
2717 | IEEE80211_ASSOC_MAX_TRIES); | 2697 | IEEE80211_ASSOC_MAX_TRIES); |
2718 | ieee80211_send_assoc(sdata); | 2698 | ieee80211_send_assoc(sdata); |
2719 | 2699 | ||
2720 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 2700 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
@@ -3085,13 +3065,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3085 | * since we look at probe response/beacon data here | 3065 | * since we look at probe response/beacon data here |
3086 | * it should be OK. | 3066 | * it should be OK. |
3087 | */ | 3067 | */ |
3088 | printk(KERN_DEBUG | 3068 | pr_debug("%s: Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", |
3089 | "%s: Wrong control channel: center-freq: %d" | 3069 | sdata->name, cbss->channel->center_freq, |
3090 | " ht-cfreq: %d ht->primary_chan: %d" | 3070 | ht_cfreq, ht_oper->primary_chan, |
3091 | " band: %d. Disabling HT.\n", | 3071 | cbss->channel->band); |
3092 | sdata->name, cbss->channel->center_freq, | ||
3093 | ht_cfreq, ht_oper->primary_chan, | ||
3094 | cbss->channel->band); | ||
3095 | ht_oper = NULL; | 3072 | ht_oper = NULL; |
3096 | } | 3073 | } |
3097 | } | 3074 | } |
@@ -3115,9 +3092,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3115 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 3092 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
3116 | /* can only fail due to HT40+/- mismatch */ | 3093 | /* can only fail due to HT40+/- mismatch */ |
3117 | channel_type = NL80211_CHAN_HT20; | 3094 | channel_type = NL80211_CHAN_HT20; |
3118 | printk(KERN_DEBUG | 3095 | pr_debug("%s: disabling 40 MHz due to multi-vif mismatch\n", |
3119 | "%s: disabling 40 MHz due to multi-vif mismatch\n", | 3096 | sdata->name); |
3120 | sdata->name); | ||
3121 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3097 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; |
3122 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | 3098 | WARN_ON(!ieee80211_set_channel_type(local, sdata, |
3123 | channel_type)); | 3099 | channel_type)); |
@@ -3146,9 +3122,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3146 | * we can connect -- with a warning. | 3122 | * we can connect -- with a warning. |
3147 | */ | 3123 | */ |
3148 | if (!basic_rates && min_rate_index >= 0) { | 3124 | if (!basic_rates && min_rate_index >= 0) { |
3149 | printk(KERN_DEBUG | 3125 | pr_debug("%s: No basic rates, using min rate instead\n", |
3150 | "%s: No basic rates, using min rate instead.\n", | 3126 | sdata->name); |
3151 | sdata->name); | ||
3152 | basic_rates = BIT(min_rate_index); | 3127 | basic_rates = BIT(min_rate_index); |
3153 | } | 3128 | } |
3154 | 3129 | ||
@@ -3174,9 +3149,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3174 | err = sta_info_insert(sta); | 3149 | err = sta_info_insert(sta); |
3175 | sta = NULL; | 3150 | sta = NULL; |
3176 | if (err) { | 3151 | if (err) { |
3177 | printk(KERN_DEBUG | 3152 | pr_debug("%s: failed to insert STA entry for the AP (error %d)\n", |
3178 | "%s: failed to insert STA entry for the AP (error %d)\n", | 3153 | sdata->name, err); |
3179 | sdata->name, err); | ||
3180 | return err; | 3154 | return err; |
3181 | } | 3155 | } |
3182 | } else | 3156 | } else |
@@ -3254,8 +3228,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3254 | if (ifmgd->associated) | 3228 | if (ifmgd->associated) |
3255 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 3229 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
3256 | 3230 | ||
3257 | printk(KERN_DEBUG "%s: authenticate with %pM\n", | 3231 | pr_debug("%s: authenticate with %pM\n", sdata->name, req->bss->bssid); |
3258 | sdata->name, req->bss->bssid); | ||
3259 | 3232 | ||
3260 | err = ieee80211_prep_connection(sdata, req->bss, false); | 3233 | err = ieee80211_prep_connection(sdata, req->bss, false); |
3261 | if (err) | 3234 | if (err) |
@@ -3290,7 +3263,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3290 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3263 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
3291 | struct ieee80211_mgd_assoc_data *assoc_data; | 3264 | struct ieee80211_mgd_assoc_data *assoc_data; |
3292 | struct ieee80211_supported_band *sband; | 3265 | struct ieee80211_supported_band *sband; |
3293 | const u8 *ssidie; | 3266 | const u8 *ssidie, *ht_ie; |
3294 | int i, err; | 3267 | int i, err; |
3295 | 3268 | ||
3296 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 3269 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
@@ -3338,11 +3311,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3338 | * We can set this to true for non-11n hardware, that'll be checked | 3311 | * We can set this to true for non-11n hardware, that'll be checked |
3339 | * separately along with the peer capabilities. | 3312 | * separately along with the peer capabilities. |
3340 | */ | 3313 | */ |
3341 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 3314 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { |
3342 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3315 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3343 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3316 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3344 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 3317 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3345 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3318 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3319 | netdev_info(sdata->dev, | ||
3320 | "disabling HT due to WEP/TKIP use\n"); | ||
3321 | } | ||
3322 | } | ||
3346 | 3323 | ||
3347 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3324 | if (req->flags & ASSOC_REQ_DISABLE_HT) |
3348 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3325 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
@@ -3350,8 +3327,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3350 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3327 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3351 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3328 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3352 | if (!sband->ht_cap.ht_supported || | 3329 | if (!sband->ht_cap.ht_supported || |
3353 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) | 3330 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3354 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3331 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3332 | netdev_info(sdata->dev, | ||
3333 | "disabling HT as WMM/QoS is not supported\n"); | ||
3334 | } | ||
3355 | 3335 | ||
3356 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3336 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
3357 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 3337 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
@@ -3377,8 +3357,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3377 | (local->hw.queues >= IEEE80211_NUM_ACS); | 3357 | (local->hw.queues >= IEEE80211_NUM_ACS); |
3378 | assoc_data->supp_rates = bss->supp_rates; | 3358 | assoc_data->supp_rates = bss->supp_rates; |
3379 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3359 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3380 | assoc_data->ht_operation_ie = | 3360 | |
3381 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); | 3361 | ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); |
3362 | if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) | ||
3363 | assoc_data->ap_ht_param = | ||
3364 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | ||
3365 | else | ||
3366 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
3382 | 3367 | ||
3383 | if (bss->wmm_used && bss->uapsd_supported && | 3368 | if (bss->wmm_used && bss->uapsd_supported && |
3384 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3369 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3425,8 +3410,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3425 | * Wait up to one beacon interval ... | 3410 | * Wait up to one beacon interval ... |
3426 | * should this be more if we miss one? | 3411 | * should this be more if we miss one? |
3427 | */ | 3412 | */ |
3428 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | 3413 | pr_debug("%s: waiting for beacon from %pM\n", |
3429 | sdata->name, ifmgd->bssid); | 3414 | sdata->name, ifmgd->bssid); |
3430 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); | 3415 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); |
3431 | } else { | 3416 | } else { |
3432 | assoc_data->have_beacon = true; | 3417 | assoc_data->have_beacon = true; |
@@ -3445,8 +3430,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3445 | corrupt_type = "beacon"; | 3430 | corrupt_type = "beacon"; |
3446 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) | 3431 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) |
3447 | corrupt_type = "probe response"; | 3432 | corrupt_type = "probe response"; |
3448 | printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n", | 3433 | pr_debug("%s: associating with AP with corrupt %s\n", |
3449 | sdata->name, corrupt_type); | 3434 | sdata->name, corrupt_type); |
3450 | } | 3435 | } |
3451 | 3436 | ||
3452 | err = 0; | 3437 | err = 0; |
@@ -3475,9 +3460,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3475 | return 0; | 3460 | return 0; |
3476 | } | 3461 | } |
3477 | 3462 | ||
3478 | printk(KERN_DEBUG | 3463 | pr_debug("%s: deauthenticating from %pM by local choice (reason=%d)\n", |
3479 | "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 3464 | sdata->name, req->bssid, req->reason_code); |
3480 | sdata->name, req->bssid, req->reason_code); | ||
3481 | 3465 | ||
3482 | if (ifmgd->associated && | 3466 | if (ifmgd->associated && |
3483 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) | 3467 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) |
@@ -3519,8 +3503,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3519 | return -ENOLINK; | 3503 | return -ENOLINK; |
3520 | } | 3504 | } |
3521 | 3505 | ||
3522 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 3506 | pr_debug("%s: disassociating from %pM by local choice (reason=%d)\n", |
3523 | sdata->name, req->bss->bssid, req->reason_code); | 3507 | sdata->name, req->bss->bssid, req->reason_code); |
3524 | 3508 | ||
3525 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 3509 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
3526 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, | 3510 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, |
@@ -3561,10 +3545,3 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
3561 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 3545 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
3562 | } | 3546 | } |
3563 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 3547 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
3564 | |||
3565 | unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif) | ||
3566 | { | ||
3567 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
3568 | return sdata->dev->operstate; | ||
3569 | } | ||
3570 | EXPORT_SYMBOL(ieee80211_get_operstate); | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 935aa4b6deee..abb226dc4753 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
17 | #include "ieee80211_i.h" | 17 | #include "ieee80211_i.h" |
18 | #include "driver-trace.h" | 18 | #include "driver-trace.h" |
19 | #include "driver-ops.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Tell our hardware to disable PS. | 22 | * Tell our hardware to disable PS. |
@@ -181,34 +182,58 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
181 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&local->iflist_mtx); |
182 | } | 183 | } |
183 | 184 | ||
185 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | ||
186 | { | ||
187 | if (roc->notified) | ||
188 | return; | ||
189 | |||
190 | if (roc->mgmt_tx_cookie) { | ||
191 | if (!WARN_ON(!roc->frame)) { | ||
192 | ieee80211_tx_skb(roc->sdata, roc->frame); | ||
193 | roc->frame = NULL; | ||
194 | } | ||
195 | } else { | ||
196 | cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc, | ||
197 | roc->chan, roc->chan_type, | ||
198 | roc->req_duration, GFP_KERNEL); | ||
199 | } | ||
200 | |||
201 | roc->notified = true; | ||
202 | } | ||
203 | |||
184 | static void ieee80211_hw_roc_start(struct work_struct *work) | 204 | static void ieee80211_hw_roc_start(struct work_struct *work) |
185 | { | 205 | { |
186 | struct ieee80211_local *local = | 206 | struct ieee80211_local *local = |
187 | container_of(work, struct ieee80211_local, hw_roc_start); | 207 | container_of(work, struct ieee80211_local, hw_roc_start); |
188 | struct ieee80211_sub_if_data *sdata; | 208 | struct ieee80211_roc_work *roc, *dep, *tmp; |
189 | 209 | ||
190 | mutex_lock(&local->mtx); | 210 | mutex_lock(&local->mtx); |
191 | 211 | ||
192 | if (!local->hw_roc_channel) { | 212 | if (list_empty(&local->roc_list)) |
193 | mutex_unlock(&local->mtx); | 213 | goto out_unlock; |
194 | return; | ||
195 | } | ||
196 | 214 | ||
197 | if (local->hw_roc_skb) { | 215 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
198 | sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); | 216 | list); |
199 | ieee80211_tx_skb(sdata, local->hw_roc_skb); | 217 | |
200 | local->hw_roc_skb = NULL; | 218 | if (!roc->started) |
201 | } else { | 219 | goto out_unlock; |
202 | cfg80211_ready_on_channel(local->hw_roc_dev, | ||
203 | local->hw_roc_cookie, | ||
204 | local->hw_roc_channel, | ||
205 | local->hw_roc_channel_type, | ||
206 | local->hw_roc_duration, | ||
207 | GFP_KERNEL); | ||
208 | } | ||
209 | 220 | ||
210 | ieee80211_recalc_idle(local); | 221 | roc->hw_begun = true; |
222 | roc->hw_start_time = local->hw_roc_start_time; | ||
211 | 223 | ||
224 | ieee80211_handle_roc_started(roc); | ||
225 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) { | ||
226 | ieee80211_handle_roc_started(dep); | ||
227 | |||
228 | if (dep->duration > roc->duration) { | ||
229 | u32 dur = dep->duration; | ||
230 | dep->duration = dur - roc->duration; | ||
231 | roc->duration = dur; | ||
232 | list_del(&dep->list); | ||
233 | list_add(&dep->list, &roc->list); | ||
234 | } | ||
235 | } | ||
236 | out_unlock: | ||
212 | mutex_unlock(&local->mtx); | 237 | mutex_unlock(&local->mtx); |
213 | } | 238 | } |
214 | 239 | ||
@@ -216,52 +241,179 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw) | |||
216 | { | 241 | { |
217 | struct ieee80211_local *local = hw_to_local(hw); | 242 | struct ieee80211_local *local = hw_to_local(hw); |
218 | 243 | ||
244 | local->hw_roc_start_time = jiffies; | ||
245 | |||
219 | trace_api_ready_on_channel(local); | 246 | trace_api_ready_on_channel(local); |
220 | 247 | ||
221 | ieee80211_queue_work(hw, &local->hw_roc_start); | 248 | ieee80211_queue_work(hw, &local->hw_roc_start); |
222 | } | 249 | } |
223 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); | 250 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); |
224 | 251 | ||
225 | static void ieee80211_hw_roc_done(struct work_struct *work) | 252 | void ieee80211_start_next_roc(struct ieee80211_local *local) |
226 | { | 253 | { |
227 | struct ieee80211_local *local = | 254 | struct ieee80211_roc_work *roc; |
228 | container_of(work, struct ieee80211_local, hw_roc_done); | ||
229 | 255 | ||
230 | mutex_lock(&local->mtx); | 256 | lockdep_assert_held(&local->mtx); |
231 | 257 | ||
232 | if (!local->hw_roc_channel) { | 258 | if (list_empty(&local->roc_list)) { |
233 | mutex_unlock(&local->mtx); | 259 | ieee80211_run_deferred_scan(local); |
234 | return; | 260 | return; |
235 | } | 261 | } |
236 | 262 | ||
237 | /* was never transmitted */ | 263 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
238 | if (local->hw_roc_skb) { | 264 | list); |
239 | u64 cookie; | ||
240 | 265 | ||
241 | cookie = local->hw_roc_cookie ^ 2; | 266 | if (local->ops->remain_on_channel) { |
267 | int ret, duration = roc->duration; | ||
242 | 268 | ||
243 | cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, | 269 | /* XXX: duplicated, see ieee80211_start_roc_work() */ |
244 | local->hw_roc_skb->data, | 270 | if (!duration) |
245 | local->hw_roc_skb->len, false, | 271 | duration = 10; |
246 | GFP_KERNEL); | ||
247 | 272 | ||
248 | kfree_skb(local->hw_roc_skb); | 273 | ret = drv_remain_on_channel(local, roc->chan, |
249 | local->hw_roc_skb = NULL; | 274 | roc->chan_type, |
250 | local->hw_roc_skb_for_status = NULL; | 275 | duration); |
276 | |||
277 | roc->started = true; | ||
278 | |||
279 | if (ret) { | ||
280 | wiphy_warn(local->hw.wiphy, | ||
281 | "failed to start next HW ROC (%d)\n", ret); | ||
282 | /* | ||
283 | * queue the work struct again to avoid recursion | ||
284 | * when multiple failures occur | ||
285 | */ | ||
286 | ieee80211_remain_on_channel_expired(&local->hw); | ||
287 | } | ||
288 | } else { | ||
289 | /* delay it a bit */ | ||
290 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | ||
291 | round_jiffies_relative(HZ/2)); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | ||
296 | { | ||
297 | struct ieee80211_roc_work *dep, *tmp; | ||
298 | |||
299 | /* was never transmitted */ | ||
300 | if (roc->frame) { | ||
301 | cfg80211_mgmt_tx_status(roc->sdata->dev, | ||
302 | (unsigned long)roc->frame, | ||
303 | roc->frame->data, roc->frame->len, | ||
304 | false, GFP_KERNEL); | ||
305 | kfree_skb(roc->frame); | ||
251 | } | 306 | } |
252 | 307 | ||
253 | if (!local->hw_roc_for_tx) | 308 | if (!roc->mgmt_tx_cookie) |
254 | cfg80211_remain_on_channel_expired(local->hw_roc_dev, | 309 | cfg80211_remain_on_channel_expired(roc->sdata->dev, |
255 | local->hw_roc_cookie, | 310 | (unsigned long)roc, |
256 | local->hw_roc_channel, | 311 | roc->chan, roc->chan_type, |
257 | local->hw_roc_channel_type, | ||
258 | GFP_KERNEL); | 312 | GFP_KERNEL); |
259 | 313 | ||
260 | local->hw_roc_channel = NULL; | 314 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
261 | local->hw_roc_cookie = 0; | 315 | ieee80211_roc_notify_destroy(dep); |
316 | |||
317 | kfree(roc); | ||
318 | } | ||
319 | |||
320 | void ieee80211_sw_roc_work(struct work_struct *work) | ||
321 | { | ||
322 | struct ieee80211_roc_work *roc = | ||
323 | container_of(work, struct ieee80211_roc_work, work.work); | ||
324 | struct ieee80211_sub_if_data *sdata = roc->sdata; | ||
325 | struct ieee80211_local *local = sdata->local; | ||
326 | |||
327 | mutex_lock(&local->mtx); | ||
328 | |||
329 | if (roc->abort) | ||
330 | goto finish; | ||
331 | |||
332 | if (WARN_ON(list_empty(&local->roc_list))) | ||
333 | goto out_unlock; | ||
334 | |||
335 | if (WARN_ON(roc != list_first_entry(&local->roc_list, | ||
336 | struct ieee80211_roc_work, | ||
337 | list))) | ||
338 | goto out_unlock; | ||
339 | |||
340 | if (!roc->started) { | ||
341 | struct ieee80211_roc_work *dep; | ||
342 | |||
343 | /* start this ROC */ | ||
262 | 344 | ||
263 | ieee80211_recalc_idle(local); | 345 | /* switch channel etc */ |
346 | ieee80211_recalc_idle(local); | ||
264 | 347 | ||
348 | local->tmp_channel = roc->chan; | ||
349 | local->tmp_channel_type = roc->chan_type; | ||
350 | ieee80211_hw_config(local, 0); | ||
351 | |||
352 | /* tell userspace or send frame */ | ||
353 | ieee80211_handle_roc_started(roc); | ||
354 | list_for_each_entry(dep, &roc->dependents, list) | ||
355 | ieee80211_handle_roc_started(dep); | ||
356 | |||
357 | /* if it was pure TX, just finish right away */ | ||
358 | if (!roc->duration) | ||
359 | goto finish; | ||
360 | |||
361 | roc->started = true; | ||
362 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | ||
363 | msecs_to_jiffies(roc->duration)); | ||
364 | } else { | ||
365 | /* finish this ROC */ | ||
366 | finish: | ||
367 | list_del(&roc->list); | ||
368 | ieee80211_roc_notify_destroy(roc); | ||
369 | |||
370 | if (roc->started) { | ||
371 | drv_flush(local, false); | ||
372 | |||
373 | local->tmp_channel = NULL; | ||
374 | ieee80211_hw_config(local, 0); | ||
375 | |||
376 | ieee80211_offchannel_return(local, true); | ||
377 | } | ||
378 | |||
379 | ieee80211_recalc_idle(local); | ||
380 | |||
381 | ieee80211_start_next_roc(local); | ||
382 | ieee80211_run_deferred_scan(local); | ||
383 | } | ||
384 | |||
385 | out_unlock: | ||
386 | mutex_unlock(&local->mtx); | ||
387 | } | ||
388 | |||
389 | static void ieee80211_hw_roc_done(struct work_struct *work) | ||
390 | { | ||
391 | struct ieee80211_local *local = | ||
392 | container_of(work, struct ieee80211_local, hw_roc_done); | ||
393 | struct ieee80211_roc_work *roc; | ||
394 | |||
395 | mutex_lock(&local->mtx); | ||
396 | |||
397 | if (list_empty(&local->roc_list)) | ||
398 | goto out_unlock; | ||
399 | |||
400 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | ||
401 | list); | ||
402 | |||
403 | if (!roc->started) | ||
404 | goto out_unlock; | ||
405 | |||
406 | list_del(&roc->list); | ||
407 | |||
408 | ieee80211_roc_notify_destroy(roc); | ||
409 | |||
410 | /* if there's another roc, start it now */ | ||
411 | ieee80211_start_next_roc(local); | ||
412 | |||
413 | /* or scan maybe */ | ||
414 | ieee80211_run_deferred_scan(local); | ||
415 | |||
416 | out_unlock: | ||
265 | mutex_unlock(&local->mtx); | 417 | mutex_unlock(&local->mtx); |
266 | } | 418 | } |
267 | 419 | ||
@@ -275,8 +427,48 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) | |||
275 | } | 427 | } |
276 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); | 428 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); |
277 | 429 | ||
278 | void ieee80211_hw_roc_setup(struct ieee80211_local *local) | 430 | void ieee80211_roc_setup(struct ieee80211_local *local) |
279 | { | 431 | { |
280 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); | 432 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); |
281 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); | 433 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); |
434 | INIT_LIST_HEAD(&local->roc_list); | ||
435 | } | ||
436 | |||
437 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) | ||
438 | { | ||
439 | struct ieee80211_local *local = sdata->local; | ||
440 | struct ieee80211_roc_work *roc, *tmp; | ||
441 | LIST_HEAD(tmp_list); | ||
442 | |||
443 | mutex_lock(&local->mtx); | ||
444 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
445 | if (roc->sdata != sdata) | ||
446 | continue; | ||
447 | |||
448 | if (roc->started && local->ops->remain_on_channel) { | ||
449 | /* can race, so ignore return value */ | ||
450 | drv_cancel_remain_on_channel(local); | ||
451 | } | ||
452 | |||
453 | list_move_tail(&roc->list, &tmp_list); | ||
454 | roc->abort = true; | ||
455 | } | ||
456 | |||
457 | ieee80211_start_next_roc(local); | ||
458 | ieee80211_run_deferred_scan(local); | ||
459 | mutex_unlock(&local->mtx); | ||
460 | |||
461 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | ||
462 | if (local->ops->remain_on_channel) { | ||
463 | list_del(&roc->list); | ||
464 | ieee80211_roc_notify_destroy(roc); | ||
465 | } else { | ||
466 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | ||
467 | |||
468 | /* work will clean up etc */ | ||
469 | flush_delayed_work(&roc->work); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | WARN_ON_ONCE(!list_empty(&tmp_list)); | ||
282 | } | 474 | } |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index af1c4e26e965..98c128be3827 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -77,6 +77,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
77 | int err = drv_suspend(local, wowlan); | 77 | int err = drv_suspend(local, wowlan); |
78 | if (err < 0) { | 78 | if (err < 0) { |
79 | local->quiescing = false; | 79 | local->quiescing = false; |
80 | local->wowlan = false; | ||
80 | return err; | 81 | return err; |
81 | } else if (err > 0) { | 82 | } else if (err > 0) { |
82 | WARN_ON(err != 1); | 83 | WARN_ON(err != 1); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7bcecf73aafb..6fd2cb0838c4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1137,22 +1137,22 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1137 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1137 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1138 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1138 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1139 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1139 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1140 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1140 | pr_debug("%s: STA %pM aid %d enters power save mode\n", |
1141 | sdata->name, sta->sta.addr, sta->sta.aid); | 1141 | sdata->name, sta->sta.addr, sta->sta.aid); |
1142 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1142 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static void ap_sta_ps_end(struct sta_info *sta) | 1145 | static void ap_sta_ps_end(struct sta_info *sta) |
1146 | { | 1146 | { |
1147 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1147 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1148 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1148 | pr_debug("%s: STA %pM aid %d exits power save mode\n", |
1149 | sta->sdata->name, sta->sta.addr, sta->sta.aid); | 1149 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1150 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1150 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1151 | 1151 | ||
1152 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1152 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
1153 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1153 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1154 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1154 | pr_debug("%s: STA %pM aid %d driver-ps-blocked\n", |
1155 | sta->sdata->name, sta->sta.addr, sta->sta.aid); | 1155 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1156 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1156 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1157 | return; | 1157 | return; |
1158 | } | 1158 | } |
@@ -1387,12 +1387,10 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1388 | struct ieee80211_hdr *hdr = | 1388 | struct ieee80211_hdr *hdr = |
1389 | (struct ieee80211_hdr *) entry->skb_list.next->data; | 1389 | (struct ieee80211_hdr *) entry->skb_list.next->data; |
1390 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " | 1390 | pr_debug("%s: RX reassembly removed oldest fragment entry (idx=%d age=%lu seq=%d last_frag=%d addr1=%pM addr2=%pM\n", |
1391 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " | 1391 | sdata->name, idx, |
1392 | "addr1=%pM addr2=%pM\n", | 1392 | jiffies - entry->first_frag_time, entry->seq, |
1393 | sdata->name, idx, | 1393 | entry->last_frag, hdr->addr1, hdr->addr2); |
1394 | jiffies - entry->first_frag_time, entry->seq, | ||
1395 | entry->last_frag, hdr->addr1, hdr->addr2); | ||
1396 | #endif | 1394 | #endif |
1397 | __skb_queue_purge(&entry->skb_list); | 1395 | __skb_queue_purge(&entry->skb_list); |
1398 | } | 1396 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6d90a562669f..267b2940fadd 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -322,7 +322,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
322 | ieee80211_mlme_notify_scan_completed(local); | 322 | ieee80211_mlme_notify_scan_completed(local); |
323 | ieee80211_ibss_notify_scan_completed(local); | 323 | ieee80211_ibss_notify_scan_completed(local); |
324 | ieee80211_mesh_notify_scan_completed(local); | 324 | ieee80211_mesh_notify_scan_completed(local); |
325 | ieee80211_queue_work(&local->hw, &local->work_work); | 325 | ieee80211_start_next_roc(local); |
326 | } | 326 | } |
327 | 327 | ||
328 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 328 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
@@ -375,7 +375,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
375 | static bool ieee80211_can_scan(struct ieee80211_local *local, | 375 | static bool ieee80211_can_scan(struct ieee80211_local *local, |
376 | struct ieee80211_sub_if_data *sdata) | 376 | struct ieee80211_sub_if_data *sdata) |
377 | { | 377 | { |
378 | if (!list_empty(&local->work_list)) | 378 | if (!list_empty(&local->roc_list)) |
379 | return false; | 379 | return false; |
380 | 380 | ||
381 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 381 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index de455f8bbb91..77dcf2f89d42 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -333,9 +333,8 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local, | |||
333 | } | 333 | } |
334 | 334 | ||
335 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 335 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
336 | printk(KERN_DEBUG | 336 | pr_debug("%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n", |
337 | "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n", | 337 | sdata->name, sta->sta.addr, state + 1, err); |
338 | sdata->name, sta->sta.addr, state + 1, err); | ||
339 | err = 0; | 338 | err = 0; |
340 | } | 339 | } |
341 | 340 | ||
@@ -619,8 +618,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
619 | 618 | ||
620 | local->total_ps_buffered--; | 619 | local->total_ps_buffered--; |
621 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 620 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
622 | printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", | 621 | pr_debug("Buffered frame expired (STA %pM)\n", sta->sta.addr); |
623 | sta->sta.addr); | ||
624 | #endif | 622 | #endif |
625 | dev_kfree_skb(skb); | 623 | dev_kfree_skb(skb); |
626 | } | 624 | } |
@@ -889,10 +887,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
889 | continue; | 887 | continue; |
890 | 888 | ||
891 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 889 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
892 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 890 | ibss_vdbg("%s: expiring inactive STA %pM\n", |
893 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 891 | sdata->name, sta->sta.addr); |
894 | sdata->name, sta->sta.addr); | ||
895 | #endif | ||
896 | WARN_ON(__sta_info_destroy(sta)); | 892 | WARN_ON(__sta_info_destroy(sta)); |
897 | } | 893 | } |
898 | } | 894 | } |
@@ -991,9 +987,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
991 | sta_info_recalc_tim(sta); | 987 | sta_info_recalc_tim(sta); |
992 | 988 | ||
993 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 989 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
994 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 990 | pr_debug("%s: STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", |
995 | "since STA not sleeping anymore\n", sdata->name, | 991 | sdata->name, sta->sta.addr, sta->sta.aid, filtered, buffered); |
996 | sta->sta.addr, sta->sta.aid, filtered, buffered); | ||
997 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 992 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
998 | } | 993 | } |
999 | 994 | ||
@@ -1385,8 +1380,8 @@ int sta_info_move_state(struct sta_info *sta, | |||
1385 | } | 1380 | } |
1386 | 1381 | ||
1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1382 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1388 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | 1383 | pr_debug("%s: moving STA %pM to state %d\n", |
1389 | sta->sdata->name, sta->sta.addr, new_state); | 1384 | sta->sdata->name, sta->sta.addr, new_state); |
1390 | #endif | 1385 | #endif |
1391 | 1386 | ||
1392 | /* | 1387 | /* |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 28cfa981cfb1..6b4f42527887 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -520,36 +520,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
520 | 520 | ||
521 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 521 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
522 | u64 cookie = (unsigned long)skb; | 522 | u64 cookie = (unsigned long)skb; |
523 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
523 | 524 | ||
524 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 525 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
525 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | 526 | ieee80211_is_qos_nullfunc(hdr->frame_control)) |
526 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
527 | |||
528 | cfg80211_probe_status(skb->dev, hdr->addr1, | 527 | cfg80211_probe_status(skb->dev, hdr->addr1, |
529 | cookie, acked, GFP_ATOMIC); | 528 | cookie, acked, GFP_ATOMIC); |
530 | } else { | 529 | else |
531 | struct ieee80211_work *wk; | ||
532 | |||
533 | rcu_read_lock(); | ||
534 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
535 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
536 | continue; | ||
537 | if (wk->offchan_tx.frame != skb) | ||
538 | continue; | ||
539 | wk->offchan_tx.status = true; | ||
540 | break; | ||
541 | } | ||
542 | rcu_read_unlock(); | ||
543 | if (local->hw_roc_skb_for_status == skb) { | ||
544 | cookie = local->hw_roc_cookie ^ 2; | ||
545 | local->hw_roc_skb_for_status = NULL; | ||
546 | } | ||
547 | |||
548 | cfg80211_mgmt_tx_status( | 530 | cfg80211_mgmt_tx_status( |
549 | skb->dev, cookie, skb->data, skb->len, | 531 | skb->dev, cookie, skb->data, skb->len, |
550 | !!(info->flags & IEEE80211_TX_STAT_ACK), | 532 | acked, GFP_ATOMIC); |
551 | GFP_ATOMIC); | ||
552 | } | ||
553 | } | 533 | } |
554 | 534 | ||
555 | if (unlikely(info->ack_frame_id)) { | 535 | if (unlikely(info->ack_frame_id)) { |
@@ -589,7 +569,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
589 | /* send frame to monitor interfaces now */ | 569 | /* send frame to monitor interfaces now */ |
590 | rtap_len = ieee80211_tx_radiotap_len(info); | 570 | rtap_len = ieee80211_tx_radiotap_len(info); |
591 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { | 571 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { |
592 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | 572 | pr_err("ieee80211_tx_status: headroom too small\n"); |
593 | dev_kfree_skb(skb); | 573 | dev_kfree_skb(skb); |
594 | return; | 574 | return; |
595 | } | 575 | } |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 51077a956a83..68be47ca208f 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -263,12 +263,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
263 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 263 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
264 | { | 264 | { |
265 | int i; | 265 | int i; |
266 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); | 266 | pr_debug("TKIP decrypt: data(len=%zd)", payload_len); |
267 | for (i = 0; i < payload_len; i++) | 267 | for (i = 0; i < payload_len; i++) |
268 | printk(" %02x", payload[i]); | 268 | printk(" %02x", payload[i]); |
269 | printk("\n"); | 269 | printk("\n"); |
270 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", | 270 | pr_debug("TKIP decrypt: iv16=%04x iv32=%08x\n", iv16, iv32); |
271 | iv16, iv32); | ||
272 | } | 271 | } |
273 | #endif | 272 | #endif |
274 | 273 | ||
@@ -283,11 +282,10 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
283 | (iv32 == key->u.tkip.rx[queue].iv32 && | 282 | (iv32 == key->u.tkip.rx[queue].iv32 && |
284 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 283 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
285 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 284 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
286 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " | 285 | pr_debug("TKIP replay detected for RX frame from %pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", |
287 | "%pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", | 286 | ta, iv32, iv16, |
288 | ta, | 287 | key->u.tkip.rx[queue].iv32, |
289 | iv32, iv16, key->u.tkip.rx[queue].iv32, | 288 | key->u.tkip.rx[queue].iv16); |
290 | key->u.tkip.rx[queue].iv16); | ||
291 | #endif | 289 | #endif |
292 | return TKIP_DECRYPT_REPLAY; | 290 | return TKIP_DECRYPT_REPLAY; |
293 | } | 291 | } |
@@ -306,13 +304,12 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
306 | { | 304 | { |
307 | int i; | 305 | int i; |
308 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; | 306 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; |
309 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%pM" | 307 | pr_debug("TKIP decrypt: Phase1 TA=%pM TK=", ta); |
310 | " TK=", ta); | ||
311 | for (i = 0; i < 16; i++) | 308 | for (i = 0; i < 16; i++) |
312 | printk("%02x ", | 309 | printk("%02x ", |
313 | key->conf.key[key_offset + i]); | 310 | key->conf.key[key_offset + i]); |
314 | printk("\n"); | 311 | printk("\n"); |
315 | printk(KERN_DEBUG "TKIP decrypt: P1K="); | 312 | pr_debug("TKIP decrypt: P1K="); |
316 | for (i = 0; i < 5; i++) | 313 | for (i = 0; i < 5; i++) |
317 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); | 314 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); |
318 | printk("\n"); | 315 | printk("\n"); |
@@ -336,7 +333,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
336 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 333 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
337 | { | 334 | { |
338 | int i; | 335 | int i; |
339 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); | 336 | pr_debug("TKIP decrypt: Phase2 rc4key="); |
340 | for (i = 0; i < 16; i++) | 337 | for (i = 0; i < 16; i++) |
341 | printk("%02x ", rc4key[i]); | 338 | printk("%02x ", rc4key[i]); |
342 | printk("\n"); | 339 | printk("\n"); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e453212fa17f..af25c4e7ec5c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -297,9 +297,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
297 | if (unlikely(!assoc && | 297 | if (unlikely(!assoc && |
298 | ieee80211_is_data(hdr->frame_control))) { | 298 | ieee80211_is_data(hdr->frame_control))) { |
299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
300 | printk(KERN_DEBUG "%s: dropped data frame to not " | 300 | pr_debug("%s: dropped data frame to not associated station %pM\n", |
301 | "associated station %pM\n", | 301 | tx->sdata->name, hdr->addr1); |
302 | tx->sdata->name, hdr->addr1); | ||
303 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 302 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
304 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 303 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
305 | return TX_DROP; | 304 | return TX_DROP; |
@@ -467,8 +466,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
467 | } | 466 | } |
468 | 467 | ||
469 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 468 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
470 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", | 469 | pr_debug("STA %pM aid %d: PS buffer for AC %d\n", |
471 | sta->sta.addr, sta->sta.aid, ac); | 470 | sta->sta.addr, sta->sta.aid, ac); |
472 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 471 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
473 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 472 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
474 | purge_old_ps_buffers(tx->local); | 473 | purge_old_ps_buffers(tx->local); |
@@ -502,9 +501,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
502 | } | 501 | } |
503 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 502 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
504 | else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { | 503 | else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { |
505 | printk(KERN_DEBUG | 504 | pr_debug("%s: STA %pM in PS mode, but polling/in SP -> send frame\n", |
506 | "%s: STA %pM in PS mode, but polling/in SP -> send frame\n", | 505 | tx->sdata->name, sta->sta.addr); |
507 | tx->sdata->name, sta->sta.addr); | ||
508 | } | 506 | } |
509 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 507 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
510 | 508 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 8dd4712620ff..1df4019f294b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -804,7 +804,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
804 | struct ieee80211_local *local = sdata->local; | 804 | struct ieee80211_local *local = sdata->local; |
805 | struct ieee80211_tx_queue_params qparam; | 805 | struct ieee80211_tx_queue_params qparam; |
806 | int ac; | 806 | int ac; |
807 | bool use_11b; | 807 | bool use_11b, enable_qos; |
808 | int aCWmin, aCWmax; | 808 | int aCWmin, aCWmax; |
809 | 809 | ||
810 | if (!local->ops->conf_tx) | 810 | if (!local->ops->conf_tx) |
@@ -818,6 +818,13 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
818 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && | 818 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && |
819 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 819 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
820 | 820 | ||
821 | /* | ||
822 | * By default disable QoS in STA mode for old access points, which do | ||
823 | * not support 802.11e. New APs will provide proper queue parameters, | ||
824 | * that we will configure later. | ||
825 | */ | ||
826 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); | ||
827 | |||
821 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 828 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
822 | /* Set defaults according to 802.11-2007 Table 7-37 */ | 829 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
823 | aCWmax = 1023; | 830 | aCWmax = 1023; |
@@ -826,38 +833,47 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
826 | else | 833 | else |
827 | aCWmin = 15; | 834 | aCWmin = 15; |
828 | 835 | ||
829 | switch (ac) { | 836 | if (enable_qos) { |
830 | case IEEE80211_AC_BK: | 837 | switch (ac) { |
831 | qparam.cw_max = aCWmax; | 838 | case IEEE80211_AC_BK: |
832 | qparam.cw_min = aCWmin; | 839 | qparam.cw_max = aCWmax; |
833 | qparam.txop = 0; | 840 | qparam.cw_min = aCWmin; |
834 | qparam.aifs = 7; | 841 | qparam.txop = 0; |
835 | break; | 842 | qparam.aifs = 7; |
836 | default: /* never happens but let's not leave undefined */ | 843 | break; |
837 | case IEEE80211_AC_BE: | 844 | /* never happens but let's not leave undefined */ |
845 | default: | ||
846 | case IEEE80211_AC_BE: | ||
847 | qparam.cw_max = aCWmax; | ||
848 | qparam.cw_min = aCWmin; | ||
849 | qparam.txop = 0; | ||
850 | qparam.aifs = 3; | ||
851 | break; | ||
852 | case IEEE80211_AC_VI: | ||
853 | qparam.cw_max = aCWmin; | ||
854 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | ||
855 | if (use_11b) | ||
856 | qparam.txop = 6016/32; | ||
857 | else | ||
858 | qparam.txop = 3008/32; | ||
859 | qparam.aifs = 2; | ||
860 | break; | ||
861 | case IEEE80211_AC_VO: | ||
862 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | ||
863 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | ||
864 | if (use_11b) | ||
865 | qparam.txop = 3264/32; | ||
866 | else | ||
867 | qparam.txop = 1504/32; | ||
868 | qparam.aifs = 2; | ||
869 | break; | ||
870 | } | ||
871 | } else { | ||
872 | /* Confiure old 802.11b/g medium access rules. */ | ||
838 | qparam.cw_max = aCWmax; | 873 | qparam.cw_max = aCWmax; |
839 | qparam.cw_min = aCWmin; | 874 | qparam.cw_min = aCWmin; |
840 | qparam.txop = 0; | 875 | qparam.txop = 0; |
841 | qparam.aifs = 3; | ||
842 | break; | ||
843 | case IEEE80211_AC_VI: | ||
844 | qparam.cw_max = aCWmin; | ||
845 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | ||
846 | if (use_11b) | ||
847 | qparam.txop = 6016/32; | ||
848 | else | ||
849 | qparam.txop = 3008/32; | ||
850 | qparam.aifs = 2; | ||
851 | break; | ||
852 | case IEEE80211_AC_VO: | ||
853 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | ||
854 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | ||
855 | if (use_11b) | ||
856 | qparam.txop = 3264/32; | ||
857 | else | ||
858 | qparam.txop = 1504/32; | ||
859 | qparam.aifs = 2; | 876 | qparam.aifs = 2; |
860 | break; | ||
861 | } | 877 | } |
862 | 878 | ||
863 | qparam.uapsd = false; | 879 | qparam.uapsd = false; |
@@ -866,12 +882,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
866 | drv_conf_tx(local, sdata, ac, &qparam); | 882 | drv_conf_tx(local, sdata, ac, &qparam); |
867 | } | 883 | } |
868 | 884 | ||
869 | /* after reinitialize QoS TX queues setting to default, | ||
870 | * disable QoS at all */ | ||
871 | |||
872 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 885 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
873 | sdata->vif.bss_conf.qos = | 886 | sdata->vif.bss_conf.qos = enable_qos; |
874 | sdata->vif.type != NL80211_IFTYPE_STATION; | ||
875 | if (bss_notify) | 887 | if (bss_notify) |
876 | ieee80211_bss_info_change_notify(sdata, | 888 | ieee80211_bss_info_change_notify(sdata, |
877 | BSS_CHANGED_QOS); | 889 | BSS_CHANGED_QOS); |
@@ -1267,14 +1279,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1267 | /* add STAs back */ | 1279 | /* add STAs back */ |
1268 | mutex_lock(&local->sta_mtx); | 1280 | mutex_lock(&local->sta_mtx); |
1269 | list_for_each_entry(sta, &local->sta_list, list) { | 1281 | list_for_each_entry(sta, &local->sta_list, list) { |
1270 | if (sta->uploaded) { | 1282 | enum ieee80211_sta_state state; |
1271 | enum ieee80211_sta_state state; | ||
1272 | 1283 | ||
1273 | for (state = IEEE80211_STA_NOTEXIST; | 1284 | if (!sta->uploaded) |
1274 | state < sta->sta_state; state++) | 1285 | continue; |
1275 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | 1286 | |
1276 | state, state + 1)); | 1287 | /* AP-mode stations will be added later */ |
1277 | } | 1288 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) |
1289 | continue; | ||
1290 | |||
1291 | for (state = IEEE80211_STA_NOTEXIST; | ||
1292 | state < sta->sta_state; state++) | ||
1293 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1294 | state + 1)); | ||
1278 | } | 1295 | } |
1279 | mutex_unlock(&local->sta_mtx); | 1296 | mutex_unlock(&local->sta_mtx); |
1280 | 1297 | ||
@@ -1371,6 +1388,24 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1371 | } | 1388 | } |
1372 | } | 1389 | } |
1373 | 1390 | ||
1391 | /* APs are now beaconing, add back stations */ | ||
1392 | mutex_lock(&local->sta_mtx); | ||
1393 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1394 | enum ieee80211_sta_state state; | ||
1395 | |||
1396 | if (!sta->uploaded) | ||
1397 | continue; | ||
1398 | |||
1399 | if (sta->sdata->vif.type != NL80211_IFTYPE_AP) | ||
1400 | continue; | ||
1401 | |||
1402 | for (state = IEEE80211_STA_NOTEXIST; | ||
1403 | state < sta->sta_state; state++) | ||
1404 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1405 | state + 1)); | ||
1406 | } | ||
1407 | mutex_unlock(&local->sta_mtx); | ||
1408 | |||
1374 | /* add back keys */ | 1409 | /* add back keys */ |
1375 | list_for_each_entry(sdata, &local->interfaces, list) | 1410 | list_for_each_entry(sdata, &local->interfaces, list) |
1376 | if (ieee80211_sdata_running(sdata)) | 1411 | if (ieee80211_sdata_running(sdata)) |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c deleted file mode 100644 index b2650a9d45ff..000000000000 --- a/net/mac80211/work.c +++ /dev/null | |||
@@ -1,370 +0,0 @@ | |||
1 | /* | ||
2 | * mac80211 work implementation | ||
3 | * | ||
4 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/delay.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/if_arp.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <net/mac80211.h> | ||
24 | #include <asm/unaligned.h> | ||
25 | |||
26 | #include "ieee80211_i.h" | ||
27 | #include "rate.h" | ||
28 | #include "driver-ops.h" | ||
29 | |||
30 | enum work_action { | ||
31 | WORK_ACT_NONE, | ||
32 | WORK_ACT_TIMEOUT, | ||
33 | }; | ||
34 | |||
35 | |||
36 | /* utils */ | ||
37 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | ||
38 | { | ||
39 | lockdep_assert_held(&local->mtx); | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * We can have multiple work items (and connection probing) | ||
44 | * scheduling this timer, but we need to take care to only | ||
45 | * reschedule it when it should fire _earlier_ than it was | ||
46 | * asked for before, or if it's not pending right now. This | ||
47 | * function ensures that. Note that it then is required to | ||
48 | * run this function for all timeouts after the first one | ||
49 | * has happened -- the work that runs from this timer will | ||
50 | * do that. | ||
51 | */ | ||
52 | static void run_again(struct ieee80211_local *local, | ||
53 | unsigned long timeout) | ||
54 | { | ||
55 | ASSERT_WORK_MTX(local); | ||
56 | |||
57 | if (!timer_pending(&local->work_timer) || | ||
58 | time_before(timeout, local->work_timer.expires)) | ||
59 | mod_timer(&local->work_timer, timeout); | ||
60 | } | ||
61 | |||
62 | void free_work(struct ieee80211_work *wk) | ||
63 | { | ||
64 | kfree_rcu(wk, rcu_head); | ||
65 | } | ||
66 | |||
67 | static enum work_action __must_check | ||
68 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | ||
69 | { | ||
70 | /* | ||
71 | * First time we run, do nothing -- the generic code will | ||
72 | * have switched to the right channel etc. | ||
73 | */ | ||
74 | if (!wk->started) { | ||
75 | wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); | ||
76 | |||
77 | cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, | ||
78 | wk->chan, wk->chan_type, | ||
79 | wk->remain.duration, GFP_KERNEL); | ||
80 | |||
81 | return WORK_ACT_NONE; | ||
82 | } | ||
83 | |||
84 | return WORK_ACT_TIMEOUT; | ||
85 | } | ||
86 | |||
87 | static enum work_action __must_check | ||
88 | ieee80211_offchannel_tx(struct ieee80211_work *wk) | ||
89 | { | ||
90 | if (!wk->started) { | ||
91 | wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait); | ||
92 | |||
93 | /* | ||
94 | * After this, offchan_tx.frame remains but now is no | ||
95 | * longer a valid pointer -- we still need it as the | ||
96 | * cookie for canceling this work/status matching. | ||
97 | */ | ||
98 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | ||
99 | |||
100 | return WORK_ACT_NONE; | ||
101 | } | ||
102 | |||
103 | return WORK_ACT_TIMEOUT; | ||
104 | } | ||
105 | |||
106 | static void ieee80211_work_timer(unsigned long data) | ||
107 | { | ||
108 | struct ieee80211_local *local = (void *) data; | ||
109 | |||
110 | if (local->quiescing) | ||
111 | return; | ||
112 | |||
113 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
114 | } | ||
115 | |||
116 | static void ieee80211_work_work(struct work_struct *work) | ||
117 | { | ||
118 | struct ieee80211_local *local = | ||
119 | container_of(work, struct ieee80211_local, work_work); | ||
120 | struct ieee80211_work *wk, *tmp; | ||
121 | LIST_HEAD(free_work); | ||
122 | enum work_action rma; | ||
123 | bool remain_off_channel = false; | ||
124 | |||
125 | /* | ||
126 | * ieee80211_queue_work() should have picked up most cases, | ||
127 | * here we'll pick the rest. | ||
128 | */ | ||
129 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | ||
130 | return; | ||
131 | |||
132 | mutex_lock(&local->mtx); | ||
133 | |||
134 | if (local->scanning) { | ||
135 | mutex_unlock(&local->mtx); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | ieee80211_recalc_idle(local); | ||
140 | |||
141 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
142 | bool started = wk->started; | ||
143 | |||
144 | /* mark work as started if it's on the current off-channel */ | ||
145 | if (!started && local->tmp_channel && | ||
146 | wk->chan == local->tmp_channel && | ||
147 | wk->chan_type == local->tmp_channel_type) { | ||
148 | started = true; | ||
149 | wk->timeout = jiffies; | ||
150 | } | ||
151 | |||
152 | if (!started && !local->tmp_channel) { | ||
153 | ieee80211_offchannel_stop_vifs(local, true); | ||
154 | |||
155 | local->tmp_channel = wk->chan; | ||
156 | local->tmp_channel_type = wk->chan_type; | ||
157 | |||
158 | ieee80211_hw_config(local, 0); | ||
159 | |||
160 | started = true; | ||
161 | wk->timeout = jiffies; | ||
162 | } | ||
163 | |||
164 | /* don't try to work with items that aren't started */ | ||
165 | if (!started) | ||
166 | continue; | ||
167 | |||
168 | if (time_is_after_jiffies(wk->timeout)) { | ||
169 | /* | ||
170 | * This work item isn't supposed to be worked on | ||
171 | * right now, but take care to adjust the timer | ||
172 | * properly. | ||
173 | */ | ||
174 | run_again(local, wk->timeout); | ||
175 | continue; | ||
176 | } | ||
177 | |||
178 | switch (wk->type) { | ||
179 | default: | ||
180 | WARN_ON(1); | ||
181 | /* nothing */ | ||
182 | rma = WORK_ACT_NONE; | ||
183 | break; | ||
184 | case IEEE80211_WORK_ABORT: | ||
185 | rma = WORK_ACT_TIMEOUT; | ||
186 | break; | ||
187 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | ||
188 | rma = ieee80211_remain_on_channel_timeout(wk); | ||
189 | break; | ||
190 | case IEEE80211_WORK_OFFCHANNEL_TX: | ||
191 | rma = ieee80211_offchannel_tx(wk); | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | wk->started = started; | ||
196 | |||
197 | switch (rma) { | ||
198 | case WORK_ACT_NONE: | ||
199 | /* might have changed the timeout */ | ||
200 | run_again(local, wk->timeout); | ||
201 | break; | ||
202 | case WORK_ACT_TIMEOUT: | ||
203 | list_del_rcu(&wk->list); | ||
204 | synchronize_rcu(); | ||
205 | list_add(&wk->list, &free_work); | ||
206 | break; | ||
207 | default: | ||
208 | WARN(1, "unexpected: %d", rma); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | list_for_each_entry(wk, &local->work_list, list) { | ||
213 | if (!wk->started) | ||
214 | continue; | ||
215 | if (wk->chan != local->tmp_channel || | ||
216 | wk->chan_type != local->tmp_channel_type) | ||
217 | continue; | ||
218 | remain_off_channel = true; | ||
219 | } | ||
220 | |||
221 | if (!remain_off_channel && local->tmp_channel) { | ||
222 | local->tmp_channel = NULL; | ||
223 | ieee80211_hw_config(local, 0); | ||
224 | |||
225 | ieee80211_offchannel_return(local, true); | ||
226 | |||
227 | /* give connection some time to breathe */ | ||
228 | run_again(local, jiffies + HZ/2); | ||
229 | } | ||
230 | |||
231 | ieee80211_recalc_idle(local); | ||
232 | ieee80211_run_deferred_scan(local); | ||
233 | |||
234 | mutex_unlock(&local->mtx); | ||
235 | |||
236 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
237 | wk->done(wk, NULL); | ||
238 | list_del(&wk->list); | ||
239 | kfree(wk); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | void ieee80211_add_work(struct ieee80211_work *wk) | ||
244 | { | ||
245 | struct ieee80211_local *local; | ||
246 | |||
247 | if (WARN_ON(!wk->chan)) | ||
248 | return; | ||
249 | |||
250 | if (WARN_ON(!wk->sdata)) | ||
251 | return; | ||
252 | |||
253 | if (WARN_ON(!wk->done)) | ||
254 | return; | ||
255 | |||
256 | if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) | ||
257 | return; | ||
258 | |||
259 | wk->started = false; | ||
260 | |||
261 | local = wk->sdata->local; | ||
262 | mutex_lock(&local->mtx); | ||
263 | list_add_tail(&wk->list, &local->work_list); | ||
264 | mutex_unlock(&local->mtx); | ||
265 | |||
266 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
267 | } | ||
268 | |||
269 | void ieee80211_work_init(struct ieee80211_local *local) | ||
270 | { | ||
271 | INIT_LIST_HEAD(&local->work_list); | ||
272 | setup_timer(&local->work_timer, ieee80211_work_timer, | ||
273 | (unsigned long)local); | ||
274 | INIT_WORK(&local->work_work, ieee80211_work_work); | ||
275 | } | ||
276 | |||
277 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | ||
278 | { | ||
279 | struct ieee80211_local *local = sdata->local; | ||
280 | struct ieee80211_work *wk; | ||
281 | bool cleanup = false; | ||
282 | |||
283 | mutex_lock(&local->mtx); | ||
284 | list_for_each_entry(wk, &local->work_list, list) { | ||
285 | if (wk->sdata != sdata) | ||
286 | continue; | ||
287 | cleanup = true; | ||
288 | wk->type = IEEE80211_WORK_ABORT; | ||
289 | wk->started = true; | ||
290 | wk->timeout = jiffies; | ||
291 | } | ||
292 | mutex_unlock(&local->mtx); | ||
293 | |||
294 | /* run cleanups etc. */ | ||
295 | if (cleanup) | ||
296 | ieee80211_work_work(&local->work_work); | ||
297 | |||
298 | mutex_lock(&local->mtx); | ||
299 | list_for_each_entry(wk, &local->work_list, list) { | ||
300 | if (wk->sdata != sdata) | ||
301 | continue; | ||
302 | WARN_ON(1); | ||
303 | break; | ||
304 | } | ||
305 | mutex_unlock(&local->mtx); | ||
306 | } | ||
307 | |||
308 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, | ||
309 | struct sk_buff *skb) | ||
310 | { | ||
311 | /* | ||
312 | * We are done serving the remain-on-channel command. | ||
313 | */ | ||
314 | cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk, | ||
315 | wk->chan, wk->chan_type, | ||
316 | GFP_KERNEL); | ||
317 | |||
318 | return WORK_DONE_DESTROY; | ||
319 | } | ||
320 | |||
321 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
322 | struct ieee80211_channel *chan, | ||
323 | enum nl80211_channel_type channel_type, | ||
324 | unsigned int duration, u64 *cookie) | ||
325 | { | ||
326 | struct ieee80211_work *wk; | ||
327 | |||
328 | wk = kzalloc(sizeof(*wk), GFP_KERNEL); | ||
329 | if (!wk) | ||
330 | return -ENOMEM; | ||
331 | |||
332 | wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; | ||
333 | wk->chan = chan; | ||
334 | wk->chan_type = channel_type; | ||
335 | wk->sdata = sdata; | ||
336 | wk->done = ieee80211_remain_done; | ||
337 | |||
338 | wk->remain.duration = duration; | ||
339 | |||
340 | *cookie = (unsigned long) wk; | ||
341 | |||
342 | ieee80211_add_work(wk); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
348 | u64 cookie) | ||
349 | { | ||
350 | struct ieee80211_local *local = sdata->local; | ||
351 | struct ieee80211_work *wk, *tmp; | ||
352 | bool found = false; | ||
353 | |||
354 | mutex_lock(&local->mtx); | ||
355 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
356 | if ((unsigned long) wk == cookie) { | ||
357 | wk->timeout = jiffies; | ||
358 | found = true; | ||
359 | break; | ||
360 | } | ||
361 | } | ||
362 | mutex_unlock(&local->mtx); | ||
363 | |||
364 | if (!found) | ||
365 | return -ENOENT; | ||
366 | |||
367 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
368 | |||
369 | return 0; | ||
370 | } | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index 9f6ce011d35d..4177bb5104b9 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -121,14 +121,14 @@ error: | |||
121 | * The device remains polling for targets until a target is found or | 121 | * The device remains polling for targets until a target is found or |
122 | * the nfc_stop_poll function is called. | 122 | * the nfc_stop_poll function is called. |
123 | */ | 123 | */ |
124 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | 124 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) |
125 | { | 125 | { |
126 | int rc; | 126 | int rc; |
127 | 127 | ||
128 | pr_debug("dev_name=%s protocols=0x%x\n", | 128 | pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n", |
129 | dev_name(&dev->dev), protocols); | 129 | dev_name(&dev->dev), im_protocols, tm_protocols); |
130 | 130 | ||
131 | if (!protocols) | 131 | if (!im_protocols && !tm_protocols) |
132 | return -EINVAL; | 132 | return -EINVAL; |
133 | 133 | ||
134 | device_lock(&dev->dev); | 134 | device_lock(&dev->dev); |
@@ -143,9 +143,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | |||
143 | goto error; | 143 | goto error; |
144 | } | 144 | } |
145 | 145 | ||
146 | rc = dev->ops->start_poll(dev, protocols); | 146 | rc = dev->ops->start_poll(dev, im_protocols, tm_protocols); |
147 | if (!rc) | 147 | if (!rc) { |
148 | dev->polling = true; | 148 | dev->polling = true; |
149 | dev->rf_mode = NFC_RF_NONE; | ||
150 | } | ||
149 | 151 | ||
150 | error: | 152 | error: |
151 | device_unlock(&dev->dev); | 153 | device_unlock(&dev->dev); |
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | |||
235 | } | 237 | } |
236 | 238 | ||
237 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); | 239 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); |
238 | if (!rc) | 240 | if (!rc) { |
239 | dev->active_target = target; | 241 | dev->active_target = target; |
242 | dev->rf_mode = NFC_RF_INITIATOR; | ||
243 | } | ||
240 | 244 | ||
241 | error: | 245 | error: |
242 | device_unlock(&dev->dev); | 246 | device_unlock(&dev->dev); |
@@ -264,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
264 | goto error; | 268 | goto error; |
265 | } | 269 | } |
266 | 270 | ||
267 | if (dev->dep_rf_mode == NFC_RF_TARGET) { | ||
268 | rc = -EOPNOTSUPP; | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | rc = dev->ops->dep_link_down(dev); | 271 | rc = dev->ops->dep_link_down(dev); |
273 | if (!rc) { | 272 | if (!rc) { |
274 | dev->dep_link_up = false; | 273 | dev->dep_link_up = false; |
@@ -286,7 +285,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
286 | u8 comm_mode, u8 rf_mode) | 285 | u8 comm_mode, u8 rf_mode) |
287 | { | 286 | { |
288 | dev->dep_link_up = true; | 287 | dev->dep_link_up = true; |
289 | dev->dep_rf_mode = rf_mode; | ||
290 | 288 | ||
291 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 289 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
292 | 290 | ||
@@ -330,6 +328,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
330 | rc = dev->ops->activate_target(dev, target, protocol); | 328 | rc = dev->ops->activate_target(dev, target, protocol); |
331 | if (!rc) { | 329 | if (!rc) { |
332 | dev->active_target = target; | 330 | dev->active_target = target; |
331 | dev->rf_mode = NFC_RF_INITIATOR; | ||
333 | 332 | ||
334 | if (dev->ops->check_presence) | 333 | if (dev->ops->check_presence) |
335 | mod_timer(&dev->check_pres_timer, jiffies + | 334 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -409,27 +408,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
409 | goto error; | 408 | goto error; |
410 | } | 409 | } |
411 | 410 | ||
412 | if (dev->active_target == NULL) { | 411 | if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) { |
413 | rc = -ENOTCONN; | 412 | if (dev->active_target->idx != target_idx) { |
414 | kfree_skb(skb); | 413 | rc = -EADDRNOTAVAIL; |
415 | goto error; | 414 | kfree_skb(skb); |
416 | } | 415 | goto error; |
416 | } | ||
417 | 417 | ||
418 | if (dev->active_target->idx != target_idx) { | 418 | if (dev->ops->check_presence) |
419 | rc = -EADDRNOTAVAIL; | 419 | del_timer_sync(&dev->check_pres_timer); |
420 | |||
421 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | ||
422 | cb_context); | ||
423 | |||
424 | if (!rc && dev->ops->check_presence) | ||
425 | mod_timer(&dev->check_pres_timer, jiffies + | ||
426 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
427 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | ||
428 | rc = dev->ops->tm_send(dev, skb); | ||
429 | } else { | ||
430 | rc = -ENOTCONN; | ||
420 | kfree_skb(skb); | 431 | kfree_skb(skb); |
421 | goto error; | 432 | goto error; |
422 | } | 433 | } |
423 | 434 | ||
424 | if (dev->ops->check_presence) | ||
425 | del_timer_sync(&dev->check_pres_timer); | ||
426 | |||
427 | rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, | ||
428 | cb_context); | ||
429 | |||
430 | if (!rc && dev->ops->check_presence) | ||
431 | mod_timer(&dev->check_pres_timer, jiffies + | ||
432 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
433 | 435 | ||
434 | error: | 436 | error: |
435 | device_unlock(&dev->dev); | 437 | device_unlock(&dev->dev); |
@@ -447,6 +449,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
447 | } | 449 | } |
448 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 450 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
449 | 451 | ||
452 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len) | ||
453 | { | ||
454 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | ||
455 | |||
456 | return nfc_llcp_general_bytes(dev, gb_len); | ||
457 | } | ||
458 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
459 | |||
460 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
461 | { | ||
462 | /* Only LLCP target mode for now */ | ||
463 | if (dev->dep_link_up == false) { | ||
464 | kfree_skb(skb); | ||
465 | return -ENOLINK; | ||
466 | } | ||
467 | |||
468 | return nfc_llcp_data_received(dev, skb); | ||
469 | } | ||
470 | EXPORT_SYMBOL(nfc_tm_data_received); | ||
471 | |||
472 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
473 | u8 *gb, size_t gb_len) | ||
474 | { | ||
475 | int rc; | ||
476 | |||
477 | device_lock(&dev->dev); | ||
478 | |||
479 | dev->polling = false; | ||
480 | |||
481 | if (gb != NULL) { | ||
482 | rc = nfc_set_remote_general_bytes(dev, gb, gb_len); | ||
483 | if (rc < 0) | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | dev->rf_mode = NFC_RF_TARGET; | ||
488 | |||
489 | if (protocol == NFC_PROTO_NFC_DEP_MASK) | ||
490 | nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET); | ||
491 | |||
492 | rc = nfc_genl_tm_activated(dev, protocol); | ||
493 | |||
494 | out: | ||
495 | device_unlock(&dev->dev); | ||
496 | |||
497 | return rc; | ||
498 | } | ||
499 | EXPORT_SYMBOL(nfc_tm_activated); | ||
500 | |||
501 | int nfc_tm_deactivated(struct nfc_dev *dev) | ||
502 | { | ||
503 | dev->dep_link_up = false; | ||
504 | |||
505 | return nfc_genl_tm_deactivated(dev); | ||
506 | } | ||
507 | EXPORT_SYMBOL(nfc_tm_deactivated); | ||
508 | |||
450 | /** | 509 | /** |
451 | * nfc_alloc_send_skb - allocate a skb for data exchange responses | 510 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
452 | * | 511 | * |
@@ -678,7 +737,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
678 | struct nfc_dev *dev; | 737 | struct nfc_dev *dev; |
679 | 738 | ||
680 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 739 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
681 | !ops->deactivate_target || !ops->data_exchange) | 740 | !ops->deactivate_target || !ops->im_transceive) |
682 | return NULL; | 741 | return NULL; |
683 | 742 | ||
684 | if (!supported_protocols) | 743 | if (!supported_protocols) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d2b588..a8b0b71e8f86 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) | |||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 484 | static int hci_start_poll(struct nfc_dev *nfc_dev, |
485 | u32 im_protocols, u32 tm_protocols) | ||
485 | { | 486 | { |
486 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 487 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
487 | 488 | ||
488 | if (hdev->ops->start_poll) | 489 | if (hdev->ops->start_poll) |
489 | return hdev->ops->start_poll(hdev, protocols); | 490 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
490 | else | 491 | else |
491 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 492 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
492 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 493 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
@@ -511,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, | |||
511 | { | 512 | { |
512 | } | 513 | } |
513 | 514 | ||
514 | static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 515 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
515 | struct sk_buff *skb, data_exchange_cb_t cb, | 516 | struct sk_buff *skb, data_exchange_cb_t cb, |
516 | void *cb_context) | 517 | void *cb_context) |
517 | { | 518 | { |
518 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 519 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
519 | int r; | 520 | int r; |
@@ -579,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = { | |||
579 | .stop_poll = hci_stop_poll, | 580 | .stop_poll = hci_stop_poll, |
580 | .activate_target = hci_activate_target, | 581 | .activate_target = hci_activate_target, |
581 | .deactivate_target = hci_deactivate_target, | 582 | .deactivate_target = hci_deactivate_target, |
582 | .data_exchange = hci_data_exchange, | 583 | .im_transceive = hci_transceive, |
583 | .check_presence = hci_check_presence, | 584 | .check_presence = hci_check_presence, |
584 | }; | 585 | }; |
585 | 586 | ||
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 5665dc6d893a..6b836e6242b7 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
765 | return 0; | 765 | return 0; |
766 | } | 766 | } |
767 | 767 | ||
768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols) | 768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, |
769 | u32 im_protocols, u32 tm_protocols) | ||
769 | { | 770 | { |
770 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); | 771 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); |
771 | 772 | ||
772 | pr_debug("\n"); | 773 | pr_debug("\n"); |
773 | 774 | ||
774 | if (shdlc->ops->start_poll) | 775 | if (shdlc->ops->start_poll) |
775 | return shdlc->ops->start_poll(shdlc, protocols); | 776 | return shdlc->ops->start_poll(shdlc, |
777 | im_protocols, tm_protocols); | ||
776 | 778 | ||
777 | return 0; | 779 | return 0; |
778 | } | 780 | } |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index bf8ae4f0b90c..b982b5b890d7 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) | |||
51 | return tlv[2]; | 51 | return tlv[2]; |
52 | } | 52 | } |
53 | 53 | ||
54 | static u8 llcp_tlv16(u8 *tlv, u8 type) | 54 | static u16 llcp_tlv16(u8 *tlv, u8 type) |
55 | { | 55 | { |
56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | 56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) |
57 | return 0; | 57 | return 0; |
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv) | |||
67 | 67 | ||
68 | static u16 llcp_tlv_miux(u8 *tlv) | 68 | static u16 llcp_tlv_miux(u8 *tlv) |
69 | { | 69 | { |
70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; | 70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; |
71 | } | 71 | } |
72 | 72 | ||
73 | static u16 llcp_tlv_wks(u8 *tlv) | 73 | static u16 llcp_tlv_wks(u8 *tlv) |
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 121 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 122 | { |
123 | u8 *tlv = tlv_array, type, length, offset = 0; | 123 | u8 *tlv = tlv_array, type, length, offset = 0; |
124 | 124 | ||
@@ -149,8 +149,45 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
149 | case LLCP_TLV_OPT: | 149 | case LLCP_TLV_OPT: |
150 | local->remote_opt = llcp_tlv_opt(tlv); | 150 | local->remote_opt = llcp_tlv_opt(tlv); |
151 | break; | 151 | break; |
152 | default: | ||
153 | pr_err("Invalid gt tlv value 0x%x\n", type); | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | offset += length + 2; | ||
158 | tlv += length + 2; | ||
159 | } | ||
160 | |||
161 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n", | ||
162 | local->remote_version, local->remote_miu, | ||
163 | local->remote_lto, local->remote_opt, | ||
164 | local->remote_wks); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
170 | u8 *tlv_array, u16 tlv_array_len) | ||
171 | { | ||
172 | u8 *tlv = tlv_array, type, length, offset = 0; | ||
173 | |||
174 | pr_debug("TLV array length %d\n", tlv_array_len); | ||
175 | |||
176 | if (sock == NULL) | ||
177 | return -ENOTCONN; | ||
178 | |||
179 | while (offset < tlv_array_len) { | ||
180 | type = tlv[0]; | ||
181 | length = tlv[1]; | ||
182 | |||
183 | pr_debug("type 0x%x length %d\n", type, length); | ||
184 | |||
185 | switch (type) { | ||
186 | case LLCP_TLV_MIUX: | ||
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | ||
188 | break; | ||
152 | case LLCP_TLV_RW: | 189 | case LLCP_TLV_RW: |
153 | local->remote_rw = llcp_tlv_rw(tlv); | 190 | sock->rw = llcp_tlv_rw(tlv); |
154 | break; | 191 | break; |
155 | case LLCP_TLV_SN: | 192 | case LLCP_TLV_SN: |
156 | break; | 193 | break; |
@@ -163,10 +200,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
163 | tlv += length + 2; | 200 | tlv += length + 2; |
164 | } | 201 | } |
165 | 202 | ||
166 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | 203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); |
167 | local->remote_version, local->remote_miu, | ||
168 | local->remote_lto, local->remote_opt, | ||
169 | local->remote_wks, local->remote_rw); | ||
170 | 204 | ||
171 | return 0; | 205 | return 0; |
172 | } | 206 | } |
@@ -474,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 508 | ||
475 | while (remaining_len > 0) { | 509 | while (remaining_len > 0) { |
476 | 510 | ||
477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); | 511 | frag_len = min_t(size_t, sock->miu, remaining_len); |
478 | 512 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 513 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 514 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 42994fac26d6..5d503eeb15a1 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -31,47 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | |||
31 | 31 | ||
32 | static struct list_head llcp_devices; | 32 | static struct list_head llcp_devices; |
33 | 33 | ||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 34 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) |
35 | { | 35 | { |
36 | struct nfc_llcp_sock *parent, *s, *n; | 36 | write_lock(&l->lock); |
37 | struct sock *sk, *parent_sk; | 37 | sk_add_node(sk, &l->head); |
38 | int i; | 38 | write_unlock(&l->lock); |
39 | 39 | } | |
40 | mutex_lock(&local->socket_lock); | ||
41 | |||
42 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
43 | parent = local->sockets[i]; | ||
44 | if (parent == NULL) | ||
45 | continue; | ||
46 | |||
47 | /* Release all child sockets */ | ||
48 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
49 | list_del_init(&s->list); | ||
50 | sk = &s->sk; | ||
51 | |||
52 | lock_sock(sk); | ||
53 | |||
54 | if (sk->sk_state == LLCP_CONNECTED) | ||
55 | nfc_put_device(s->dev); | ||
56 | 40 | ||
57 | sk->sk_state = LLCP_CLOSED; | 41 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) |
42 | { | ||
43 | write_lock(&l->lock); | ||
44 | sk_del_node_init(sk); | ||
45 | write_unlock(&l->lock); | ||
46 | } | ||
58 | 47 | ||
59 | release_sock(sk); | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) |
49 | { | ||
50 | struct sock *sk; | ||
51 | struct hlist_node *node, *tmp; | ||
52 | struct nfc_llcp_sock *llcp_sock; | ||
60 | 53 | ||
61 | sock_orphan(sk); | 54 | write_lock(&local->sockets.lock); |
62 | 55 | ||
63 | s->local = NULL; | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
64 | } | 57 | llcp_sock = nfc_llcp_sock(sk); |
65 | 58 | ||
66 | parent_sk = &parent->sk; | 59 | lock_sock(sk); |
67 | 60 | ||
68 | lock_sock(parent_sk); | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | ||
69 | 63 | ||
70 | if (parent_sk->sk_state == LLCP_LISTEN) { | 64 | if (sk->sk_state == LLCP_LISTEN) { |
71 | struct nfc_llcp_sock *lsk, *n; | 65 | struct nfc_llcp_sock *lsk, *n; |
72 | struct sock *accept_sk; | 66 | struct sock *accept_sk; |
73 | 67 | ||
74 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
75 | accept_queue) { | 69 | accept_queue) { |
76 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
77 | lock_sock(accept_sk); | 71 | lock_sock(accept_sk); |
@@ -83,24 +77,53 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
83 | release_sock(accept_sk); | 77 | release_sock(accept_sk); |
84 | 78 | ||
85 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
86 | |||
87 | lsk->local = NULL; | ||
88 | } | 80 | } |
89 | } | 81 | } |
90 | 82 | ||
91 | if (parent_sk->sk_state == LLCP_CONNECTED) | 83 | sk->sk_state = LLCP_CLOSED; |
92 | nfc_put_device(parent->dev); | ||
93 | |||
94 | parent_sk->sk_state = LLCP_CLOSED; | ||
95 | 84 | ||
96 | release_sock(parent_sk); | 85 | release_sock(sk); |
97 | 86 | ||
98 | sock_orphan(parent_sk); | 87 | sock_orphan(sk); |
99 | 88 | ||
100 | parent->local = NULL; | 89 | sk_del_node_init(sk); |
101 | } | 90 | } |
102 | 91 | ||
103 | mutex_unlock(&local->socket_lock); | 92 | write_unlock(&local->sockets.lock); |
93 | } | ||
94 | |||
95 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ||
96 | { | ||
97 | kref_get(&local->ref); | ||
98 | |||
99 | return local; | ||
100 | } | ||
101 | |||
102 | static void local_release(struct kref *ref) | ||
103 | { | ||
104 | struct nfc_llcp_local *local; | ||
105 | |||
106 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
107 | |||
108 | list_del(&local->list); | ||
109 | nfc_llcp_socket_release(local); | ||
110 | del_timer_sync(&local->link_timer); | ||
111 | skb_queue_purge(&local->tx_queue); | ||
112 | destroy_workqueue(local->tx_wq); | ||
113 | destroy_workqueue(local->rx_wq); | ||
114 | destroy_workqueue(local->timeout_wq); | ||
115 | kfree_skb(local->rx_pending); | ||
116 | kfree(local); | ||
117 | } | ||
118 | |||
119 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | ||
120 | { | ||
121 | WARN_ON(local == NULL); | ||
122 | |||
123 | if (local == NULL) | ||
124 | return 0; | ||
125 | |||
126 | return kref_put(&local->ref, local_release); | ||
104 | } | 127 | } |
105 | 128 | ||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 129 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) |
@@ -384,31 +407,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
384 | return -EINVAL; | 407 | return -EINVAL; |
385 | } | 408 | } |
386 | 409 | ||
387 | return nfc_llcp_parse_tlv(local, | 410 | return nfc_llcp_parse_gb_tlv(local, |
388 | &local->remote_gb[3], | 411 | &local->remote_gb[3], |
389 | local->remote_gb_len - 3); | 412 | local->remote_gb_len - 3); |
390 | } | ||
391 | |||
392 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
393 | { | ||
394 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
395 | tx_work); | ||
396 | struct sk_buff *skb; | ||
397 | |||
398 | skb = skb_dequeue(&local->tx_queue); | ||
399 | if (skb != NULL) { | ||
400 | pr_debug("Sending pending skb\n"); | ||
401 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET, | ||
402 | 16, 1, skb->data, skb->len, true); | ||
403 | |||
404 | nfc_data_exchange(local->dev, local->target_idx, | ||
405 | skb, nfc_llcp_recv, local); | ||
406 | } else { | ||
407 | nfc_llcp_send_symm(local->dev); | ||
408 | } | ||
409 | |||
410 | mod_timer(&local->link_timer, | ||
411 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
412 | } | 413 | } |
413 | 414 | ||
414 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | 415 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
@@ -443,46 +444,146 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
443 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 444 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
444 | } | 445 | } |
445 | 446 | ||
447 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
448 | { | ||
449 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
450 | tx_work); | ||
451 | struct sk_buff *skb; | ||
452 | struct sock *sk; | ||
453 | struct nfc_llcp_sock *llcp_sock; | ||
454 | |||
455 | skb = skb_dequeue(&local->tx_queue); | ||
456 | if (skb != NULL) { | ||
457 | sk = skb->sk; | ||
458 | llcp_sock = nfc_llcp_sock(sk); | ||
459 | if (llcp_sock != NULL) { | ||
460 | int ret; | ||
461 | |||
462 | pr_debug("Sending pending skb\n"); | ||
463 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", | ||
464 | DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb->len, true); | ||
466 | |||
467 | ret = nfc_data_exchange(local->dev, local->target_idx, | ||
468 | skb, nfc_llcp_recv, local); | ||
469 | |||
470 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
471 | skb = skb_get(skb); | ||
472 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
473 | skb); | ||
474 | } | ||
475 | } else { | ||
476 | nfc_llcp_send_symm(local->dev); | ||
477 | } | ||
478 | } else { | ||
479 | nfc_llcp_send_symm(local->dev); | ||
480 | } | ||
481 | |||
482 | mod_timer(&local->link_timer, | ||
483 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | ||
484 | } | ||
485 | |||
486 | static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, | ||
487 | u8 ssap) | ||
488 | { | ||
489 | struct sock *sk; | ||
490 | struct nfc_llcp_sock *llcp_sock; | ||
491 | struct hlist_node *node; | ||
492 | |||
493 | read_lock(&local->connecting_sockets.lock); | ||
494 | |||
495 | sk_for_each(sk, node, &local->connecting_sockets.head) { | ||
496 | llcp_sock = nfc_llcp_sock(sk); | ||
497 | |||
498 | if (llcp_sock->ssap == ssap) { | ||
499 | sock_hold(&llcp_sock->sk); | ||
500 | goto out; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | llcp_sock = NULL; | ||
505 | |||
506 | out: | ||
507 | read_unlock(&local->connecting_sockets.lock); | ||
508 | |||
509 | return llcp_sock; | ||
510 | } | ||
511 | |||
446 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 512 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
447 | u8 ssap, u8 dsap) | 513 | u8 ssap, u8 dsap) |
448 | { | 514 | { |
449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 515 | struct sock *sk; |
516 | struct hlist_node *node; | ||
517 | struct nfc_llcp_sock *llcp_sock; | ||
450 | 518 | ||
451 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 519 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
452 | 520 | ||
453 | if (ssap == 0 && dsap == 0) | 521 | if (ssap == 0 && dsap == 0) |
454 | return NULL; | 522 | return NULL; |
455 | 523 | ||
456 | mutex_lock(&local->socket_lock); | 524 | read_lock(&local->sockets.lock); |
457 | sock = local->sockets[ssap]; | ||
458 | if (sock == NULL) { | ||
459 | mutex_unlock(&local->socket_lock); | ||
460 | return NULL; | ||
461 | } | ||
462 | 525 | ||
463 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | 526 | llcp_sock = NULL; |
464 | 527 | ||
465 | if (sock->dsap == dsap) { | 528 | sk_for_each(sk, node, &local->sockets.head) { |
466 | sock_hold(&sock->sk); | 529 | llcp_sock = nfc_llcp_sock(sk); |
467 | mutex_unlock(&local->socket_lock); | 530 | |
468 | return sock; | 531 | if (llcp_sock->ssap == ssap && |
532 | llcp_sock->dsap == dsap) | ||
533 | break; | ||
469 | } | 534 | } |
470 | 535 | ||
471 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 536 | read_unlock(&local->sockets.lock); |
472 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 537 | |
473 | &llcp_sock->sk, llcp_sock->dsap); | 538 | if (llcp_sock == NULL) |
474 | if (llcp_sock->dsap == dsap) { | 539 | return NULL; |
475 | sock_hold(&llcp_sock->sk); | 540 | |
476 | mutex_unlock(&local->socket_lock); | 541 | sock_hold(&llcp_sock->sk); |
477 | return llcp_sock; | 542 | |
478 | } | 543 | return llcp_sock; |
544 | } | ||
545 | |||
546 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | ||
547 | u8 *sn, size_t sn_len) | ||
548 | { | ||
549 | struct sock *sk; | ||
550 | struct hlist_node *node; | ||
551 | struct nfc_llcp_sock *llcp_sock; | ||
552 | |||
553 | pr_debug("sn %zd\n", sn_len); | ||
554 | |||
555 | if (sn == NULL || sn_len == 0) | ||
556 | return NULL; | ||
557 | |||
558 | read_lock(&local->sockets.lock); | ||
559 | |||
560 | llcp_sock = NULL; | ||
561 | |||
562 | sk_for_each(sk, node, &local->sockets.head) { | ||
563 | llcp_sock = nfc_llcp_sock(sk); | ||
564 | |||
565 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
566 | continue; | ||
567 | |||
568 | if (llcp_sock->service_name == NULL || | ||
569 | llcp_sock->service_name_len == 0) | ||
570 | continue; | ||
571 | |||
572 | if (llcp_sock->service_name_len != sn_len) | ||
573 | continue; | ||
574 | |||
575 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
576 | break; | ||
479 | } | 577 | } |
480 | 578 | ||
481 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | 579 | read_unlock(&local->sockets.lock); |
482 | 580 | ||
483 | mutex_unlock(&local->socket_lock); | 581 | if (llcp_sock == NULL) |
582 | return NULL; | ||
484 | 583 | ||
485 | return NULL; | 584 | sock_hold(&llcp_sock->sk); |
585 | |||
586 | return llcp_sock; | ||
486 | } | 587 | } |
487 | 588 | ||
488 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | 589 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) |
@@ -518,35 +619,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
518 | { | 619 | { |
519 | struct sock *new_sk, *parent; | 620 | struct sock *new_sk, *parent; |
520 | struct nfc_llcp_sock *sock, *new_sock; | 621 | struct nfc_llcp_sock *sock, *new_sock; |
521 | u8 dsap, ssap, bound_sap, reason; | 622 | u8 dsap, ssap, reason; |
522 | 623 | ||
523 | dsap = nfc_llcp_dsap(skb); | 624 | dsap = nfc_llcp_dsap(skb); |
524 | ssap = nfc_llcp_ssap(skb); | 625 | ssap = nfc_llcp_ssap(skb); |
525 | 626 | ||
526 | pr_debug("%d %d\n", dsap, ssap); | 627 | pr_debug("%d %d\n", dsap, ssap); |
527 | 628 | ||
528 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
529 | skb->len - LLCP_HEADER_SIZE); | ||
530 | |||
531 | if (dsap != LLCP_SAP_SDP) { | 629 | if (dsap != LLCP_SAP_SDP) { |
532 | bound_sap = dsap; | 630 | sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); |
533 | 631 | if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { | |
534 | mutex_lock(&local->socket_lock); | ||
535 | sock = local->sockets[dsap]; | ||
536 | if (sock == NULL) { | ||
537 | mutex_unlock(&local->socket_lock); | ||
538 | reason = LLCP_DM_NOBOUND; | 632 | reason = LLCP_DM_NOBOUND; |
539 | goto fail; | 633 | goto fail; |
540 | } | 634 | } |
541 | |||
542 | sock_hold(&sock->sk); | ||
543 | mutex_unlock(&local->socket_lock); | ||
544 | |||
545 | lock_sock(&sock->sk); | ||
546 | |||
547 | if (sock->dsap == LLCP_SAP_SDP && | ||
548 | sock->sk.sk_state == LLCP_LISTEN) | ||
549 | goto enqueue; | ||
550 | } else { | 635 | } else { |
551 | u8 *sn; | 636 | u8 *sn; |
552 | size_t sn_len; | 637 | size_t sn_len; |
@@ -559,40 +644,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
559 | 644 | ||
560 | pr_debug("Service name length %zu\n", sn_len); | 645 | pr_debug("Service name length %zu\n", sn_len); |
561 | 646 | ||
562 | mutex_lock(&local->socket_lock); | 647 | sock = nfc_llcp_sock_get_sn(local, sn, sn_len); |
563 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 648 | if (sock == NULL) { |
564 | bound_sap++) { | 649 | reason = LLCP_DM_NOBOUND; |
565 | sock = local->sockets[bound_sap]; | 650 | goto fail; |
566 | if (sock == NULL) | ||
567 | continue; | ||
568 | |||
569 | if (sock->service_name == NULL || | ||
570 | sock->service_name_len == 0) | ||
571 | continue; | ||
572 | |||
573 | if (sock->service_name_len != sn_len) | ||
574 | continue; | ||
575 | |||
576 | if (sock->dsap == LLCP_SAP_SDP && | ||
577 | sock->sk.sk_state == LLCP_LISTEN && | ||
578 | !memcmp(sn, sock->service_name, sn_len)) { | ||
579 | pr_debug("Found service name at SAP %d\n", | ||
580 | bound_sap); | ||
581 | sock_hold(&sock->sk); | ||
582 | mutex_unlock(&local->socket_lock); | ||
583 | |||
584 | lock_sock(&sock->sk); | ||
585 | |||
586 | goto enqueue; | ||
587 | } | ||
588 | } | 651 | } |
589 | mutex_unlock(&local->socket_lock); | ||
590 | } | 652 | } |
591 | 653 | ||
592 | reason = LLCP_DM_NOBOUND; | 654 | lock_sock(&sock->sk); |
593 | goto fail; | ||
594 | 655 | ||
595 | enqueue: | ||
596 | parent = &sock->sk; | 656 | parent = &sock->sk; |
597 | 657 | ||
598 | if (sk_acceptq_is_full(parent)) { | 658 | if (sk_acceptq_is_full(parent)) { |
@@ -612,15 +672,19 @@ enqueue: | |||
612 | 672 | ||
613 | new_sock = nfc_llcp_sock(new_sk); | 673 | new_sock = nfc_llcp_sock(new_sk); |
614 | new_sock->dev = local->dev; | 674 | new_sock->dev = local->dev; |
615 | new_sock->local = local; | 675 | new_sock->local = nfc_llcp_local_get(local); |
676 | new_sock->miu = local->remote_miu; | ||
616 | new_sock->nfc_protocol = sock->nfc_protocol; | 677 | new_sock->nfc_protocol = sock->nfc_protocol; |
617 | new_sock->ssap = bound_sap; | 678 | new_sock->ssap = sock->ssap; |
618 | new_sock->dsap = ssap; | 679 | new_sock->dsap = ssap; |
619 | new_sock->parent = parent; | 680 | new_sock->parent = parent; |
620 | 681 | ||
682 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], | ||
683 | skb->len - LLCP_HEADER_SIZE); | ||
684 | |||
621 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | 685 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); |
622 | 686 | ||
623 | list_add_tail(&new_sock->list, &sock->list); | 687 | nfc_llcp_sock_link(&local->sockets, new_sk); |
624 | 688 | ||
625 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | 689 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); |
626 | 690 | ||
@@ -654,12 +718,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
654 | 718 | ||
655 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 719 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
656 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 720 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
657 | local->remote_rw); | 721 | sock->rw); |
658 | 722 | ||
659 | /* Try to queue some I frames for transmission */ | 723 | /* Try to queue some I frames for transmission */ |
660 | while (sock->remote_ready && | 724 | while (sock->remote_ready && |
661 | skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { | 725 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { |
662 | struct sk_buff *pdu, *pending_pdu; | 726 | struct sk_buff *pdu; |
663 | 727 | ||
664 | pdu = skb_dequeue(&sock->tx_queue); | 728 | pdu = skb_dequeue(&sock->tx_queue); |
665 | if (pdu == NULL) | 729 | if (pdu == NULL) |
@@ -668,10 +732,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
668 | /* Update N(S)/N(R) */ | 732 | /* Update N(S)/N(R) */ |
669 | nfc_llcp_set_nrns(sock, pdu); | 733 | nfc_llcp_set_nrns(sock, pdu); |
670 | 734 | ||
671 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
672 | |||
673 | skb_queue_tail(&local->tx_queue, pdu); | 735 | skb_queue_tail(&local->tx_queue, pdu); |
674 | skb_queue_tail(&sock->tx_pending_queue, pending_pdu); | ||
675 | nr_frames++; | 736 | nr_frames++; |
676 | } | 737 | } |
677 | 738 | ||
@@ -728,11 +789,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
728 | 789 | ||
729 | llcp_sock->send_ack_n = nr; | 790 | llcp_sock->send_ack_n = nr; |
730 | 791 | ||
731 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) | 792 | /* Remove and free all skbs until ns == nr */ |
732 | if (nfc_llcp_ns(s) <= nr) { | 793 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { |
733 | skb_unlink(s, &llcp_sock->tx_pending_queue); | 794 | skb_unlink(s, &llcp_sock->tx_pending_queue); |
734 | kfree_skb(s); | 795 | kfree_skb(s); |
735 | } | 796 | |
797 | if (nfc_llcp_ns(s) == nr) | ||
798 | break; | ||
799 | } | ||
800 | |||
801 | /* Re-queue the remaining skbs for transmission */ | ||
802 | skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue, | ||
803 | s, tmp) { | ||
804 | skb_unlink(s, &llcp_sock->tx_pending_queue); | ||
805 | skb_queue_head(&local->tx_queue, s); | ||
806 | } | ||
736 | } | 807 | } |
737 | 808 | ||
738 | if (ptype == LLCP_PDU_RR) | 809 | if (ptype == LLCP_PDU_RR) |
@@ -740,7 +811,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
740 | else if (ptype == LLCP_PDU_RNR) | 811 | else if (ptype == LLCP_PDU_RNR) |
741 | llcp_sock->remote_ready = false; | 812 | llcp_sock->remote_ready = false; |
742 | 813 | ||
743 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0) | 814 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I) |
744 | nfc_llcp_send_rr(llcp_sock); | 815 | nfc_llcp_send_rr(llcp_sock); |
745 | 816 | ||
746 | release_sock(sk); | 817 | release_sock(sk); |
@@ -791,11 +862,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
791 | dsap = nfc_llcp_dsap(skb); | 862 | dsap = nfc_llcp_dsap(skb); |
792 | ssap = nfc_llcp_ssap(skb); | 863 | ssap = nfc_llcp_ssap(skb); |
793 | 864 | ||
794 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | 865 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); |
795 | |||
796 | if (llcp_sock == NULL) | ||
797 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
798 | |||
799 | if (llcp_sock == NULL) { | 866 | if (llcp_sock == NULL) { |
800 | pr_err("Invalid CC\n"); | 867 | pr_err("Invalid CC\n"); |
801 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | 868 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); |
@@ -803,11 +870,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
803 | return; | 870 | return; |
804 | } | 871 | } |
805 | 872 | ||
806 | llcp_sock->dsap = ssap; | ||
807 | sk = &llcp_sock->sk; | 873 | sk = &llcp_sock->sk; |
808 | 874 | ||
809 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 875 | /* Unlink from connecting and link to the client array */ |
810 | skb->len - LLCP_HEADER_SIZE); | 876 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
877 | nfc_llcp_sock_link(&local->sockets, sk); | ||
878 | llcp_sock->dsap = ssap; | ||
879 | |||
880 | nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE], | ||
881 | skb->len - LLCP_HEADER_SIZE); | ||
811 | 882 | ||
812 | sk->sk_state = LLCP_CONNECTED; | 883 | sk->sk_state = LLCP_CONNECTED; |
813 | sk->sk_state_change(sk); | 884 | sk->sk_state_change(sk); |
@@ -891,6 +962,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
891 | return; | 962 | return; |
892 | } | 963 | } |
893 | 964 | ||
965 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
966 | { | ||
967 | struct nfc_llcp_local *local; | ||
968 | |||
969 | local = nfc_llcp_find_local(dev); | ||
970 | if (local == NULL) | ||
971 | return -ENODEV; | ||
972 | |||
973 | local->rx_pending = skb_get(skb); | ||
974 | del_timer(&local->link_timer); | ||
975 | queue_work(local->rx_wq, &local->rx_work); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
894 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | 980 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) |
895 | { | 981 | { |
896 | struct nfc_llcp_local *local; | 982 | struct nfc_llcp_local *local; |
@@ -943,8 +1029,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
943 | 1029 | ||
944 | local->dev = ndev; | 1030 | local->dev = ndev; |
945 | INIT_LIST_HEAD(&local->list); | 1031 | INIT_LIST_HEAD(&local->list); |
1032 | kref_init(&local->ref); | ||
946 | mutex_init(&local->sdp_lock); | 1033 | mutex_init(&local->sdp_lock); |
947 | mutex_init(&local->socket_lock); | ||
948 | init_timer(&local->link_timer); | 1034 | init_timer(&local->link_timer); |
949 | local->link_timer.data = (unsigned long) local; | 1035 | local->link_timer.data = (unsigned long) local; |
950 | local->link_timer.function = nfc_llcp_symm_timer; | 1036 | local->link_timer.function = nfc_llcp_symm_timer; |
@@ -984,11 +1070,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
984 | goto err_rx_wq; | 1070 | goto err_rx_wq; |
985 | } | 1071 | } |
986 | 1072 | ||
1073 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | ||
1074 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | ||
1075 | |||
987 | nfc_llcp_build_gb(local); | 1076 | nfc_llcp_build_gb(local); |
988 | 1077 | ||
989 | local->remote_miu = LLCP_DEFAULT_MIU; | 1078 | local->remote_miu = LLCP_DEFAULT_MIU; |
990 | local->remote_lto = LLCP_DEFAULT_LTO; | 1079 | local->remote_lto = LLCP_DEFAULT_LTO; |
991 | local->remote_rw = LLCP_DEFAULT_RW; | ||
992 | 1080 | ||
993 | list_add(&llcp_devices, &local->list); | 1081 | list_add(&llcp_devices, &local->list); |
994 | 1082 | ||
@@ -1015,14 +1103,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1015 | return; | 1103 | return; |
1016 | } | 1104 | } |
1017 | 1105 | ||
1018 | list_del(&local->list); | 1106 | nfc_llcp_local_put(local); |
1019 | nfc_llcp_socket_release(local); | ||
1020 | del_timer_sync(&local->link_timer); | ||
1021 | skb_queue_purge(&local->tx_queue); | ||
1022 | destroy_workqueue(local->tx_wq); | ||
1023 | destroy_workqueue(local->rx_wq); | ||
1024 | kfree_skb(local->rx_pending); | ||
1025 | kfree(local); | ||
1026 | } | 1107 | } |
1027 | 1108 | ||
1028 | int __init nfc_llcp_init(void) | 1109 | int __init nfc_llcp_init(void) |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 50680ce5ae43..7286c86982ff 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -40,12 +40,18 @@ enum llcp_state { | |||
40 | 40 | ||
41 | struct nfc_llcp_sock; | 41 | struct nfc_llcp_sock; |
42 | 42 | ||
43 | struct llcp_sock_list { | ||
44 | struct hlist_head head; | ||
45 | rwlock_t lock; | ||
46 | }; | ||
47 | |||
43 | struct nfc_llcp_local { | 48 | struct nfc_llcp_local { |
44 | struct list_head list; | 49 | struct list_head list; |
45 | struct nfc_dev *dev; | 50 | struct nfc_dev *dev; |
46 | 51 | ||
52 | struct kref ref; | ||
53 | |||
47 | struct mutex sdp_lock; | 54 | struct mutex sdp_lock; |
48 | struct mutex socket_lock; | ||
49 | 55 | ||
50 | struct timer_list link_timer; | 56 | struct timer_list link_timer; |
51 | struct sk_buff_head tx_queue; | 57 | struct sk_buff_head tx_queue; |
@@ -77,24 +83,26 @@ struct nfc_llcp_local { | |||
77 | u16 remote_lto; | 83 | u16 remote_lto; |
78 | u8 remote_opt; | 84 | u8 remote_opt; |
79 | u16 remote_wks; | 85 | u16 remote_wks; |
80 | u8 remote_rw; | ||
81 | 86 | ||
82 | /* sockets array */ | 87 | /* sockets array */ |
83 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | 88 | struct llcp_sock_list sockets; |
89 | struct llcp_sock_list connecting_sockets; | ||
84 | }; | 90 | }; |
85 | 91 | ||
86 | struct nfc_llcp_sock { | 92 | struct nfc_llcp_sock { |
87 | struct sock sk; | 93 | struct sock sk; |
88 | struct list_head list; | ||
89 | struct nfc_dev *dev; | 94 | struct nfc_dev *dev; |
90 | struct nfc_llcp_local *local; | 95 | struct nfc_llcp_local *local; |
91 | u32 target_idx; | 96 | u32 target_idx; |
92 | u32 nfc_protocol; | 97 | u32 nfc_protocol; |
93 | 98 | ||
99 | /* Link parameters */ | ||
94 | u8 ssap; | 100 | u8 ssap; |
95 | u8 dsap; | 101 | u8 dsap; |
96 | char *service_name; | 102 | char *service_name; |
97 | size_t service_name_len; | 103 | size_t service_name_len; |
104 | u8 rw; | ||
105 | u16 miu; | ||
98 | 106 | ||
99 | /* Link variables */ | 107 | /* Link variables */ |
100 | u8 send_n; | 108 | u8 send_n; |
@@ -164,7 +172,11 @@ struct nfc_llcp_sock { | |||
164 | #define LLCP_DM_REJ 0x03 | 172 | #define LLCP_DM_REJ 0x03 |
165 | 173 | ||
166 | 174 | ||
175 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); | ||
176 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); | ||
167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 177 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
178 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | ||
179 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | ||
168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 180 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
169 | struct nfc_llcp_sock *sock); | 181 | struct nfc_llcp_sock *sock); |
170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 182 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); |
@@ -179,8 +191,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); | |||
179 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | 191 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); |
180 | 192 | ||
181 | /* TLV API */ | 193 | /* TLV API */ |
182 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 194 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
183 | u8 *tlv_array, u16 tlv_array_len); | 195 | u8 *tlv_array, u16 tlv_array_len); |
196 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
197 | u8 *tlv_array, u16 tlv_array_len); | ||
184 | 198 | ||
185 | /* Commands API */ | 199 | /* Commands API */ |
186 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 200 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 3f339b19d140..30e3cc71be7a 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | llcp_sock->dev = dev; | 113 | llcp_sock->dev = dev; |
114 | llcp_sock->local = local; | 114 | llcp_sock->local = nfc_llcp_local_get(local); |
115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | 115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
116 | llcp_sock->service_name_len = min_t(unsigned int, | 116 | llcp_sock->service_name_len = min_t(unsigned int, |
117 | llcp_addr.service_name_len, | 117 | llcp_addr.service_name_len, |
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
125 | goto put_dev; | 125 | goto put_dev; |
126 | 126 | ||
127 | local->sockets[llcp_sock->ssap] = llcp_sock; | 127 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 128 | ||
129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | 129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); |
130 | 130 | ||
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock) | |||
379 | goto out; | 379 | goto out; |
380 | } | 380 | } |
381 | 381 | ||
382 | mutex_lock(&local->socket_lock); | ||
383 | |||
384 | if (llcp_sock == local->sockets[llcp_sock->ssap]) | ||
385 | local->sockets[llcp_sock->ssap] = NULL; | ||
386 | else | ||
387 | list_del_init(&llcp_sock->list); | ||
388 | |||
389 | mutex_unlock(&local->socket_lock); | ||
390 | |||
391 | lock_sock(sk); | 382 | lock_sock(sk); |
392 | 383 | ||
393 | /* Send a DISC */ | 384 | /* Send a DISC */ |
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock) | |||
412 | } | 403 | } |
413 | } | 404 | } |
414 | 405 | ||
415 | /* Freeing the SAP */ | 406 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
416 | if ((sk->sk_state == LLCP_CONNECTED | ||
417 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
418 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) | ||
419 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
420 | 407 | ||
421 | release_sock(sk); | 408 | release_sock(sk); |
422 | 409 | ||
410 | nfc_llcp_sock_unlink(&local->sockets, sk); | ||
411 | |||
423 | out: | 412 | out: |
424 | sock_orphan(sk); | 413 | sock_orphan(sk); |
425 | sock_put(sk); | 414 | sock_put(sk); |
@@ -487,7 +476,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
487 | } | 476 | } |
488 | 477 | ||
489 | llcp_sock->dev = dev; | 478 | llcp_sock->dev = dev; |
490 | llcp_sock->local = local; | 479 | llcp_sock->local = nfc_llcp_local_get(local); |
480 | llcp_sock->miu = llcp_sock->local->remote_miu; | ||
491 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 481 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
492 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 482 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
493 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
@@ -505,21 +495,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
505 | llcp_sock->service_name_len, | 495 | llcp_sock->service_name_len, |
506 | GFP_KERNEL); | 496 | GFP_KERNEL); |
507 | 497 | ||
508 | local->sockets[llcp_sock->ssap] = llcp_sock; | 498 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
509 | 499 | ||
510 | ret = nfc_llcp_send_connect(llcp_sock); | 500 | ret = nfc_llcp_send_connect(llcp_sock); |
511 | if (ret) | 501 | if (ret) |
512 | goto put_dev; | 502 | goto sock_unlink; |
513 | 503 | ||
514 | ret = sock_wait_state(sk, LLCP_CONNECTED, | 504 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 505 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
516 | if (ret) | 506 | if (ret) |
517 | goto put_dev; | 507 | goto sock_unlink; |
518 | 508 | ||
519 | release_sock(sk); | 509 | release_sock(sk); |
520 | 510 | ||
521 | return 0; | 511 | return 0; |
522 | 512 | ||
513 | sock_unlink: | ||
514 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
515 | |||
516 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
517 | |||
523 | put_dev: | 518 | put_dev: |
524 | nfc_put_device(dev); | 519 | nfc_put_device(dev); |
525 | 520 | ||
@@ -684,13 +679,14 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
684 | 679 | ||
685 | llcp_sock->ssap = 0; | 680 | llcp_sock->ssap = 0; |
686 | llcp_sock->dsap = LLCP_SAP_SDP; | 681 | llcp_sock->dsap = LLCP_SAP_SDP; |
682 | llcp_sock->rw = LLCP_DEFAULT_RW; | ||
683 | llcp_sock->miu = LLCP_DEFAULT_MIU; | ||
687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 684 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 685 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
689 | llcp_sock->remote_ready = 1; | 686 | llcp_sock->remote_ready = 1; |
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 687 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 688 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 689 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
693 | INIT_LIST_HEAD(&llcp_sock->list); | ||
694 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 690 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
695 | 691 | ||
696 | if (sock != NULL) | 692 | if (sock != NULL) |
@@ -701,8 +697,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
701 | 697 | ||
702 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 698 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) |
703 | { | 699 | { |
704 | struct nfc_llcp_local *local = sock->local; | ||
705 | |||
706 | kfree(sock->service_name); | 700 | kfree(sock->service_name); |
707 | 701 | ||
708 | skb_queue_purge(&sock->tx_queue); | 702 | skb_queue_purge(&sock->tx_queue); |
@@ -711,12 +705,9 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
711 | 705 | ||
712 | list_del_init(&sock->accept_queue); | 706 | list_del_init(&sock->accept_queue); |
713 | 707 | ||
714 | if (local != NULL && sock == local->sockets[sock->ssap]) | ||
715 | local->sockets[sock->ssap] = NULL; | ||
716 | else | ||
717 | list_del_init(&sock->list); | ||
718 | |||
719 | sock->parent = NULL; | 708 | sock->parent = NULL; |
709 | |||
710 | nfc_llcp_local_put(sock->local); | ||
720 | } | 711 | } |
721 | 712 | ||
722 | static int llcp_sock_create(struct net *net, struct socket *sock, | 713 | static int llcp_sock_create(struct net *net, struct socket *sock, |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index d560e6f13072..766a02b1dfa1 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) | |||
387 | return nci_close_device(ndev); | 387 | return nci_close_device(ndev); |
388 | } | 388 | } |
389 | 389 | ||
390 | static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | 390 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
391 | __u32 im_protocols, __u32 tm_protocols) | ||
391 | { | 392 | { |
392 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 393 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
393 | int rc; | 394 | int rc; |
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
413 | return -EBUSY; | 414 | return -EBUSY; |
414 | } | 415 | } |
415 | 416 | ||
416 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | 417 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, |
417 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 418 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
418 | 419 | ||
419 | if (!rc) | 420 | if (!rc) |
420 | ndev->poll_prots = protocols; | 421 | ndev->poll_prots = im_protocols; |
421 | 422 | ||
422 | return rc; | 423 | return rc; |
423 | } | 424 | } |
@@ -521,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
521 | } | 522 | } |
522 | } | 523 | } |
523 | 524 | ||
524 | static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 525 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
525 | struct sk_buff *skb, | 526 | struct sk_buff *skb, |
526 | data_exchange_cb_t cb, void *cb_context) | 527 | data_exchange_cb_t cb, void *cb_context) |
527 | { | 528 | { |
528 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 529 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
529 | int rc; | 530 | int rc; |
@@ -556,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
556 | .stop_poll = nci_stop_poll, | 557 | .stop_poll = nci_stop_poll, |
557 | .activate_target = nci_activate_target, | 558 | .activate_target = nci_activate_target, |
558 | .deactivate_target = nci_deactivate_target, | 559 | .deactivate_target = nci_deactivate_target, |
559 | .data_exchange = nci_data_exchange, | 560 | .im_transceive = nci_transceive, |
560 | }; | 561 | }; |
561 | 562 | ||
562 | /* ---- Interface to NCI drivers ---- */ | 563 | /* ---- Interface to NCI drivers ---- */ |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 581d419083aa..03c31db38f12 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | 49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, |
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | 50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, |
51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
52 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | ||
53 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 56 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -219,6 +221,68 @@ free_msg: | |||
219 | return -EMSGSIZE; | 221 | return -EMSGSIZE; |
220 | } | 222 | } |
221 | 223 | ||
224 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) | ||
225 | { | ||
226 | struct sk_buff *msg; | ||
227 | void *hdr; | ||
228 | |||
229 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
230 | if (!msg) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
234 | NFC_EVENT_TM_ACTIVATED); | ||
235 | if (!hdr) | ||
236 | goto free_msg; | ||
237 | |||
238 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
239 | goto nla_put_failure; | ||
240 | if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) | ||
241 | goto nla_put_failure; | ||
242 | |||
243 | genlmsg_end(msg, hdr); | ||
244 | |||
245 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | nla_put_failure: | ||
250 | genlmsg_cancel(msg, hdr); | ||
251 | free_msg: | ||
252 | nlmsg_free(msg); | ||
253 | return -EMSGSIZE; | ||
254 | } | ||
255 | |||
256 | int nfc_genl_tm_deactivated(struct nfc_dev *dev) | ||
257 | { | ||
258 | struct sk_buff *msg; | ||
259 | void *hdr; | ||
260 | |||
261 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
262 | if (!msg) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
266 | NFC_EVENT_TM_DEACTIVATED); | ||
267 | if (!hdr) | ||
268 | goto free_msg; | ||
269 | |||
270 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
271 | goto nla_put_failure; | ||
272 | |||
273 | genlmsg_end(msg, hdr); | ||
274 | |||
275 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | nla_put_failure: | ||
280 | genlmsg_cancel(msg, hdr); | ||
281 | free_msg: | ||
282 | nlmsg_free(msg); | ||
283 | return -EMSGSIZE; | ||
284 | } | ||
285 | |||
222 | int nfc_genl_device_added(struct nfc_dev *dev) | 286 | int nfc_genl_device_added(struct nfc_dev *dev) |
223 | { | 287 | { |
224 | struct sk_buff *msg; | 288 | struct sk_buff *msg; |
@@ -519,16 +583,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
519 | struct nfc_dev *dev; | 583 | struct nfc_dev *dev; |
520 | int rc; | 584 | int rc; |
521 | u32 idx; | 585 | u32 idx; |
522 | u32 protocols; | 586 | u32 im_protocols = 0, tm_protocols = 0; |
523 | 587 | ||
524 | pr_debug("Poll start\n"); | 588 | pr_debug("Poll start\n"); |
525 | 589 | ||
526 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 590 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
527 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 591 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && |
592 | !info->attrs[NFC_ATTR_PROTOCOLS]) && | ||
593 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) | ||
528 | return -EINVAL; | 594 | return -EINVAL; |
529 | 595 | ||
530 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 596 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
531 | protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | 597 | |
598 | if (info->attrs[NFC_ATTR_TM_PROTOCOLS]) | ||
599 | tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]); | ||
600 | |||
601 | if (info->attrs[NFC_ATTR_IM_PROTOCOLS]) | ||
602 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]); | ||
603 | else if (info->attrs[NFC_ATTR_PROTOCOLS]) | ||
604 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | ||
532 | 605 | ||
533 | dev = nfc_get_device(idx); | 606 | dev = nfc_get_device(idx); |
534 | if (!dev) | 607 | if (!dev) |
@@ -536,7 +609,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
536 | 609 | ||
537 | mutex_lock(&dev->genl_data.genl_data_mutex); | 610 | mutex_lock(&dev->genl_data.genl_data_mutex); |
538 | 611 | ||
539 | rc = nfc_start_poll(dev, protocols); | 612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); |
540 | if (!rc) | 613 | if (!rc) |
541 | dev->genl_data.poll_req_pid = info->snd_pid; | 614 | dev->genl_data.poll_req_pid = info->snd_pid; |
542 | 615 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 3dd4232ae664..c5e42b79a418 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev); | |||
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | 55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); |
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | ||
58 | int __init nfc_llcp_init(void); | 59 | int __init nfc_llcp_init(void); |
59 | void nfc_llcp_exit(void); | 60 | void nfc_llcp_exit(void); |
60 | 61 | ||
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len) | |||
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
92 | 93 | ||
94 | static inline int nfc_llcp_data_received(struct nfc_dev *dev, | ||
95 | struct sk_buff *skb) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
93 | static inline int nfc_llcp_init(void) | 100 | static inline int nfc_llcp_init(void) |
94 | { | 101 | { |
95 | return 0; | 102 | return 0; |
@@ -128,6 +135,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | |||
128 | u8 comm_mode, u8 rf_mode); | 135 | u8 comm_mode, u8 rf_mode); |
129 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | 136 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); |
130 | 137 | ||
138 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | ||
139 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | ||
140 | |||
131 | struct nfc_dev *nfc_get_device(unsigned int idx); | 141 | struct nfc_dev *nfc_get_device(unsigned int idx); |
132 | 142 | ||
133 | static inline void nfc_put_device(struct nfc_dev *dev) | 143 | static inline void nfc_put_device(struct nfc_dev *dev) |
@@ -158,7 +168,7 @@ int nfc_dev_up(struct nfc_dev *dev); | |||
158 | 168 | ||
159 | int nfc_dev_down(struct nfc_dev *dev); | 169 | int nfc_dev_down(struct nfc_dev *dev); |
160 | 170 | ||
161 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 171 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols); |
162 | 172 | ||
163 | int nfc_stop_poll(struct nfc_dev *dev); | 173 | int nfc_stop_poll(struct nfc_dev *dev); |
164 | 174 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index f974961754ca..752b72360ebc 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -325,7 +325,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked) | |||
325 | 325 | ||
326 | rfkill_global_states[type].cur = blocked; | 326 | rfkill_global_states[type].cur = blocked; |
327 | list_for_each_entry(rfkill, &rfkill_list, node) { | 327 | list_for_each_entry(rfkill, &rfkill_list, node) { |
328 | if (rfkill->type != type) | 328 | if (rfkill->type != type && type != RFKILL_TYPE_ALL) |
329 | continue; | 329 | continue; |
330 | 330 | ||
331 | rfkill_set_block(rfkill, blocked); | 331 | rfkill_set_block(rfkill, blocked); |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 2e4444fedbe0..4d2b1ec6516f 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -114,24 +114,10 @@ config CFG80211_WEXT | |||
114 | bool "cfg80211 wireless extensions compatibility" | 114 | bool "cfg80211 wireless extensions compatibility" |
115 | depends on CFG80211 | 115 | depends on CFG80211 |
116 | select WEXT_CORE | 116 | select WEXT_CORE |
117 | default y | ||
118 | help | 117 | help |
119 | Enable this option if you need old userspace for wireless | 118 | Enable this option if you need old userspace for wireless |
120 | extensions with cfg80211-based drivers. | 119 | extensions with cfg80211-based drivers. |
121 | 120 | ||
122 | config WIRELESS_EXT_SYSFS | ||
123 | bool "Wireless extensions sysfs files" | ||
124 | depends on WEXT_CORE && SYSFS | ||
125 | help | ||
126 | This option enables the deprecated wireless statistics | ||
127 | files in /sys/class/net/*/wireless/. The same information | ||
128 | is available via the ioctls as well. | ||
129 | |||
130 | Say N. If you know you have ancient tools requiring it, | ||
131 | like very old versions of hal (prior to 0.5.12 release), | ||
132 | say Y and update the tools as soon as possible as this | ||
133 | option will be removed soon. | ||
134 | |||
135 | config LIB80211 | 121 | config LIB80211 |
136 | tristate "Common routines for IEEE802.11 drivers" | 122 | tristate "Common routines for IEEE802.11 drivers" |
137 | default n | 123 | default n |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 884801ac4dd0..c1999e45a07c 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -60,7 +60,7 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | |||
60 | diff = -20; | 60 | diff = -20; |
61 | break; | 61 | break; |
62 | default: | 62 | default: |
63 | return false; | 63 | return true; |
64 | } | 64 | } |
65 | 65 | ||
66 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); | 66 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); |
@@ -78,60 +78,17 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | |||
78 | } | 78 | } |
79 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); | 79 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); |
80 | 80 | ||
81 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 81 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
82 | struct wireless_dev *wdev, int freq, | 82 | int freq, enum nl80211_channel_type chantype) |
83 | enum nl80211_channel_type channel_type) | ||
84 | { | 83 | { |
85 | struct ieee80211_channel *chan; | 84 | struct ieee80211_channel *chan; |
86 | int result; | ||
87 | |||
88 | if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
89 | wdev = NULL; | ||
90 | |||
91 | if (wdev) { | ||
92 | ASSERT_WDEV_LOCK(wdev); | ||
93 | |||
94 | if (!netif_running(wdev->netdev)) | ||
95 | return -ENETDOWN; | ||
96 | } | ||
97 | 85 | ||
98 | if (!rdev->ops->set_channel) | 86 | if (!rdev->ops->set_monitor_channel) |
99 | return -EOPNOTSUPP; | 87 | return -EOPNOTSUPP; |
100 | 88 | ||
101 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 89 | chan = rdev_freq_to_chan(rdev, freq, chantype); |
102 | if (!chan) | 90 | if (!chan) |
103 | return -EINVAL; | 91 | return -EINVAL; |
104 | 92 | ||
105 | /* Both channels should be able to initiate communication */ | 93 | return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); |
106 | if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC || | ||
107 | wdev->iftype == NL80211_IFTYPE_AP || | ||
108 | wdev->iftype == NL80211_IFTYPE_AP_VLAN || | ||
109 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | ||
110 | wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
111 | switch (channel_type) { | ||
112 | case NL80211_CHAN_HT40PLUS: | ||
113 | case NL80211_CHAN_HT40MINUS: | ||
114 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan, | ||
115 | channel_type)) { | ||
116 | printk(KERN_DEBUG | ||
117 | "cfg80211: Secondary channel not " | ||
118 | "allowed to initiate communication\n"); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | break; | ||
122 | default: | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | result = rdev->ops->set_channel(&rdev->wiphy, | ||
128 | wdev ? wdev->netdev : NULL, | ||
129 | chan, channel_type); | ||
130 | if (result) | ||
131 | return result; | ||
132 | |||
133 | if (wdev) | ||
134 | wdev->channel = chan; | ||
135 | |||
136 | return 0; | ||
137 | } | 94 | } |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 8523f3878677..9348a47562a4 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -303,14 +303,17 @@ extern const struct mesh_config default_mesh_config; | |||
303 | extern const struct mesh_setup default_mesh_setup; | 303 | extern const struct mesh_setup default_mesh_setup; |
304 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 304 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
305 | struct net_device *dev, | 305 | struct net_device *dev, |
306 | const struct mesh_setup *setup, | 306 | struct mesh_setup *setup, |
307 | const struct mesh_config *conf); | 307 | const struct mesh_config *conf); |
308 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 308 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
309 | struct net_device *dev, | 309 | struct net_device *dev, |
310 | const struct mesh_setup *setup, | 310 | struct mesh_setup *setup, |
311 | const struct mesh_config *conf); | 311 | const struct mesh_config *conf); |
312 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 312 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
313 | struct net_device *dev); | 313 | struct net_device *dev); |
314 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | ||
315 | struct wireless_dev *wdev, int freq, | ||
316 | enum nl80211_channel_type channel_type); | ||
314 | 317 | ||
315 | /* MLME */ | 318 | /* MLME */ |
316 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 319 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
@@ -441,9 +444,8 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, | |||
441 | struct ieee80211_channel * | 444 | struct ieee80211_channel * |
442 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 445 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
443 | int freq, enum nl80211_channel_type channel_type); | 446 | int freq, enum nl80211_channel_type channel_type); |
444 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 447 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
445 | struct wireless_dev *wdev, int freq, | 448 | int freq, enum nl80211_channel_type chantype); |
446 | enum nl80211_channel_type channel_type); | ||
447 | 449 | ||
448 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 450 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |
449 | const u8 *rates, unsigned int n_rates, | 451 | const u8 *rates, unsigned int n_rates, |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 2749cb86b462..b44c736bf9cf 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -65,6 +65,9 @@ const struct mesh_config default_mesh_config = { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | const struct mesh_setup default_mesh_setup = { | 67 | const struct mesh_setup default_mesh_setup = { |
68 | /* cfg80211_join_mesh() will pick a channel if needed */ | ||
69 | .channel = NULL, | ||
70 | .channel_type = NL80211_CHAN_NO_HT, | ||
68 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | 71 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, |
69 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 72 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
70 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 73 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
@@ -75,7 +78,7 @@ const struct mesh_setup default_mesh_setup = { | |||
75 | 78 | ||
76 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 79 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
77 | struct net_device *dev, | 80 | struct net_device *dev, |
78 | const struct mesh_setup *setup, | 81 | struct mesh_setup *setup, |
79 | const struct mesh_config *conf) | 82 | const struct mesh_config *conf) |
80 | { | 83 | { |
81 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 84 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -101,6 +104,51 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
101 | if (!rdev->ops->join_mesh) | 104 | if (!rdev->ops->join_mesh) |
102 | return -EOPNOTSUPP; | 105 | return -EOPNOTSUPP; |
103 | 106 | ||
107 | if (!setup->channel) { | ||
108 | /* if no channel explicitly given, use preset channel */ | ||
109 | setup->channel = wdev->preset_chan; | ||
110 | setup->channel_type = wdev->preset_chantype; | ||
111 | } | ||
112 | |||
113 | if (!setup->channel) { | ||
114 | /* if we don't have that either, use the first usable channel */ | ||
115 | enum ieee80211_band band; | ||
116 | |||
117 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
118 | struct ieee80211_supported_band *sband; | ||
119 | struct ieee80211_channel *chan; | ||
120 | int i; | ||
121 | |||
122 | sband = rdev->wiphy.bands[band]; | ||
123 | if (!sband) | ||
124 | continue; | ||
125 | |||
126 | for (i = 0; i < sband->n_channels; i++) { | ||
127 | chan = &sband->channels[i]; | ||
128 | if (chan->flags & (IEEE80211_CHAN_NO_IBSS | | ||
129 | IEEE80211_CHAN_PASSIVE_SCAN | | ||
130 | IEEE80211_CHAN_DISABLED | | ||
131 | IEEE80211_CHAN_RADAR)) | ||
132 | continue; | ||
133 | setup->channel = chan; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | if (setup->channel) | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | /* no usable channel ... */ | ||
142 | if (!setup->channel) | ||
143 | return -EINVAL; | ||
144 | |||
145 | setup->channel_type = NL80211_CHAN_NO_HT; | ||
146 | } | ||
147 | |||
148 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel, | ||
149 | setup->channel_type)) | ||
150 | return -EINVAL; | ||
151 | |||
104 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); | 152 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); |
105 | if (!err) { | 153 | if (!err) { |
106 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 154 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
@@ -112,7 +160,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
112 | 160 | ||
113 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 161 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
114 | struct net_device *dev, | 162 | struct net_device *dev, |
115 | const struct mesh_setup *setup, | 163 | struct mesh_setup *setup, |
116 | const struct mesh_config *conf) | 164 | const struct mesh_config *conf) |
117 | { | 165 | { |
118 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 166 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -125,6 +173,45 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
125 | return err; | 173 | return err; |
126 | } | 174 | } |
127 | 175 | ||
176 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | ||
177 | struct wireless_dev *wdev, int freq, | ||
178 | enum nl80211_channel_type channel_type) | ||
179 | { | ||
180 | struct ieee80211_channel *channel; | ||
181 | |||
182 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
183 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
184 | channel, | ||
185 | channel_type)) { | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Workaround for libertas (only!), it puts the interface | ||
191 | * into mesh mode but doesn't implement join_mesh. Instead, | ||
192 | * it is configured via sysfs and then joins the mesh when | ||
193 | * you set the channel. Note that the libertas mesh isn't | ||
194 | * compatible with 802.11 mesh. | ||
195 | */ | ||
196 | if (rdev->ops->libertas_set_mesh_channel) { | ||
197 | if (channel_type != NL80211_CHAN_NO_HT) | ||
198 | return -EINVAL; | ||
199 | |||
200 | if (!netif_running(wdev->netdev)) | ||
201 | return -ENETDOWN; | ||
202 | return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, | ||
203 | wdev->netdev, | ||
204 | channel); | ||
205 | } | ||
206 | |||
207 | if (wdev->mesh_id_len) | ||
208 | return -EBUSY; | ||
209 | |||
210 | wdev->preset_chan = channel; | ||
211 | wdev->preset_chantype = channel_type; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
128 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | 215 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, |
129 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) | 216 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) |
130 | { | 217 | { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index eb90988bbd36..da4406f11929 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -947,8 +947,6 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | |||
947 | if (WARN_ON(!chan)) | 947 | if (WARN_ON(!chan)) |
948 | goto out; | 948 | goto out; |
949 | 949 | ||
950 | wdev->channel = chan; | ||
951 | |||
952 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); | 950 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); |
953 | out: | 951 | out: |
954 | wdev_unlock(wdev); | 952 | wdev_unlock(wdev); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 206465dc0cab..7ae54b82291f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -921,7 +921,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | 921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) |
922 | goto nla_put_failure; | 922 | goto nla_put_failure; |
923 | } | 923 | } |
924 | CMD(set_channel, SET_CHANNEL); | 924 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || |
925 | dev->ops->join_mesh) { | ||
926 | i++; | ||
927 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
928 | goto nla_put_failure; | ||
929 | } | ||
925 | CMD(set_wds_peer, SET_WDS_PEER); | 930 | CMD(set_wds_peer, SET_WDS_PEER); |
926 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 931 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
927 | CMD(tdls_mgmt, TDLS_MGMT); | 932 | CMD(tdls_mgmt, TDLS_MGMT); |
@@ -1162,18 +1167,22 @@ static int parse_txq_params(struct nlattr *tb[], | |||
1162 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | 1167 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) |
1163 | { | 1168 | { |
1164 | /* | 1169 | /* |
1165 | * You can only set the channel explicitly for AP, mesh | 1170 | * You can only set the channel explicitly for WDS interfaces, |
1166 | * and WDS type interfaces; all others have their channel | 1171 | * all others have their channel managed via their respective |
1167 | * managed via their respective "establish a connection" | 1172 | * "establish a connection" command (connect, join, ...) |
1168 | * command (connect, join, ...) | 1173 | * |
1174 | * For AP/GO and mesh mode, the channel can be set with the | ||
1175 | * channel userspace API, but is only stored and passed to the | ||
1176 | * low-level driver when the AP starts or the mesh is joined. | ||
1177 | * This is for backward compatibility, userspace can also give | ||
1178 | * the channel in the start-ap or join-mesh commands instead. | ||
1169 | * | 1179 | * |
1170 | * Monitors are special as they are normally slaved to | 1180 | * Monitors are special as they are normally slaved to |
1171 | * whatever else is going on, so they behave as though | 1181 | * whatever else is going on, so they have their own special |
1172 | * you tried setting the wiphy channel itself. | 1182 | * operation to set the monitor channel if possible. |
1173 | */ | 1183 | */ |
1174 | return !wdev || | 1184 | return !wdev || |
1175 | wdev->iftype == NL80211_IFTYPE_AP || | 1185 | wdev->iftype == NL80211_IFTYPE_AP || |
1176 | wdev->iftype == NL80211_IFTYPE_WDS || | ||
1177 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | 1186 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || |
1178 | wdev->iftype == NL80211_IFTYPE_MONITOR || | 1187 | wdev->iftype == NL80211_IFTYPE_MONITOR || |
1179 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | 1188 | wdev->iftype == NL80211_IFTYPE_P2P_GO; |
@@ -1204,9 +1213,14 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1204 | struct wireless_dev *wdev, | 1213 | struct wireless_dev *wdev, |
1205 | struct genl_info *info) | 1214 | struct genl_info *info) |
1206 | { | 1215 | { |
1216 | struct ieee80211_channel *channel; | ||
1207 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 1217 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
1208 | u32 freq; | 1218 | u32 freq; |
1209 | int result; | 1219 | int result; |
1220 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; | ||
1221 | |||
1222 | if (wdev) | ||
1223 | iftype = wdev->iftype; | ||
1210 | 1224 | ||
1211 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 1225 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
1212 | return -EINVAL; | 1226 | return -EINVAL; |
@@ -1221,12 +1235,32 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1221 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 1235 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
1222 | 1236 | ||
1223 | mutex_lock(&rdev->devlist_mtx); | 1237 | mutex_lock(&rdev->devlist_mtx); |
1224 | if (wdev) { | 1238 | switch (iftype) { |
1225 | wdev_lock(wdev); | 1239 | case NL80211_IFTYPE_AP: |
1226 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); | 1240 | case NL80211_IFTYPE_P2P_GO: |
1227 | wdev_unlock(wdev); | 1241 | if (wdev->beacon_interval) { |
1228 | } else { | 1242 | result = -EBUSY; |
1229 | result = cfg80211_set_freq(rdev, NULL, freq, channel_type); | 1243 | break; |
1244 | } | ||
1245 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
1246 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
1247 | channel, | ||
1248 | channel_type)) { | ||
1249 | result = -EINVAL; | ||
1250 | break; | ||
1251 | } | ||
1252 | wdev->preset_chan = channel; | ||
1253 | wdev->preset_chantype = channel_type; | ||
1254 | result = 0; | ||
1255 | break; | ||
1256 | case NL80211_IFTYPE_MESH_POINT: | ||
1257 | result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); | ||
1258 | break; | ||
1259 | case NL80211_IFTYPE_MONITOR: | ||
1260 | result = cfg80211_set_monitor_channel(rdev, freq, channel_type); | ||
1261 | break; | ||
1262 | default: | ||
1263 | result = -EINVAL; | ||
1230 | } | 1264 | } |
1231 | mutex_unlock(&rdev->devlist_mtx); | 1265 | mutex_unlock(&rdev->devlist_mtx); |
1232 | 1266 | ||
@@ -1310,8 +1344,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1310 | result = 0; | 1344 | result = 0; |
1311 | 1345 | ||
1312 | mutex_lock(&rdev->mtx); | 1346 | mutex_lock(&rdev->mtx); |
1313 | } else if (netif_running(netdev) && | 1347 | } else if (nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) |
1314 | nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | ||
1315 | wdev = netdev->ieee80211_ptr; | 1348 | wdev = netdev->ieee80211_ptr; |
1316 | else | 1349 | else |
1317 | wdev = NULL; | 1350 | wdev = NULL; |
@@ -2299,6 +2332,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2299 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); | 2332 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); |
2300 | } | 2333 | } |
2301 | 2334 | ||
2335 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
2336 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
2337 | |||
2338 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
2339 | !nl80211_valid_channel_type(info, &channel_type)) | ||
2340 | return -EINVAL; | ||
2341 | |||
2342 | params.channel = rdev_freq_to_chan(rdev, | ||
2343 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
2344 | channel_type); | ||
2345 | if (!params.channel) | ||
2346 | return -EINVAL; | ||
2347 | params.channel_type = channel_type; | ||
2348 | } else if (wdev->preset_chan) { | ||
2349 | params.channel = wdev->preset_chan; | ||
2350 | params.channel_type = wdev->preset_chantype; | ||
2351 | } else | ||
2352 | return -EINVAL; | ||
2353 | |||
2354 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, | ||
2355 | params.channel_type)) | ||
2356 | return -EINVAL; | ||
2357 | |||
2302 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); | 2358 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); |
2303 | if (!err) | 2359 | if (!err) |
2304 | wdev->beacon_interval = params.beacon_interval; | 2360 | wdev->beacon_interval = params.beacon_interval; |
@@ -5489,18 +5545,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5489 | 5545 | ||
5490 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 5546 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
5491 | 5547 | ||
5548 | if (!rdev->ops->remain_on_channel || | ||
5549 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) | ||
5550 | return -EOPNOTSUPP; | ||
5551 | |||
5492 | /* | 5552 | /* |
5493 | * We should be on that channel for at least one jiffie, | 5553 | * We should be on that channel for at least a minimum amount of |
5494 | * and more than 5 seconds seems excessive. | 5554 | * time (10ms) but no longer than the driver supports. |
5495 | */ | 5555 | */ |
5496 | if (!duration || !msecs_to_jiffies(duration) || | 5556 | if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || |
5497 | duration > rdev->wiphy.max_remain_on_channel_duration) | 5557 | duration > rdev->wiphy.max_remain_on_channel_duration) |
5498 | return -EINVAL; | 5558 | return -EINVAL; |
5499 | 5559 | ||
5500 | if (!rdev->ops->remain_on_channel || | ||
5501 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) | ||
5502 | return -EOPNOTSUPP; | ||
5503 | |||
5504 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 5560 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && |
5505 | !nl80211_valid_channel_type(info, &channel_type)) | 5561 | !nl80211_valid_channel_type(info, &channel_type)) |
5506 | return -EINVAL; | 5562 | return -EINVAL; |
@@ -5771,6 +5827,15 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
5771 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 5827 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
5772 | return -EINVAL; | 5828 | return -EINVAL; |
5773 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 5829 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
5830 | |||
5831 | /* | ||
5832 | * We should wait on the channel for at least a minimum amount | ||
5833 | * of time (10ms) but no longer than the driver supports. | ||
5834 | */ | ||
5835 | if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || | ||
5836 | wait > rdev->wiphy.max_remain_on_channel_duration) | ||
5837 | return -EINVAL; | ||
5838 | |||
5774 | } | 5839 | } |
5775 | 5840 | ||
5776 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 5841 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
@@ -6032,6 +6097,24 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6032 | return err; | 6097 | return err; |
6033 | } | 6098 | } |
6034 | 6099 | ||
6100 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
6101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
6102 | |||
6103 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
6104 | !nl80211_valid_channel_type(info, &channel_type)) | ||
6105 | return -EINVAL; | ||
6106 | |||
6107 | setup.channel = rdev_freq_to_chan(rdev, | ||
6108 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
6109 | channel_type); | ||
6110 | if (!setup.channel) | ||
6111 | return -EINVAL; | ||
6112 | setup.channel_type = channel_type; | ||
6113 | } else { | ||
6114 | /* cfg80211_join_mesh() will sort it out */ | ||
6115 | setup.channel = NULL; | ||
6116 | } | ||
6117 | |||
6035 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 6118 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
6036 | } | 6119 | } |
6037 | 6120 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6a6181a673ca..bc879833b21f 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -796,7 +796,15 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
796 | case NL80211_IFTYPE_ADHOC: | 796 | case NL80211_IFTYPE_ADHOC: |
797 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); | 797 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); |
798 | case NL80211_IFTYPE_MONITOR: | 798 | case NL80211_IFTYPE_MONITOR: |
799 | case NL80211_IFTYPE_WDS: | 799 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
800 | if (freq < 0) | ||
801 | return freq; | ||
802 | if (freq == 0) | ||
803 | return -EINVAL; | ||
804 | mutex_lock(&rdev->devlist_mtx); | ||
805 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); | ||
806 | mutex_unlock(&rdev->devlist_mtx); | ||
807 | return err; | ||
800 | case NL80211_IFTYPE_MESH_POINT: | 808 | case NL80211_IFTYPE_MESH_POINT: |
801 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); | 809 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
802 | if (freq < 0) | 810 | if (freq < 0) |
@@ -804,9 +812,8 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
804 | if (freq == 0) | 812 | if (freq == 0) |
805 | return -EINVAL; | 813 | return -EINVAL; |
806 | mutex_lock(&rdev->devlist_mtx); | 814 | mutex_lock(&rdev->devlist_mtx); |
807 | wdev_lock(wdev); | 815 | err = cfg80211_set_mesh_freq(rdev, wdev, freq, |
808 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | 816 | NL80211_CHAN_NO_HT); |
809 | wdev_unlock(wdev); | ||
810 | mutex_unlock(&rdev->devlist_mtx); | 817 | mutex_unlock(&rdev->devlist_mtx); |
811 | return err; | 818 | return err; |
812 | default: | 819 | default: |
@@ -839,11 +846,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, | |||
839 | freq->e = 6; | 846 | freq->e = 6; |
840 | return 0; | 847 | return 0; |
841 | default: | 848 | default: |
842 | if (!wdev->channel) | 849 | return -EINVAL; |
843 | return -EINVAL; | ||
844 | freq->m = wdev->channel->center_freq; | ||
845 | freq->e = 6; | ||
846 | return 0; | ||
847 | } | 850 | } |
848 | } | 851 | } |
849 | 852 | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 7decbd357d51..1f773f668d1a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -111,9 +111,15 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
111 | 111 | ||
112 | wdev->wext.connect.channel = chan; | 112 | wdev->wext.connect.channel = chan; |
113 | 113 | ||
114 | /* SSID is not set, we just want to switch channel */ | 114 | /* |
115 | * SSID is not set, we just want to switch monitor channel, | ||
116 | * this is really just backward compatibility, if the SSID | ||
117 | * is set then we use the channel to select the BSS to use | ||
118 | * to connect to instead. If we were connected on another | ||
119 | * channel we disconnected above and reconnect below. | ||
120 | */ | ||
115 | if (chan && !wdev->wext.connect.ssid_len) { | 121 | if (chan && !wdev->wext.connect.ssid_len) { |
116 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | 122 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); |
117 | goto out; | 123 | goto out; |
118 | } | 124 | } |
119 | 125 | ||