Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: add explicit IBSS driver operations

This can be useful for drivers if they have any failure cases
when joining an IBSS. Also move setting the queue parameters
to before this new call, in case the new driver op needs them
already.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+89 -2
+7
include/net/mac80211.h
··· 2666 2666 * zero using ieee80211_csa_is_complete() after the beacon has been 2667 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 2674 struct ieee80211_ops { 2671 2675 void (*tx)(struct ieee80211_hw *hw, ··· 2861 2857 void (*channel_switch_beacon)(struct ieee80211_hw *hw, 2862 2858 struct ieee80211_vif *vif, 2863 2859 struct cfg80211_chan_def *chandef); 2860 + 2861 + int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2862 + void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2864 2863 }; 2865 2864 2866 2865 /**
+27
net/mac80211/driver-ops.h
··· 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 1115 #endif /* __MAC80211_DRIVER_OPS */
+20 -2
net/mac80211/ibss.c
··· 229 229 struct beacon_data *presp; 230 230 enum nl80211_bss_scan_width scan_width; 231 231 bool have_higher_than_11mbit; 232 + int err; 232 233 233 234 sdata_assert_lock(sdata); 234 235 ··· 248 247 ieee80211_bss_info_change_notify(sdata, 249 248 BSS_CHANGED_IBSS | 250 249 BSS_CHANGED_BEACON_ENABLED); 250 + drv_leave_ibss(local, sdata); 251 251 } 252 252 253 253 presp = rcu_dereference_protected(ifibss->presp, ··· 331 329 else 332 330 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 333 331 332 + ieee80211_set_wmm_default(sdata, true); 333 + 334 334 sdata->vif.bss_conf.ibss_joined = true; 335 335 sdata->vif.bss_conf.ibss_creator = creator; 336 - ieee80211_bss_info_change_notify(sdata, bss_change); 337 336 338 - ieee80211_set_wmm_default(sdata, true); 337 + err = drv_join_ibss(local, sdata); 338 + if (err) { 339 + sdata->vif.bss_conf.ibss_joined = false; 340 + sdata->vif.bss_conf.ibss_creator = false; 341 + sdata->vif.bss_conf.enable_beacon = false; 342 + sdata->vif.bss_conf.ssid_len = 0; 343 + RCU_INIT_POINTER(ifibss->presp, NULL); 344 + kfree_rcu(presp, rcu_head); 345 + ieee80211_vif_release_channel(sdata); 346 + sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", 347 + err); 348 + return; 349 + } 350 + 351 + ieee80211_bss_info_change_notify(sdata, bss_change); 339 352 340 353 ifibss->state = IEEE80211_IBSS_MLME_JOINED; 341 354 mod_timer(&ifibss->timer, ··· 778 761 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 779 762 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 780 763 BSS_CHANGED_IBSS); 764 + drv_leave_ibss(local, sdata); 781 765 ieee80211_vif_release_channel(sdata); 782 766 } 783 767
+35
net/mac80211/trace.h
··· 1475 1475 ); 1476 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 1514 * Tracing for API calls that drivers call. 1480 1515 */