diff options
-rw-r--r-- | include/net/mac80211.h | 7 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 27 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 22 | ||||
-rw-r--r-- | net/mac80211/trace.h | 35 |
4 files changed, 89 insertions, 2 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3411c59b636b..8cff800f7046 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -2666,6 +2666,10 @@ enum ieee80211_roc_type { | |||
2666 | * zero using ieee80211_csa_is_complete() after the beacon has been | 2666 | * zero using ieee80211_csa_is_complete() after the beacon has been |
2667 | * transmitted and then call ieee80211_csa_finish(). | 2667 | * transmitted and then call ieee80211_csa_finish(). |
2668 | * | 2668 | * |
2669 | * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all | ||
2670 | * information in bss_conf is set up and the beacon can be retrieved. A | ||
2671 | * channel context is bound before this is called. | ||
2672 | * @leave_ibss: Leave the IBSS again. | ||
2669 | */ | 2673 | */ |
2670 | struct ieee80211_ops { | 2674 | struct ieee80211_ops { |
2671 | void (*tx)(struct ieee80211_hw *hw, | 2675 | void (*tx)(struct ieee80211_hw *hw, |
@@ -2857,6 +2861,9 @@ struct ieee80211_ops { | |||
2857 | void (*channel_switch_beacon)(struct ieee80211_hw *hw, | 2861 | void (*channel_switch_beacon)(struct ieee80211_hw *hw, |
2858 | struct ieee80211_vif *vif, | 2862 | struct ieee80211_vif *vif, |
2859 | struct cfg80211_chan_def *chandef); | 2863 | struct cfg80211_chan_def *chandef); |
2864 | |||
2865 | int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
2866 | void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
2860 | }; | 2867 | }; |
2861 | 2868 | ||
2862 | /** | 2869 | /** |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b3ea11f3d526..5d03c47c0a4c 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -1085,4 +1085,31 @@ drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, | |||
1085 | } | 1085 | } |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static inline int drv_join_ibss(struct ieee80211_local *local, | ||
1089 | struct ieee80211_sub_if_data *sdata) | ||
1090 | { | ||
1091 | int ret = 0; | ||
1092 | |||
1093 | might_sleep(); | ||
1094 | check_sdata_in_driver(sdata); | ||
1095 | |||
1096 | trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); | ||
1097 | if (local->ops->join_ibss) | ||
1098 | ret = local->ops->join_ibss(&local->hw, &sdata->vif); | ||
1099 | trace_drv_return_int(local, ret); | ||
1100 | return ret; | ||
1101 | } | ||
1102 | |||
1103 | static inline void drv_leave_ibss(struct ieee80211_local *local, | ||
1104 | struct ieee80211_sub_if_data *sdata) | ||
1105 | { | ||
1106 | might_sleep(); | ||
1107 | check_sdata_in_driver(sdata); | ||
1108 | |||
1109 | trace_drv_leave_ibss(local, sdata); | ||
1110 | if (local->ops->leave_ibss) | ||
1111 | local->ops->leave_ibss(&local->hw, &sdata->vif); | ||
1112 | trace_drv_return_void(local); | ||
1113 | } | ||
1114 | |||
1088 | #endif /* __MAC80211_DRIVER_OPS */ | 1115 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5ea9b3ae303e..21a0b8835cb3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -229,6 +229,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
229 | struct beacon_data *presp; | 229 | struct beacon_data *presp; |
230 | enum nl80211_bss_scan_width scan_width; | 230 | enum nl80211_bss_scan_width scan_width; |
231 | bool have_higher_than_11mbit; | 231 | bool have_higher_than_11mbit; |
232 | int err; | ||
232 | 233 | ||
233 | sdata_assert_lock(sdata); | 234 | sdata_assert_lock(sdata); |
234 | 235 | ||
@@ -247,6 +248,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
247 | ieee80211_bss_info_change_notify(sdata, | 248 | ieee80211_bss_info_change_notify(sdata, |
248 | BSS_CHANGED_IBSS | | 249 | BSS_CHANGED_IBSS | |
249 | BSS_CHANGED_BEACON_ENABLED); | 250 | BSS_CHANGED_BEACON_ENABLED); |
251 | drv_leave_ibss(local, sdata); | ||
250 | } | 252 | } |
251 | 253 | ||
252 | presp = rcu_dereference_protected(ifibss->presp, | 254 | presp = rcu_dereference_protected(ifibss->presp, |
@@ -329,11 +331,26 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
329 | else | 331 | else |
330 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 332 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
331 | 333 | ||
334 | ieee80211_set_wmm_default(sdata, true); | ||
335 | |||
332 | sdata->vif.bss_conf.ibss_joined = true; | 336 | sdata->vif.bss_conf.ibss_joined = true; |
333 | sdata->vif.bss_conf.ibss_creator = creator; | 337 | sdata->vif.bss_conf.ibss_creator = creator; |
334 | ieee80211_bss_info_change_notify(sdata, bss_change); | ||
335 | 338 | ||
336 | ieee80211_set_wmm_default(sdata, true); | 339 | err = drv_join_ibss(local, sdata); |
340 | if (err) { | ||
341 | sdata->vif.bss_conf.ibss_joined = false; | ||
342 | sdata->vif.bss_conf.ibss_creator = false; | ||
343 | sdata->vif.bss_conf.enable_beacon = false; | ||
344 | sdata->vif.bss_conf.ssid_len = 0; | ||
345 | RCU_INIT_POINTER(ifibss->presp, NULL); | ||
346 | kfree_rcu(presp, rcu_head); | ||
347 | ieee80211_vif_release_channel(sdata); | ||
348 | sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", | ||
349 | err); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | ieee80211_bss_info_change_notify(sdata, bss_change); | ||
337 | 354 | ||
338 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 355 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
339 | mod_timer(&ifibss->timer, | 356 | mod_timer(&ifibss->timer, |
@@ -761,6 +778,7 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) | |||
761 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 778 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
762 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 779 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
763 | BSS_CHANGED_IBSS); | 780 | BSS_CHANGED_IBSS); |
781 | drv_leave_ibss(local, sdata); | ||
764 | ieee80211_vif_release_channel(sdata); | 782 | ieee80211_vif_release_channel(sdata); |
765 | } | 783 | } |
766 | 784 | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 1aba645882bd..5d62c5804819 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1475,6 +1475,41 @@ DEFINE_EVENT(local_sdata_evt, drv_ipv6_addr_change, | |||
1475 | ); | 1475 | ); |
1476 | #endif | 1476 | #endif |
1477 | 1477 | ||
1478 | TRACE_EVENT(drv_join_ibss, | ||
1479 | TP_PROTO(struct ieee80211_local *local, | ||
1480 | struct ieee80211_sub_if_data *sdata, | ||
1481 | struct ieee80211_bss_conf *info), | ||
1482 | |||
1483 | TP_ARGS(local, sdata, info), | ||
1484 | |||
1485 | TP_STRUCT__entry( | ||
1486 | LOCAL_ENTRY | ||
1487 | VIF_ENTRY | ||
1488 | __field(u8, dtimper) | ||
1489 | __field(u16, bcnint) | ||
1490 | __dynamic_array(u8, ssid, info->ssid_len); | ||
1491 | ), | ||
1492 | |||
1493 | TP_fast_assign( | ||
1494 | LOCAL_ASSIGN; | ||
1495 | VIF_ASSIGN; | ||
1496 | __entry->dtimper = info->dtim_period; | ||
1497 | __entry->bcnint = info->beacon_int; | ||
1498 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); | ||
1499 | ), | ||
1500 | |||
1501 | TP_printk( | ||
1502 | LOCAL_PR_FMT VIF_PR_FMT, | ||
1503 | LOCAL_PR_ARG, VIF_PR_ARG | ||
1504 | ) | ||
1505 | ); | ||
1506 | |||
1507 | DEFINE_EVENT(local_sdata_evt, drv_leave_ibss, | ||
1508 | TP_PROTO(struct ieee80211_local *local, | ||
1509 | struct ieee80211_sub_if_data *sdata), | ||
1510 | TP_ARGS(local, sdata) | ||
1511 | ); | ||
1512 | |||
1478 | /* | 1513 | /* |
1479 | * Tracing for API calls that drivers call. | 1514 | * Tracing for API calls that drivers call. |
1480 | */ | 1515 | */ |