/* * Detach net80211 state on device detach. Tear down * all vap's and reclaim all common state prior to the * device state going away. Note we may call back into * driver; it must be prepared for this. */ void ieee80211_ifdetach(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap; if_detach(ifp); while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) ieee80211_vap_destroy(vap); ieee80211_waitfor_parent(ic); ieee80211_sysctl_detach(ic); ieee80211_dfs_detach(ic); ieee80211_regdomain_detach(ic); ieee80211_scan_detach(ic); #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_superg_detach(ic); #endif ieee80211_ht_detach(ic); /* NB: must be called before ieee80211_node_detach */ ieee80211_proto_detach(ic); ieee80211_crypto_detach(ic); ieee80211_power_detach(ic); ieee80211_node_detach(ic); ifmedia_removeall(&ic->ic_media); taskqueue_free(ic->ic_tq); }
void ieee80211_ifdetach(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; ieee80211_proto_detach(ifp); ieee80211_crypto_detach(ifp); ieee80211_node_detach(ifp); LIST_REMOVE(ic, ic_list); ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY); ether_ifdetach(ifp); }
void ieee80211_ifdetach(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; ieee80211_proto_detach(ifp); ieee80211_crypto_detach(ifp); ieee80211_node_detach(ifp); #ifdef __FreeBSD__ ifmedia_removeall(&ic->ic_media); #else ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY); #endif #if NBPFILTER > 0 bpfdetach(ifp); #endif ether_ifdetach(ifp); }
/* * Detach net80211 state on device detach. Tear down * all vap's and reclaim all common state prior to the * device state going away. Note we may call back into * driver; it must be prepared for this. */ void ieee80211_ifdetach(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap; /* * This detaches the main interface, but not the vaps. * Each VAP may be in a separate VIMAGE. */ CURVNET_SET(ifp->if_vnet); if_detach(ifp); CURVNET_RESTORE(); /* * The VAP is responsible for setting and clearing * the VIMAGE context. */ while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) ieee80211_vap_destroy(vap); ieee80211_waitfor_parent(ic); ieee80211_sysctl_detach(ic); ieee80211_dfs_detach(ic); ieee80211_regdomain_detach(ic); ieee80211_scan_detach(ic); #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_superg_detach(ic); #endif ieee80211_ht_detach(ic); /* NB: must be called before ieee80211_node_detach */ ieee80211_proto_detach(ic); ieee80211_crypto_detach(ic); ieee80211_power_detach(ic); ieee80211_node_detach(ic); /* XXX VNET needed? */ ifmedia_removeall(&ic->ic_media); taskqueue_free(ic->ic_tq); IEEE80211_TX_LOCK_DESTROY(ic); IEEE80211_LOCK_DESTROY(ic); }
void ieee80211_ifdetach(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; ieee80211_remove_vap(ic); ieee80211_sysctl_detach(ic); ieee80211_proto_detach(ic); ieee80211_crypto_detach(ic); ieee80211_node_detach(ic); LIST_REMOVE(ic, ic_list); ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY); IEEE80211_BEACON_LOCK_DESTROY(ic); bpf_detach(ifp); ether_ifdetach(ifp); }
int ieee80211_ifattach(struct ieee80211com *ic, IEEE80211_REG_PARAMETERS *ieee80211_reg_parm) { u_int8_t bcast[IEEE80211_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; int error = 0; ic->ic_reg_parm = *ieee80211_reg_parm; /* set up broadcast address */ IEEE80211_ADDR_COPY(ic->ic_broadcast, bcast); /* initialize channel list */ ieee80211_update_channellist(ic, 0); /* initialize rate set */ ieee80211_init_rateset(ic); /* validate ic->ic_curmode */ if (!IEEE80211_SUPPORT_PHY_MODE(ic, ic->ic_curmode)) ic->ic_curmode = IEEE80211_MODE_AUTO; /* setup initial channel settings */ ic->ic_curchan = ieee80211_get_channel(ic, 0); /* arbitrarily pick the first channel */ /* Enable marking of dfs by default */ ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS; if (ic->ic_reg_parm.htEnableWepTkip) { ieee80211_ic_wep_tkip_htrate_set(ic); } else { ieee80211_ic_wep_tkip_htrate_clear(ic); } if (ic->ic_reg_parm.htVendorIeEnable) IEEE80211_ENABLE_HTVIE(ic); /* whether to ignore 11d beacon */ if (ic->ic_reg_parm.ignore11dBeacon) IEEE80211_ENABLE_IGNORE_11D_BEACON(ic); if (ic->ic_reg_parm.disallowAutoCCchange) { ieee80211_ic_disallowAutoCCchange_set(ic); } else { ieee80211_ic_disallowAutoCCchange_clear(ic); } (void) ieee80211_setmode(ic, ic->ic_curmode, ic->ic_opmode); ic->ic_intval = IEEE80211_BINTVAL_DEFAULT; /* beacon interval */ ic->ic_set_beacon_interval(ic); ic->ic_lintval = 1; /* listen interval */ ic->ic_lintval_assoc = IEEE80211_LINTVAL_MAX; /* listen interval to use in association */ ic->ic_bmisstimeout = IEEE80211_BMISS_LIMIT * ic->ic_intval; TAILQ_INIT(&ic->ic_vaps); ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; /* Intialize WDS Auto Detect mode */ ic->ic_flags_ext |= IEEE80211_FEXT_WDS_AUTODETECT; /* ** Enable the 11d country code IE by default */ ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE; /* setup CWM configuration */ ic->ic_cwm_set_mode(ic, ic->ic_reg_parm.cwmMode); ic->ic_cwm_set_extoffset(ic, ic->ic_reg_parm.cwmExtOffset); ic->ic_cwm_set_extprotmode(ic, ic->ic_reg_parm.cwmExtProtMode); ic->ic_cwm_set_extprotspacing(ic, ic->ic_reg_parm.cwmExtProtSpacing); #if tbd /* XXX - TODO - move these into ath layer */ #else ic->ic_cwm_set_enable(ic, ic->ic_reg_parm.cwmEnable); ic->ic_cwm_set_extbusythreshold(ic, ic->ic_reg_parm.cwmExtBusyThreshold); #endif ic->ic_enable2GHzHt40Cap = ic->ic_reg_parm.enable2GHzHt40Cap; #ifdef ATH_COALESCING ic->ic_tx_coalescing = ic->ic_reg_parm.txCoalescingEnable; #endif ic->ic_ignoreDynamicHalt = ic->ic_reg_parm.ignoreDynamicHalt; /* default to auto ADDBA mode */ ic->ic_addba_mode = ADDBA_MODE_AUTO; if (ic->ic_reg_parm.ht20AdhocEnable) { /* * Support HT rates in Ad hoc connections. */ if (IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT20) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT20)) { ieee80211_ic_ht20Adhoc_set(ic); if (ic->ic_reg_parm.htAdhocAggrEnable) { ieee80211_ic_htAdhocAggr_set(ic); } } } if (ic->ic_reg_parm.ht40AdhocEnable) { /* * Support HT rates in Ad hoc connections. */ if (IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT40PLUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT40MINUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT40PLUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT40MINUS)) { ieee80211_ic_ht40Adhoc_set(ic); if (ic->ic_reg_parm.htAdhocAggrEnable) { ieee80211_ic_htAdhocAggr_set(ic); } } } OS_INIT_TIMER(ic->ic_osdev, &(ic->ic_inact_timer), ieee80211_inact_timeout, (void *) (ic)); #if UMAC_SUPPORT_WNM OS_INIT_TIMER(ic->ic_osdev, &(ic->ic_bssload_timer), ieee80211_bssload_timeout, (void *) (ic)); #endif if (ic->ic_reg_parm.disable2040Coexist) { ic->ic_flags |= IEEE80211_F_COEXT_DISABLE; } else { ic->ic_flags &= ~IEEE80211_F_COEXT_DISABLE; } /* setup other modules */ /* The TSF Timer module is required when P2P or Off-channel support are required */ ic->ic_tsf_timer = ieee80211_tsf_timer_attach(ic); #if UMAC_SUPPORT_TDLS_CHAN_SWITCH /* TDLS off-channel support requires TSF timer */ if (ic->ic_tsf_timer) { ieee80211_ic_off_channel_support_set(ic); } else { ieee80211_ic_off_channel_support_clear(ic); } #else ieee80211_ic_off_channel_support_clear(ic); #endif ieee80211_p2p_attach(ic); ieee80211_crypto_attach(ic); ieee80211_node_attach(ic); ieee80211_proto_attach(ic); ieee80211_power_attach(ic); ieee80211_mlme_attach(ic); #if ATH_SUPPORT_DFS ieee80211_dfs_attach(ic); #endif /* ATH_SUPPORT_DFS */ if (IEEE80211_ENAB_AOW(ic)) ieee80211_aow_attach(ic); error = ieee80211_scan_table_attach(ic, &(ic->ic_scan_table), ic->ic_osdev); if (error) { ieee80211_node_detach(ic); return error; } /* * By default overwrite probe response with beacon IE in scan entry. */ ieee80211_ic_override_proberesp_ie_set(ic); error = ieee80211_scan_attach(&(ic->ic_scanner), ic, ic->ic_osdev, ieee80211_is_connected, ieee80211_is_txq_empty, ieee80211_is_sw_txq_empty); if (error) { /* detach and free already allocated memory for scan */ ieee80211_scan_table_detach(&(ic->ic_scan_table)); ieee80211_node_detach(ic); return error; } ic->ic_resmgr = ieee80211_resmgr_create(ic, IEEE80211_RESMGR_MODE_SINGLE_CHANNEL); error = ieee80211_acs_attach(&(ic->ic_acs), ic, ic->ic_osdev); if (error) { /* detach and free already allocated memory for scan */ ieee80211_scan_table_detach(&(ic->ic_scan_table)); ieee80211_scan_detach(&(ic->ic_scanner)); ieee80211_node_detach(ic); return error; } ic->ic_notify_tx_bcn_mgr = ieee80211_notify_tx_bcn_attach(ic); ieee80211_rptplacement_attach(ic); IEEE80211_TDLS_ATTACH(ic); #if UMAC_SUPPORT_VI_DBG ieee80211_vi_dbg_attach(ic); #endif ieee80211_quiet_attach(ic); ieee80211_admctl_attach(ic); /* * Perform steps that require multiple objects to be initialized. * For example, cross references between objects such as ResMgr and Scanner. */ ieee80211_scan_attach_complete(ic->ic_scanner); ieee80211_resmgr_create_complete(ic->ic_resmgr); ieee80211_smartantenna_attach(ic); ieee80211_prdperfstats_attach(ic); ic->ic_get_ext_chan_info = ieee80211_get_extchan_info; /* initialization complete */ ic->ic_initialized = 1; return 0; }
void ieee80211_ifdetach(struct ieee80211com *ic) { if (!ic->ic_initialized) { return; } /* * Preparation for detaching objects. * For example, remove and cross references between objects such as those * between ResMgr and Scanner. */ ieee80211_scan_detach_prepare(ic->ic_scanner); ieee80211_resmgr_delete_prepare(ic->ic_resmgr); OS_FREE_TIMER(&ic->ic_inact_timer); #if UMAC_SUPPORT_WNM OS_FREE_TIMER(&ic->ic_bssload_timer); #endif /* all the vaps should have been deleted now */ ASSERT(TAILQ_FIRST(&ic->ic_vaps) == NULL); ieee80211_scan_table_detach(&(ic->ic_scan_table)); ieee80211_node_detach(ic); ieee80211_quiet_detach(ic); ieee80211_admctl_detach(ic); if (IEEE80211_ENAB_AOW(ic)) ieee80211_aow_detach(ic); #if ATH_SUPPORT_DFS ieee80211_dfs_detach(ic); #endif /* ATH_SUPPORT_DFS */ ieee80211_proto_detach(ic); ieee80211_crypto_detach(ic); ieee80211_power_detach(ic); ieee80211_mlme_detach(ic); ieee80211_notify_tx_bcn_detach(ic->ic_notify_tx_bcn_mgr); ieee80211_resmgr_delete(ic->ic_resmgr); ieee80211_scan_detach(&(ic->ic_scanner)); ieee80211_p2p_detach(ic); ieee80211_acs_detach(&(ic->ic_acs)); ieee80211_rptplacement_detach(ic); IEEE80211_TDLS_DETACH(ic); #if UMAC_SUPPORT_VI_DBG ieee80211_vi_dbg_detach(ic); #endif ieee80211_smartantenna_detach(ic); ieee80211_prdperfstats_detach(ic); spin_lock_destroy(&ic->ic_lock); /* Detach TSF timer at the end to avoid assertion */ if (ic->ic_tsf_timer) { ieee80211_tsf_timer_detach(ic->ic_tsf_timer); ic->ic_tsf_timer = NULL; } spin_lock_destroy(&ic->ic_lock); IEEE80211_STATE_LOCK_DESTROY(ic); }