static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add)
{
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
int ret;
- /*
- * NB: this assumes that the station it gets will be
- * IWL_STA_ID, which will happen but isn't obvious.
- */
-
if (add) {
- ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false);
+ ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false,
+ &vif_priv->ibss_bssid_sta_id);
if (ret)
return ret;
- iwl3945_sync_sta(priv, IWL_STA_ID,
+ iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
(priv->band == IEEE80211_BAND_5GHZ) ?
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
CMD_ASYNC);
- iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
+ iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
return 0;
}
- return iwl_remove_station(priv, vif->bss_conf.bssid);
+ return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+ vif->bss_conf.bssid);
}
/**
};
+/*
+ * The common struct MUST be first because it is shared between
+ * 3945 and agn!
+ */
struct iwl3945_sta_priv {
+ struct iwl_station_priv_common common;
struct iwl3945_rs_sta rs_sta;
};
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add)
{
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
if (add)
- return iwl_add_local_station(priv, vif->bss_conf.bssid, true);
- return iwl_remove_station(priv, vif->bss_conf.bssid);
+ return iwl_add_local_station(priv, vif->bss_conf.bssid, true,
+ &vif_priv->ibss_bssid_sta_id);
+ return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+ vif->bss_conf.bssid);
}
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
hw->sta_data_size = sizeof(struct iwl_station_priv);
+ hw->vif_data_size = sizeof(struct iwl_vif_priv);
+
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
int ret;
u8 sta_id;
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
return ret;
}
+ sta_priv->common.sta_id = sta_id;
+
/* Initialize rate scaling */
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id);
- return ret;
+ return 0;
}
/*****************************************************************************
struct iwl_link_quality_cmd *lq;
};
+struct iwl_station_priv_common {
+ u8 sta_id;
+};
+
/*
* iwl_station_priv: Driver's private station information
*
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
* in the structure for use by driver. This structure is places in that
* space.
+ *
+ * The common struct MUST be first because it is shared between
+ * 3945 and agn!
*/
struct iwl_station_priv {
+ struct iwl_station_priv_common common;
struct iwl_lq_sta lq_sta;
atomic_t pending_frames;
bool client;
bool asleep;
};
+/**
+ * struct iwl_vif_priv - driver's private per-interface information
+ *
+ * When mac80211 allocates a virtual interface, it can allocate
+ * space for us to put data into.
+ */
+struct iwl_vif_priv {
+ u8 ibss_bssid_sta_id;
+};
+
/* one for each uCode image (inst/data, boot/init/runtime) */
struct fw_desc {
void *v_addr; /* access by driver */
}
/*
- * iwl_add_local_stations - Add stations not requested by mac80211
+ * iwl_add_local_station - Add stations not requested by mac80211
*
* This will be either the broadcast station or the bssid station needed by
* ad-hoc.
*
* Function sleeps.
*/
-int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs)
+int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
+ u8 *sta_id_r)
{
int ret;
u8 sta_id;
struct iwl_link_quality_cmd *link_cmd;
unsigned long flags;
+ if (*sta_id_r)
+ *sta_id_r = IWL_INVALID_STATION;
+
ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
if (ret) {
IWL_ERR(priv, "Unable to add station %pM\n", addr);
return ret;
}
+ if (sta_id_r)
+ *sta_id_r = sta_id;
+
spin_lock_irqsave(&priv->sta_lock, flags);
priv->stations[sta_id].used |= IWL_STA_LOCAL;
spin_unlock_irqrestore(&priv->sta_lock, flags);
/**
* iwl_remove_station - Remove driver's knowledge of station.
*/
-int iwl_remove_station(struct iwl_priv *priv, const u8 *addr)
+int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr)
{
- int sta_id = IWL_INVALID_STATION;
- int i, ret = -EINVAL;
- unsigned long flags;
- bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
struct iwl_station_entry *station;
+ unsigned long flags;
if (!iwl_is_ready(priv)) {
IWL_DEBUG_INFO(priv,
return 0;
}
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- if (is_ap)
- sta_id = IWL_AP_ID;
- else
- for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
- if (priv->stations[i].used &&
- !compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
- sta_id = i;
- break;
- }
+ IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n",
+ sta_id, addr);
- if (unlikely(sta_id == IWL_INVALID_STATION))
- goto out;
+ if (WARN_ON(sta_id == IWL_INVALID_STATION))
+ return -EINVAL;
- IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n",
- sta_id, addr);
+ spin_lock_irqsave(&priv->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
addr);
- goto out;
+ goto out_err;
}
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
addr);
- goto out;
+ goto out_err;
}
if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
station = &priv->stations[sta_id];
spin_unlock_irqrestore(&priv->sta_lock, flags);
- ret = iwl_send_remove_station(priv, station);
- return ret;
-out:
+ return iwl_send_remove_station(priv, station);
+out_err:
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return ret;
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(iwl_remove_station);
EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
int iwl_mac_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
- int ret;
struct iwl_priv *priv = hw->priv;
+ struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
+ int ret;
+
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
sta->addr);
- ret = iwl_remove_station(priv, sta->addr);
+ ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
if (ret)
IWL_ERR(priv, "Error removing station %pM\n",
sta->addr);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags);
-int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs);
+int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
+ u8 *sta_id_r);
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
bool is_ap,
struct ieee80211_sta_ht_cap *ht_info,
u8 *sta_id_r);
-int iwl_remove_station(struct iwl_priv *priv, const u8 *addr);
+int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr);
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
struct ieee80211_sta *sta)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
int ret;
- bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
+ bool is_ap = vif->type == NL80211_IFTYPE_STATION;
u8 sta_id;
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
return ret;
}
+ sta_priv->common.sta_id = sta_id;
+
/* Initialize rate scaling */
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl3945_rs_rate_init(priv, sta, sta_id);
return 0;
-
-
-
- return ret;
}
/*****************************************************************************
*
hw->rate_control_algorithm = "iwl-3945-rs";
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+ hw->vif_data_size = sizeof(struct iwl_vif_priv);
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |