Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe6b23dd authored by Reinette Chatre's avatar Reinette Chatre
Browse files

iwlwifi: implement new mac80211 station add/remove calls



mac80211 recently implemented two new callbacks that are used to request
station add/remove from the driver. The benefot from these new callbacks
are that they enable the driver to sleep while performing this work.

This is a big patch since a few things need to be coordinated in this move.
First we need to decouple station management from rate scaling, which
caused a lot of code to be moved and/or deleted. Next we needed to tie in
with mac80211's station management callback and let it direct our station
management as well as trigger the rate scaling initialization.

Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
parent 7e246191
Loading
Loading
Loading
Loading
+52 −31
Original line number Diff line number Diff line
@@ -329,16 +329,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,

}

static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
			 struct ieee80211_sta *sta, void *priv_sta)
/*
 * Called after adding a new station to initialize rate scaling
 */
void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
{
	struct iwl3945_rs_sta *rs_sta = priv_sta;
	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
	struct ieee80211_hw *hw = priv->hw;
	struct ieee80211_conf *conf = &priv->hw->conf;
	struct iwl3945_sta_priv *psta;
	struct iwl3945_rs_sta *rs_sta;
	struct ieee80211_supported_band *sband;
	int i;

	IWL_DEBUG_RATE(priv, "enter\n");
	IWL_DEBUG_INFO(priv, "enter \n");
	if (sta_id == priv->hw_params.bcast_sta_id)
		goto out;

	spin_lock_init(&rs_sta->lock);
	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
	rs_sta = &psta->rs_sta;
	sband = hw->wiphy->bands[conf->channel->band];

	rs_sta->priv = priv;

@@ -351,9 +360,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
	rs_sta->last_flush = jiffies;
	rs_sta->flush_time = IWL_RATE_FLUSH;
	rs_sta->last_tx_packets = 0;
	rs_sta->ibss_sta_added = 0;

	init_timer(&rs_sta->rate_scale_flush);
	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
	rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;

@@ -380,8 +387,10 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
						IWL_FIRST_OFDM_RATE;
	}

out:
	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;

	IWL_DEBUG_RATE(priv, "leave\n");
	IWL_DEBUG_INFO(priv, "leave\n");
}

static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
@@ -405,6 +414,9 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)

	rs_sta = &psta->rs_sta;

	spin_lock_init(&rs_sta->lock);
	init_timer(&rs_sta->rate_scale_flush);

	IWL_DEBUG_RATE(priv, "leave\n");

	return rs_sta;
@@ -413,13 +425,14 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
			void *priv_sta)
{
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
	struct iwl3945_rs_sta *rs_sta = &psta->rs_sta;
	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
	struct iwl3945_rs_sta *rs_sta = priv_sta;

	IWL_DEBUG_RATE(priv, "enter\n");
	/*
	 * Be careful not to use any members of iwl3945_rs_sta (like trying
	 * to use iwl_priv to print out debugging) since it may not be fully
	 * initialized at this point.
	 */
	del_timer_sync(&rs_sta->rate_scale_flush);
	IWL_DEBUG_RATE(priv, "leave\n");
}


@@ -458,6 +471,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
		return;
	}

	/* Treat uninitialized rate scaling data same as non-existing. */
	if (!rs_sta->priv) {
		IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
		return;
	}


	rs_sta->tx_packets++;

	scale_rate_index = first_index;
@@ -625,7 +645,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
	u32 fail_count;
	s8 scale_action = 0;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
	s8 max_rate_idx = -1;
	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
@@ -633,6 +652,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,

	IWL_DEBUG_RATE(priv, "enter\n");

	/* Treat uninitialized rate scaling data same as non-existing. */
	if (rs_sta && !rs_sta->priv) {
		IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
		priv_sta = NULL;
	}

	if (rate_control_send_low(sta, priv_sta, txrc))
		return;

@@ -650,20 +675,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
	if (sband->band == IEEE80211_BAND_5GHZ)
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;

	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
	    !rs_sta->ibss_sta_added) {
		u8 sta_id = iwl_find_station(priv, hdr->addr1);

		if (sta_id == IWL_INVALID_STATION) {
			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
				       hdr->addr1);
			sta_id = iwl_add_station(priv, hdr->addr1, false,
				CMD_ASYNC, NULL);
		}
		if (sta_id != IWL_INVALID_STATION)
			rs_sta->ibss_sta_added = 1;
	}

	spin_lock_irqsave(&rs_sta->lock, flags);

	/* for recent assoc, choose best rate regarding
@@ -883,12 +894,22 @@ static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
}
#endif

/*
 * Initialization of rate scaling information is done by driver after
 * the station is added. Since mac80211 calls this function before a
 * station is added we ignore it.
 */
static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
			      struct ieee80211_sta *sta, void *priv_sta)
{
}

static struct rate_control_ops rs_ops = {
	.module = NULL,
	.name = RS_NAME,
	.tx_status = rs_tx_status,
	.get_rate = rs_get_rate,
	.rate_init = rs_rate_init,
	.rate_init = rs_rate_init_stub,
	.alloc = rs_alloc,
	.free = rs_free,
	.alloc_sta = rs_alloc_sta,
@@ -899,7 +920,6 @@ static struct rate_control_ops rs_ops = {
#endif

};

void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
	struct iwl_priv *priv = hw->priv;
@@ -916,6 +936,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
	sta = ieee80211_find_sta(priv->vif,
				 priv->stations[sta_id].sta.sta.addr);
	if (!sta) {
		IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
		rcu_read_unlock();
		return;
	}
+0 −10
Original line number Diff line number Diff line
@@ -1956,16 +1956,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
		return rc;
	}

	/* If we have set the ASSOC_MSK and we are in BSS mode then
	 * add the IWL_AP_ID to the station rate table */
	if (iwl_is_associated(priv) &&
	    (priv->iw_mode == NL80211_IFTYPE_STATION))
		if (iwl_add_station(priv, priv->active_rxon.bssid_addr,
				true, CMD_SYNC, NULL) == IWL_INVALID_STATION) {
			IWL_ERR(priv, "Error adding AP address for transmit\n");
			return -EIO;
		}

	/* Init the hardware's rate fallback order based on the band */
	rc = iwl3945_init_hw_rate_table(priv);
	if (rc) {
+0 −1
Original line number Diff line number Diff line
@@ -95,7 +95,6 @@ struct iwl3945_rs_sta {
	u8 tgg;
	u8 flush_pending;
	u8 start_rate;
	u8 ibss_sta_added;
	struct timer_list rate_scale_flush;
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
#ifdef CONFIG_MAC80211_DEBUGFS
+61 −59
Original line number Diff line number Diff line
@@ -769,6 +769,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,

	IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");

	/* Treat uninitialized rate scaling data same as non-existing. */
	if (!lq_sta) {
		IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n");
		return;
	} else if (!lq_sta->drv) {
		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
		return;
	}

	if (!ieee80211_is_data(hdr->frame_control) ||
	    info->flags & IEEE80211_TX_CTL_NO_ACK)
		return;
@@ -778,10 +787,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
		return;

	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
	    !lq_sta->ibss_sta_added)
		return;

	/*
	 * Ignore this Tx frame response if its initial rate doesn't match
	 * that of latest Link Quality command.  There may be stragglers
@@ -827,7 +832,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
		lq_sta->missed_rate_counter++;
		if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
			lq_sta->missed_rate_counter = 0;
			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
		}
		/* Regardless, ignore this status info for outdated rate */
		return;
@@ -1915,7 +1920,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
	/* Update uCode's rate table. */
	rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
	rs_fill_link_cmd(priv, lq_sta, rate);
	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);

	return rate;
}
@@ -2291,7 +2296,7 @@ lq_update:
			IWL_DEBUG_RATE(priv, "Switch current  mcs: %X index: %d\n",
				     tbl->current_rate, index);
			rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
		} else
			done_search = 1;
	}
@@ -2340,7 +2345,20 @@ out:
	return;
}


/**
 * rs_initialize_lq - Initialize a station's hardware rate table
 *
 * The uCode's station table contains a table of fallback rates
 * for automatic fallback during transmission.
 *
 * NOTE: This sets up a default set of values.  These will be replaced later
 *       if the driver's iwl-agn-rs rate scaling algorithm is used, instead of
 *       rc80211_simple.
 *
 * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
 *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
 *       which requires station table entry to exist).
 */
static void rs_initialize_lq(struct iwl_priv *priv,
			     struct ieee80211_conf *conf,
			     struct ieee80211_sta *sta,
@@ -2390,7 +2408,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
	tbl->current_rate = rate;
	rs_set_expected_tpt_table(lq_sta, tbl);
	rs_fill_link_cmd(NULL, lq_sta, rate);
	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
	priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true);
 out:
	return;
}
@@ -2402,9 +2421,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
	struct sk_buff *skb = txrc->skb;
	struct ieee80211_supported_band *sband = txrc->sband;
	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
	struct ieee80211_conf *conf = &priv->hw->conf;
	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct iwl_lq_sta *lq_sta = priv_sta;
	int rate_idx;
@@ -2422,30 +2438,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
			lq_sta->max_rate_idx = -1;
	}

	/* Treat uninitialized rate scaling data same as non-existing. */
	if (lq_sta && !lq_sta->drv) {
		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
		priv_sta = NULL;
	}

	/* Send management frames and NO_ACK data using lowest rate. */
	if (rate_control_send_low(sta, priv_sta, txrc))
		return;

	rate_idx  = lq_sta->last_txrate_idx;

	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
	    !lq_sta->ibss_sta_added) {
		u8 sta_id = iwl_find_station(priv, hdr->addr1);

		if (sta_id == IWL_INVALID_STATION) {
			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
				       hdr->addr1);
			sta_id = iwl_add_station(priv, hdr->addr1,
						false, CMD_ASYNC, ht_cap);
		}
		if ((sta_id != IWL_INVALID_STATION)) {
			lq_sta->lq.sta_id = sta_id;
			lq_sta->lq.rs_table[0].rate_n_flags = 0;
			lq_sta->ibss_sta_added = 1;
			rs_initialize_lq(priv, conf, sta, lq_sta);
		}
	}

	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
		rate_idx -= IWL_FIRST_OFDM_RATE;
		/* 6M and 9M shared same MCS index */
@@ -2495,16 +2499,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
	return lq_sta;
}

static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
			 struct ieee80211_sta *sta, void *priv_sta)
/*
 * Called after adding a new station to initialize rate scaling
 */
void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
{
	int i, j;
	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
	struct ieee80211_hw *hw = priv->hw;
	struct ieee80211_conf *conf = &priv->hw->conf;
	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
	struct iwl_lq_sta *lq_sta = priv_sta;
	struct iwl_station_priv *sta_priv;
	struct iwl_lq_sta *lq_sta;
	struct ieee80211_supported_band *sband;

	sta_priv = (struct iwl_station_priv *) sta->drv_priv;
	lq_sta = &sta_priv->lq_sta;
	sband = hw->wiphy->bands[conf->channel->band];

	lq_sta->lq.sta_id = 0xff;

	lq_sta->lq.sta_id = sta_id;

	for (j = 0; j < LQ_SIZE; j++)
		for (i = 0; i < IWL_RATE_COUNT; i++)
@@ -2516,33 +2529,13 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
		for (i = 0; i < IWL_RATE_COUNT; i++)
			rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);

	IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n");
	IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n",
		       sta_id);
	/* TODO: what is a good starting rate for STA? About middle? Maybe not
	 * the lowest or the highest rate.. Could consider using RSSI from
	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
	 * after assoc.. */

	lq_sta->ibss_sta_added = 0;
	if (priv->iw_mode == NL80211_IFTYPE_AP) {
		u8 sta_id = iwl_find_station(priv,
								sta->addr);

		/* for IBSS the call are from tasklet */
		IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);

		if (sta_id == IWL_INVALID_STATION) {
			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
			sta_id = iwl_add_station(priv, sta->addr, false,
						CMD_ASYNC, ht_cap);
		}
		if ((sta_id != IWL_INVALID_STATION)) {
			lq_sta->lq.sta_id = sta_id;
			lq_sta->lq.rs_table[0].rate_n_flags = 0;
		}
		/* FIXME: this is w/a remove it later */
		priv->assoc_station_added = 1;
	}

	lq_sta->is_dup = 0;
	lq_sta->max_rate_idx = -1;
	lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
@@ -2795,7 +2788,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,

	if (lq_sta->dbg_fixed_rate) {
		rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
		iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
		iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
	}

	return count;
@@ -2992,12 +2985,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
}
#endif

/*
 * Initialization of rate scaling information is done by driver after
 * the station is added. Since mac80211 calls this function before a
 * station is added we ignore it.
 */
static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
			 struct ieee80211_sta *sta, void *priv_sta)
{
}
static struct rate_control_ops rs_ops = {
	.module = NULL,
	.name = RS_NAME,
	.tx_status = rs_tx_status,
	.get_rate = rs_get_rate,
	.rate_init = rs_rate_init,
	.rate_init = rs_rate_init_stub,
	.alloc = rs_alloc,
	.free = rs_free,
	.alloc_sta = rs_alloc_sta,
+6 −1
Original line number Diff line number Diff line
@@ -403,7 +403,6 @@ struct iwl_lq_sta {
	u8 is_green;
	u8 is_dup;
	enum ieee80211_band band;
	u8 ibss_sta_added;

	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
	u32 supp_rates;
@@ -478,6 +477,12 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
 */
extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);

/* Initialize station's rate scaling information after adding station */
extern void iwl_rs_rate_init(struct iwl_priv *priv,
			     struct ieee80211_sta *sta, u8 sta_id);
extern void iwl3945_rs_rate_init(struct iwl_priv *priv,
				 struct ieee80211_sta *sta, u8 sta_id);

/**
 * iwl_rate_control_register - Register the rate control algorithm callbacks
 *
Loading