static int ath9k_htc_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_vif *avp = (void *)vif->drv_priv; struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_vif hvif; int ret = 0; u8 cmd_rsp; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); switch (vif->type) { case NL80211_IFTYPE_STATION: hvif.opmode = HTC_M_STA; break; case NL80211_IFTYPE_ADHOC: hvif.opmode = HTC_M_IBSS; break; case NL80211_IFTYPE_AP: hvif.opmode = HTC_M_HOSTAP; break; case NL80211_IFTYPE_MESH_POINT: hvif.opmode = HTC_M_WDS; /* close enough */ break; default: ath_err(common, "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } /* Index starts from zero on the target */ avp->index = hvif.index = ffz(priv->vif_slot); hvif.rtsthreshold = cpu_to_be16(2304); WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); if (ret) goto out; /* * We need a node in target to tx mgmt frames * before association. */ ret = ath9k_htc_add_station(priv, vif, NULL); if (ret) { WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); goto out; } ath9k_htc_set_mac_bssid_mask(priv, vif); priv->vif_slot |= (1 << avp->index); priv->nvifs++; INC_VIF(priv, vif->type); if ((vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_MESH_POINT) || (vif->type == NL80211_IFTYPE_ADHOC)) ath9k_htc_assign_bslot(priv, vif); ath9k_htc_set_opmode(priv); if ((priv->ah->opmode == NL80211_IFTYPE_AP) && !test_bit(ATH_OP_ANI_RUN, &common->op_flags)) { ath9k_hw_set_tsfadjust(priv->ah, true); ath9k_htc_start_ani(priv); } ath_dbg(common, CONFIG, "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); out: ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; }
static int ath9k_htc_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_vif *avp = (void *)vif->drv_priv; struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_vif hvif; int ret = 0; u8 cmd_rsp; mutex_lock(&priv->mutex); if (priv->nvifs >= ATH9K_HTC_MAX_VIF) { mutex_unlock(&priv->mutex); return -ENOBUFS; } if (priv->num_ibss_vif || (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { ath_err(common, "IBSS coexistence with other modes is not allowed\n"); mutex_unlock(&priv->mutex); return -ENOBUFS; } if (((vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_ADHOC)) && ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) { ath_err(common, "Max. number of beaconing interfaces reached\n"); mutex_unlock(&priv->mutex); return -ENOBUFS; } ath9k_htc_ps_wakeup(priv); memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); switch (vif->type) { case NL80211_IFTYPE_STATION: hvif.opmode = HTC_M_STA; break; case NL80211_IFTYPE_ADHOC: hvif.opmode = HTC_M_IBSS; break; case NL80211_IFTYPE_AP: hvif.opmode = HTC_M_HOSTAP; break; default: ath_err(common, "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } /* Index starts from zero on the target */ avp->index = hvif.index = ffz(priv->vif_slot); hvif.rtsthreshold = cpu_to_be16(2304); WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); if (ret) goto out; /* * We need a node in target to tx mgmt frames * before association. */ ret = ath9k_htc_add_station(priv, vif, NULL); if (ret) { WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); goto out; } ath9k_htc_set_mac_bssid_mask(priv, vif); priv->vif_slot |= (1 << avp->index); priv->nvifs++; INC_VIF(priv, vif->type); if ((vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_ADHOC)) ath9k_htc_assign_bslot(priv, vif); ath9k_htc_set_opmode(priv); if ((priv->ah->opmode == NL80211_IFTYPE_AP) && !(priv->op_flags & OP_ANI_RUNNING)) { ath9k_hw_set_tsfadjust(priv->ah, 1); ath9k_htc_start_ani(priv); } ath_dbg(common, CONFIG, "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); out: ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; }