@@ -888,6 +888,7 @@ enum set_key_cmd {
* or you must take good care to not use such a pointer after a
* call to your sta_remove callback that removed it.
*
+ * @channel: the channel this sta belongs to
* @addr: MAC address
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
@@ -896,6 +897,7 @@ enum set_key_cmd {
* sizeof(void *), size is determined in hw information.
*/
struct ieee80211_sta {
+ struct ieee80211_channel *channel;
u32 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN];
u16 aid;
@@ -584,7 +584,14 @@ static void sta_apply_parameters(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata = sta->sdata;
u32 mask, set;
+ /*
+ * TODO: userspace should pass the band, there is no
+ * guarantee userspace will have sent this in synch with
+ * the STA's own same band. For now we assume the currently
+ * operating channel is on the STA's own band and channel.
+ */
sband = local->hw.wiphy->bands[local->oper_channel->band];
+ sta->sta.channel = local->oper_channel;
spin_lock_irqsave(&sta->flaglock, flags);
mask = params->sta_flags_mask;
@@ -414,6 +414,8 @@ void debugfs_hw_add(struct ieee80211_local *local)
local->tx_handlers_drop_wep);
DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc,
local->tx_handlers_drop_not_assoc);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_wrong_channel,
+ local->tx_handlers_drop_wrong_channel);
DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port,
local->tx_handlers_drop_unauth_port);
DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop);
@@ -854,6 +854,7 @@ struct ieee80211_local {
unsigned int tx_handlers_drop_fragment;
unsigned int tx_handlers_drop_wep;
unsigned int tx_handlers_drop_not_assoc;
+ unsigned int tx_handlers_drop_wrong_channel;
unsigned int tx_handlers_drop_unauth_port;
unsigned int rx_handlers_drop;
unsigned int rx_handlers_queued;
@@ -1174,6 +1174,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->skb = skb;
tx->local = local;
tx->sdata = sdata;
+ /*
+ * TODO: This should use tx->sta->sta.channel once we can
+ * actually rely on the information being accurate.
+ */
tx->channel = local->hw.conf.channel;
/*
* Set this flag (used below to indicate "automatic fragmentation"),
@@ -1213,6 +1217,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
if (!tx->sta)
tx->sta = sta_info_get(sdata, hdr->addr1);
+ if (tx->sta && tx->sta->sta.channel &&
+ tx->sta->sta.channel->center_freq != tx->channel->center_freq) {
+ I802_DEBUG_INC(local->tx_handlers_drop_wrong_channel);
+ return TX_DROP;
+ }
+
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
struct tid_ampdu_tx *tid_tx;