ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to synchronize setup for monitor vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize setup for monitor vdev %i start: %d\n",
vdev_id, ret);
return ret;
}
ret = ath10k_vdev_setup_sync(ar);
if (ret)
- ath10k_warn(ar, "failed to synchronise monitor vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize monitor vdev %i stop: %d\n",
ar->monitor_vdev_id, ret);
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %i stopped\n",
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to synchronise setup for vdev %i: %d\n",
- arg.vdev_id, ret);
+ ath10k_warn(ar,
+ "failed to synchronize setup for vdev %i restart %d: %d\n",
+ arg.vdev_id, restart, ret);
return ret;
}
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to syncronise setup for vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize setup for vdev %i stop: %d\n",
arvif->vdev_id, ret);
return ret;
}
if (is_zero_ether_addr(arvif->bssid))
return;
- memset(arvif->bssid, 0, ETH_ALEN);
+ eth_zero_addr(arvif->bssid);
return;
}
return 0;
}
+ static int ath10k_mac_ps_vif_count(struct ath10k *ar)
+ {
+ struct ath10k_vif *arvif;
+ int num = 0;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ list_for_each_entry(arvif, &ar->arvifs, list)
+ if (arvif->ps)
+ num++;
+
+ return num;
+ }
+
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
enum wmi_sta_ps_mode psmode;
int ret;
int ps_timeout;
+ bool enable_ps;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;
- if (vif->bss_conf.ps) {
+ enable_ps = arvif->ps;
+
+ if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 &&
+ !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
+ ar->fw_features)) {
+ ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
+ arvif->vdev_id);
+ enable_ps = false;
+ }
+
+ if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
ath10k_smps_map[smps]);
}
+ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta_vht_cap vht_cap)
+ {
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ int ret;
+ u32 param;
+ u32 value;
+
+ if (!(ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
+ return 0;
+
+ param = ar->wmi.vdev_param->txbf;
+ value = 0;
+
+ if (WARN_ON(param == WMI_VDEV_PARAM_UNSUPPORTED))
+ return 0;
+
+ /* The following logic is correct. If a remote STA advertises support
+ * for being a beamformer then we should enable us being a beamformee.
+ */
+
+ if (ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
+ if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
+
+ if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
+ }
+
+ if (ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
+ if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
+
+ if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
+ }
+
+ if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFEE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
+
+ if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFER)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
+
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath10k_warn(ar, "failed to submit vdev param txbf 0x%x: %d\n",
+ value, ret);
+ return ret;
+ }
+
+ return 0;
+ }
+
/* can be called only in mac80211 callbacks due to `key_count` usage */
static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
struct wmi_peer_assoc_complete_arg peer_arg;
struct ieee80211_sta *ap_sta;
int ret;
/* ap_sta must be accessed only within rcu section which must be left
* before calling ath10k_setup_peer_smps() which might sleep. */
ht_cap = ap_sta->ht_cap;
+ vht_cap = ap_sta->vht_cap;
ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
if (ret) {
return;
}
+ ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc txbf for vdev %i on bss %pM: %d\n",
+ arvif->vdev_id, bss_conf->bssid, ret);
+ return;
+ }
+
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
}
arvif->is_up = true;
+
+ /* Workaround: Some firmware revisions (tested with qca6174
+ * WLAN.RM.2.0-00073) have buggy powersave state machine and must be
+ * poked with peer param command.
+ */
+ ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
+ WMI_PEER_DUMMY_VAR, 1);
+ if (ret) {
+ ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
+ arvif->bssid, arvif->vdev_id, ret);
+ return;
+ }
}
static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ieee80211_sta_vht_cap vht_cap = {};
int ret;
lockdep_assert_held(&ar->conf_mutex);
arvif->def_wep_key_idx = -1;
+ ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc txbf for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return;
+ }
+
arvif->is_up = false;
}
return -ETIMEDOUT;
}
+ /* If we failed to start the scan, return error code at
+ * this point. This is probably due to some issue in the
+ * firmware, but no need to wedge the driver due to that...
+ */
+ spin_lock_bh(&ar->data_lock);
+ if (ar->scan.state == ATH10K_SCAN_IDLE) {
+ spin_unlock_bh(&ar->data_lock);
+ return -EINVAL;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
/* Add a 200ms margin to account for event/command processing */
ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
msecs_to_jiffies(arg->max_scan_time+200));
list_del(&arvif->list);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr);
+ ret = ath10k_wmi_peer_delete(arvif->ar, arvif->vdev_id,
+ vif->addr);
if (ret)
- ath10k_warn(ar, "failed to remove peer for AP vdev %i: %d\n",
+ ath10k_warn(ar, "failed to submit AP self-peer removal on vdev %i: %d\n",
arvif->vdev_id, ret);
kfree(arvif->u.ap.noa_data);
ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n",
arvif->vdev_id, ret);
+ /* Some firmware revisions don't notify host about self-peer removal
+ * until after associated vdev is deleted.
+ */
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ ret = ath10k_wait_for_peer_deleted(ar, arvif->vdev_id,
+ vif->addr);
+ if (ret)
+ ath10k_warn(ar, "failed to remove AP self-peer on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->num_peers--;
+ spin_unlock_bh(&ar->data_lock);
+ }
+
ath10k_peer_cleanup(ar, arvif->vdev_id);
mutex_unlock(&ar->conf_mutex);
}
if (changed & BSS_CHANGED_PS) {
- ret = ath10k_mac_vif_setup_ps(arvif);
+ arvif->ps = vif->bss_conf.ps;
+
+ ret = ath10k_config_ps(ar);
if (ret)
ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
arvif->vdev_id, ret);
* BSSID mask when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
- memset(&iter_data->mask, 0xff, ETH_ALEN);
+ eth_broadcast_addr(iter_data->mask);
iter_data->slottime = ATH9K_SLOT_TIME_9;
list_for_each_entry(avp, &ctx->vifs, list)
ctx->primary_sta = iter_data.primary_sta;
} else {
ctx->primary_sta = NULL;
- memset(common->curbssid, 0, ETH_ALEN);
+ eth_zero_addr(common->curbssid);
common->curaid = 0;
ath9k_hw_write_associd(sc->sc_ah);
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
ath9k_ps_restore(sc);
}
+ static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+ {
+ int *power = (int *)data;
+
+ if (*power < vif->bss_conf.txpower)
+ *power = vif->bss_conf.txpower;
+ }
+
+ /* Called with sc->mutex held. */
+ void ath9k_set_txpower(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+ int power;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+ ath9k_ps_wakeup(sc);
+ if (ah->tpc_enabled) {
+ power = (vif) ? vif->bss_conf.txpower : -1;
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_tpc_vif_iter, &power);
+ if (power == -1)
+ power = sc->hw->conf.power_level;
+ } else {
+ power = sc->hw->conf.power_level;
+ }
+ sc->cur_chan->txpower = 2 * power;
+ ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+ sc->cur_chan->cur_txpower = reg->max_power_level;
+ ath9k_ps_restore(sc);
+ }
+
static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
ath9k_assign_hw_queues(hw, vif);
+ ath9k_set_txpower(sc, vif);
+
an->sc = sc;
an->sta = NULL;
an->vif = vif;
ath9k_assign_hw_queues(hw, vif);
ath9k_calculate_summary_state(sc, avp->chanctx);
+ ath9k_set_txpower(sc, vif);
+
mutex_unlock(&sc->mutex);
return 0;
}
ath9k_calculate_summary_state(sc, avp->chanctx);
+ ath9k_set_txpower(sc, NULL);
+
mutex_unlock(&sc->mutex);
}
ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
}
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
- ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
- sc->cur_chan->txpower = 2 * conf->power_level;
- ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
- sc->cur_chan->txpower,
- &sc->cur_chan->cur_txpower);
- }
-
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
if (changed & CHECK_ANI)
ath_check_ani(sc);
+ if (changed & BSS_CHANGED_TXPOWER) {
+ ath_dbg(common, CONFIG, "vif %pM power %d dbm power_type %d\n",
+ vif->addr, bss_conf->txpower, bss_conf->txpower_type);
+ ath9k_set_txpower(sc, vif);
+ }
+
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
- memset(wl->bssid, 0, ETH_ALEN);
+ eth_zero_addr(wl->bssid);
}
if (b43_status(dev) >= B43_STAT_INITIALIZED) {
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
- bcma_core_pci_down(dev->dev->bdev->bus);
+ bcma_host_pci_down(dev->dev->bdev->bus);
break;
#endif
#ifdef CONFIG_B43_SSB
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
+ bcma_core_pci_irq_ctl(dev->dev->bdev->bus,
dev->dev->bdev, true);
- bcma_core_pci_up(dev->dev->bdev->bus);
+ bcma_host_pci_up(dev->dev->bdev->bus);
break;
#endif
#ifdef CONFIG_B43_SSB
wl->operating = false;
b43_adjust_opmode(dev);
- memset(wl->mac_addr, 0, ETH_ALEN);
+ eth_zero_addr(wl->mac_addr);
b43_upload_card_macaddress(dev);
mutex_unlock(&wl->mutex);
/* Kill all old instance specific information to make sure
* the card won't use it in the short timeframe between start
* and mac80211 reconfiguring it. */
- memset(wl->bssid, 0, ETH_ALEN);
- memset(wl->mac_addr, 0, ETH_ALEN);
+ eth_zero_addr(wl->bssid);
+ eth_zero_addr(wl->mac_addr);
wl->filter_flags = 0;
wl->radiotap_enabled = false;
b43_qos_clear(wl);
/* Do a scan abort to stop the driver's scan engine */
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
memset(¶ms_le, 0, sizeof(params_le));
- memset(params_le.bssid, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(params_le.bssid);
params_le.bss_type = DOT11_BSSTYPE_ANY;
params_le.scan_type = 0;
params_le.channel_num = cpu_to_le32(1);
char *ptr;
struct brcmf_ssid_le ssid_le;
- memset(params_le->bssid, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(params_le->bssid);
params_le->bss_type = DOT11_BSSTYPE_ANY;
params_le->scan_type = 0;
params_le->channel_num = 0;
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
- /* Arm scan timeout timer */
- mod_timer(&cfg->escan_timeout, jiffies +
- WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
-
escan_req = false;
if (request) {
/* scan bss */
}
}
+ /* Arm scan timeout timer */
+ mod_timer(&cfg->escan_timeout, jiffies +
+ WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
+
return 0;
scan_out:
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
- if (timer_pending(&cfg->escan_timeout))
- del_timer_sync(&cfg->escan_timeout);
cfg->scan_request = NULL;
return err;
}
BRCMF_ASSOC_PARAMS_FIXED_SIZE;
memcpy(profile->bssid, params->bssid, ETH_ALEN);
} else {
- memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
- memset(profile->bssid, 0, ETH_ALEN);
+ eth_broadcast_addr(join_params.params_le.bssid);
+ eth_zero_addr(profile->bssid);
}
/* Channel */
if (sme->bssid)
memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN);
else
- memset(&ext_join_params->assoc_le.bssid, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(ext_join_params->assoc_le.bssid);
if (cfg->channel) {
ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1);
if (sme->bssid)
memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
else
- memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(join_params.params_le.bssid);
if (cfg->channel) {
join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec);
if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
/* we ignore this key index in this case */
- brcmf_err("invalid key index (%d)\n", key_idx);
return -EINVAL;
}
return -EIO;
memcpy(&scbval.ea, params->mac, ETH_ALEN);
- scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
+ scbval.val = cpu_to_le32(params->reason_code);
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
&scbval, sizeof(scbval));
if (err)
wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, params->mac);
- memset(deauth_mac, 0, ETH_ALEN);
+ eth_zero_addr(deauth_mac);
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_node = mwifiex_get_sta_entry(priv, params->mac);
wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
" reason code %d\n", priv->cfg_bssid, reason_code);
- memset(priv->cfg_bssid, 0, ETH_ALEN);
+ eth_zero_addr(priv->cfg_bssid);
priv->hs2_enabled = false;
return 0;
dev_dbg(priv->adapter->dev,
"info: association to bssid %pM failed\n",
priv->cfg_bssid);
- memset(priv->cfg_bssid, 0, ETH_ALEN);
+ eth_zero_addr(priv->cfg_bssid);
if (ret > 0)
cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
if (mwifiex_deauthenticate(priv, NULL))
return -EFAULT;
- memset(priv->cfg_bssid, 0, ETH_ALEN);
+ eth_zero_addr(priv->cfg_bssid);
return 0;
}
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
- #define MWIFIEX_MAX_WQ_LEN 30
/*
* create a new virtual interface with the given name
*/
struct mwifiex_private *priv;
struct net_device *dev;
void *mdev_priv;
- char dfs_cac_str[MWIFIEX_MAX_WQ_LEN], dfs_chsw_str[MWIFIEX_MAX_WQ_LEN];
if (!adapter)
return ERR_PTR(-EFAULT);
return ERR_PTR(-EFAULT);
}
- strcpy(dfs_cac_str, "MWIFIEX_DFS_CAC");
- strcat(dfs_cac_str, name);
- priv->dfs_cac_workqueue = alloc_workqueue(dfs_cac_str,
+ priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1);
+ WQ_UNBOUND, 1, name);
if (!priv->dfs_cac_workqueue) {
wiphy_err(wiphy, "cannot register virtual network device\n");
free_netdev(dev);
INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
- strcpy(dfs_chsw_str, "MWIFIEX_DFS_CHSW");
- strcat(dfs_chsw_str, name);
- priv->dfs_chan_sw_workqueue = alloc_workqueue(dfs_chsw_str,
+ priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ WQ_MEM_RECLAIM, 1, name);
if (!priv->dfs_chan_sw_workqueue) {
wiphy_err(wiphy, "cannot register virtual network device\n");
free_netdev(dev);
u32 i;
priv->media_connected = false;
- memset(priv->curr_addr, 0xff, ETH_ALEN);
+ eth_broadcast_addr(priv->curr_addr);
priv->pkt_tx_ctrl = 0;
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
adapter->arp_filter_size = 0;
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
- adapter->ext_scan = false;
adapter->key_api_major_ver = 0;
adapter->key_api_minor_ver = 0;
- memset(adapter->perm_addr, 0xff, ETH_ALEN);
+ eth_broadcast_addr(adapter->perm_addr);
adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;