@ -488,8 +488,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
static int ath10k_vdev_start ( struct ath10k_vif * arvif )
{
struct ath10k * ar = arvif - > ar ;
struct ieee80211_conf * conf = & ar - > hw - > conf ;
struct ieee80211_channel * channel = conf - > chandef . chan ;
struct cfg80211_chan_def * chandef = & ar - > chandef ;
struct wmi_vdev_start_request_arg arg = { } ;
int ret = 0 ;
@ -501,16 +500,14 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
arg . dtim_period = arvif - > dtim_period ;
arg . bcn_intval = arvif - > beacon_interval ;
arg . channel . freq = channel - > center_freq ;
arg . channel . band_center_freq1 = conf - > chandef . center_freq1 ;
arg . channel . mode = chan_to_phymode ( & conf - > chandef ) ;
arg . channel . freq = chandef - > chan - > center_freq ;
arg . channel . band_center_freq1 = chandef - > center_freq1 ;
arg . channel . mode = chan_to_phymode ( chandef ) ;
arg . channel . min_power = 0 ;
arg . channel . max_power = channel - > max_power * 2 ;
arg . channel . max_reg_power = channel - > max_reg_power * 2 ;
arg . channel . max_antenna_gain = channel - > max_antenna_gain * 2 ;
arg . channel . max_power = chandef - > chan - > max_power * 2 ;
arg . channel . max_reg_power = chandef - > chan - > max_reg_power * 2 ;
arg . channel . max_antenna_gain = chandef - > chan - > max_antenna_gain * 2 ;
if ( arvif - > vdev_type = = WMI_VDEV_TYPE_AP ) {
arg . ssid = arvif - > u . ap . ssid ;
@ -519,7 +516,7 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
/* For now allow DFS for AP mode */
arg . channel . chan_radar =
! ! ( channel - > flags & IEEE80211_CHAN_RADAR ) ;
! ! ( chandef - > chan - > flags & IEEE80211_CHAN_RADAR ) ;
} else if ( arvif - > vdev_type = = WMI_VDEV_TYPE_IBSS ) {
arg . ssid = arvif - > vif - > bss_conf . ssid ;
arg . ssid_len = arvif - > vif - > bss_conf . ssid_len ;
@ -571,7 +568,8 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
static int ath10k_monitor_start ( struct ath10k * ar , int vdev_id )
{
struct ieee80211_channel * channel = ar - > hw - > conf . chandef . chan ;
struct cfg80211_chan_def * chandef = & ar - > chandef ;
struct ieee80211_channel * channel = chandef - > chan ;
struct wmi_vdev_start_request_arg arg = { } ;
int ret = 0 ;
@ -584,11 +582,11 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
arg . vdev_id = vdev_id ;
arg . channel . freq = channel - > center_freq ;
arg . channel . band_center_freq1 = ar - > hw - > conf . chandef . center_freq1 ;
arg . channel . band_center_freq1 = chandef - > center_freq1 ;
/* TODO setup this dynamically, what in case we
don ' t have any vifs ? */
arg . channel . mode = chan_to_phymode ( & ar - > hw - > conf . chandef ) ;
arg . channel . mode = chan_to_phymode ( chandef ) ;
arg . channel . chan_radar =
! ! ( channel - > flags & IEEE80211_CHAN_RADAR ) ;
@ -835,6 +833,10 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
if ( ! info - > enable_beacon ) {
ath10k_vdev_stop ( arvif ) ;
arvif - > is_started = false ;
arvif - > is_up = false ;
return ;
}
@ -844,12 +846,21 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
if ( ret )
return ;
ret = ath10k_wmi_vdev_up ( arvif - > ar , arvif - > vdev_id , 0 , info - > bssid ) ;
arvif - > aid = 0 ;
memcpy ( arvif - > bssid , info - > bssid , ETH_ALEN ) ;
ret = ath10k_wmi_vdev_up ( arvif - > ar , arvif - > vdev_id , arvif - > aid ,
arvif - > bssid ) ;
if ( ret ) {
ath10k_warn ( " Failed to bring up VDEV: %d \n " ,
arvif - > vdev_id ) ;
ath10k_vdev_stop ( arvif ) ;
return ;
}
arvif - > is_started = true ;
arvif - > is_up = true ;
ath10k_dbg ( ATH10K_DBG_MAC , " mac vdev %d up \n " , arvif - > vdev_id ) ;
}
@ -868,18 +879,18 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
ath10k_warn ( " Failed to delete IBSS self peer:%pM for VDEV:%d ret:%d \n " ,
self_peer , arvif - > vdev_id , ret ) ;
if ( is_zero_ether_addr ( arvif - > u . ibss . bssid ) )
if ( is_zero_ether_addr ( arvif - > bssid ) )
return ;
ret = ath10k_peer_delete ( arvif - > ar , arvif - > vdev_id ,
arvif - > u . ibss . bssid ) ;
arvif - > bssid ) ;
if ( ret ) {
ath10k_warn ( " Failed to delete IBSS BSSID peer:%pM for VDEV:%d ret:%d \n " ,
arvif - > u . ibss . bssid , arvif - > vdev_id , ret ) ;
arvif - > bssid , arvif - > vdev_id , ret ) ;
return ;
}
memset ( arvif - > u . ibss . bssid , 0 , ETH_ALEN ) ;
memset ( arvif - > bssid , 0 , ETH_ALEN ) ;
return ;
}
@ -1387,11 +1398,17 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
" mac vdev %d up (associated) bssid %pM aid %d \n " ,
arvif - > vdev_id , bss_conf - > bssid , bss_conf - > aid ) ;
ret = ath10k_wmi_vdev_up ( ar , arvif - > vdev_id , bss_conf - > aid ,
bss_conf - > bssid ) ;
if ( ret )
arvif - > aid = bss_conf - > aid ;
memcpy ( arvif - > bssid , bss_conf - > bssid , ETH_ALEN ) ;
ret = ath10k_wmi_vdev_up ( ar , arvif - > vdev_id , arvif - > aid , arvif - > bssid ) ;
if ( ret ) {
ath10k_warn ( " VDEV: %d up failed: ret %d \n " ,
arvif - > vdev_id , ret ) ;
return ;
}
arvif - > is_up = true ;
}
/*
@ -1431,6 +1448,9 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
ret = ath10k_wmi_vdev_down ( ar , arvif - > vdev_id ) ;
arvif - > def_wep_key_idx = 0 ;
arvif - > is_started = false ;
arvif - > is_up = false ;
}
static int ath10k_station_assoc ( struct ath10k * ar , struct ath10k_vif * arvif ,
@ -2201,6 +2221,98 @@ static int ath10k_config_ps(struct ath10k *ar)
return ret ;
}
static const char * chandef_get_width ( enum nl80211_chan_width width )
{
switch ( width ) {
case NL80211_CHAN_WIDTH_20_NOHT :
return " 20 (noht) " ;
case NL80211_CHAN_WIDTH_20 :
return " 20 " ;
case NL80211_CHAN_WIDTH_40 :
return " 40 " ;
case NL80211_CHAN_WIDTH_80 :
return " 80 " ;
case NL80211_CHAN_WIDTH_80P80 :
return " 80+80 " ;
case NL80211_CHAN_WIDTH_160 :
return " 160 " ;
case NL80211_CHAN_WIDTH_5 :
return " 5 " ;
case NL80211_CHAN_WIDTH_10 :
return " 10 " ;
}
return " ? " ;
}
static void ath10k_config_chan ( struct ath10k * ar )
{
struct ath10k_vif * arvif ;
bool monitor_was_enabled ;
int ret ;
lockdep_assert_held ( & ar - > conf_mutex ) ;
ath10k_dbg ( ATH10K_DBG_MAC ,
" mac config channel to %dMHz (cf1 %dMHz cf2 %dMHz width %s) \n " ,
ar - > chandef . chan - > center_freq ,
ar - > chandef . center_freq1 ,
ar - > chandef . center_freq2 ,
chandef_get_width ( ar - > chandef . width ) ) ;
/* First stop monitor interface. Some FW versions crash if there's a
* lone monitor interface . */
monitor_was_enabled = ar - > monitor_enabled ;
if ( ar - > monitor_enabled )
ath10k_monitor_stop ( ar ) ;
list_for_each_entry ( arvif , & ar - > arvifs , list ) {
if ( ! arvif - > is_started )
continue ;
if ( arvif - > vdev_type = = WMI_VDEV_TYPE_MONITOR )
continue ;
ret = ath10k_vdev_stop ( arvif ) ;
if ( ret ) {
ath10k_warn ( " could not stop vdev %d (%d) \n " ,
arvif - > vdev_id , ret ) ;
continue ;
}
}
/* all vdevs are now stopped - now attempt to restart them */
list_for_each_entry ( arvif , & ar - > arvifs , list ) {
if ( ! arvif - > is_started )
continue ;
if ( arvif - > vdev_type = = WMI_VDEV_TYPE_MONITOR )
continue ;
ret = ath10k_vdev_start ( arvif ) ;
if ( ret ) {
ath10k_warn ( " could not start vdev %d (%d) \n " ,
arvif - > vdev_id , ret ) ;
continue ;
}
if ( ! arvif - > is_up )
continue ;
ret = ath10k_wmi_vdev_up ( arvif - > ar , arvif - > vdev_id , arvif - > aid ,
arvif - > bssid ) ;
if ( ret ) {
ath10k_warn ( " could not bring vdev up %d (%d) \n " ,
arvif - > vdev_id , ret ) ;
continue ;
}
}
if ( monitor_was_enabled )
ath10k_monitor_start ( ar , ar - > monitor_vdev_id ) ;
}
static int ath10k_config ( struct ieee80211_hw * hw , u32 changed )
{
struct ath10k * ar = hw - > priv ;
@ -2221,6 +2333,11 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
spin_unlock_bh ( & ar - > data_lock ) ;
ath10k_config_radar_detection ( ar ) ;
if ( ! cfg80211_chandef_identical ( & ar - > chandef , & conf - > chandef ) ) {
ar - > chandef = conf - > chandef ;
ath10k_config_chan ( ar ) ;
}
}
if ( changed & IEEE80211_CONF_CHANGE_POWER ) {
@ -2615,15 +2732,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
* this is never erased as we it for crypto key
* clearing ; this is FW requirement
*/
memcpy ( arvif - > u . sta . bssid , info - > bssid ,
ETH_ALEN ) ;
memcpy ( arvif - > bssid , info - > bssid , ETH_ALEN ) ;
ath10k_dbg ( ATH10K_DBG_MAC ,
" mac vdev %d start %pM \n " ,
arvif - > vdev_id , info - > bssid ) ;
/* FIXME: check return value */
ret = ath10k_vdev_start ( arvif ) ;
if ( ret ) {
ath10k_warn ( " failed to start vdev: %d \n " ,
ret ) ;
return ;
}
arvif - > is_started = true ;
}
/*
@ -2632,7 +2754,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
* IBSS in order to remove BSSID peer .
*/
if ( vif - > type = = NL80211_IFTYPE_ADHOC )
memcpy ( arvif - > u . ibss . bssid , info - > bssid ,
memcpy ( arvif - > bssid , info - > bssid ,
ETH_ALEN ) ;
}
}