aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h7
-rw-r--r--net/mac80211/driver-ops.h27
-rw-r--r--net/mac80211/ibss.c22
-rw-r--r--net/mac80211/trace.h35
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 */
2670struct ieee80211_ops { 2674struct 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
1088static 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
1103static 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
1478TRACE_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
1507DEFINE_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 */