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

Commit dfa2bdba authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by John W. Linville
Browse files

iwlagn: upper layer uses slabs to allocate tx cmds



In a near future, the upper layer won't be aware of the tx queues.
This allows to remove one place where the upper layer needed to
provide the tx queue index to the transport layer.
This also saves around 1.5MB.

Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ba562f71
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct iwl_station_priv *sta_priv = NULL;
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
	struct iwl_device_cmd *dev_cmd = NULL;
	struct iwl_tx_cmd *tx_cmd;
	int txq_id;

@@ -386,10 +387,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
		}
	}

	tx_cmd = iwl_trans_get_tx_cmd(trans(priv), txq_id);
	if (unlikely(!tx_cmd))
	dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);

	if (unlikely(!dev_cmd))
		goto drop_unlock_sta;

	memset(dev_cmd, 0, sizeof(*dev_cmd));
	tx_cmd = &dev_cmd->cmd.tx;

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, hdr_len);

@@ -409,8 +414,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
	iwl_update_stats(priv, true, fc, len);

	info->driver_data[0] = ctx;
	info->driver_data[1] = dev_cmd;

	if (iwl_trans_tx(trans(priv), skb, tx_cmd, txq_id, fc, is_agg))
	if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id, fc, is_agg))
		goto drop_unlock_sta;

	if (ieee80211_is_data_qos(fc)) {
@@ -436,6 +442,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
	return 0;

drop_unlock_sta:
	if (dev_cmd)
		kmem_cache_free(priv->tx_cmd_pool, dev_cmd);
	spin_unlock(&priv->shrd->sta_lock);
drop_unlock_priv:
	spin_unlock_irqrestore(&priv->shrd->lock, flags);
@@ -1010,6 +1018,8 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)

			info = IEEE80211_SKB_CB(skb);
			ctx = info->driver_data[0];
			kmem_cache_free(priv->tx_cmd_pool,
					(info->driver_data[1]));

			memset(&info->status, 0, sizeof(info->status));

@@ -1184,6 +1194,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
						    info);
		}

		info = IEEE80211_SKB_CB(skb);
		kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));

		ieee80211_tx_status_irqsafe(priv->hw, skb);
	}

+9 −0
Original line number Diff line number Diff line
@@ -351,6 +351,15 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
{
	int ret;

	if (!priv->tx_cmd_pool)
		priv->tx_cmd_pool =
			kmem_cache_create("iwlagn_dev_cmd",
					  sizeof(struct iwl_device_cmd),
					  sizeof(void *), 0, NULL);

	if (!priv->tx_cmd_pool)
		return -ENOMEM;

	iwl_trans_tx_start(trans(priv));

	ret = iwlagn_send_wimax_coex(priv);
+2 −0
Original line number Diff line number Diff line
@@ -3124,6 +3124,8 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
	iwl_calib_free_results(priv);
	iwl_free_geos(priv);
	iwl_free_channel_map(priv);
	if (priv->tx_cmd_pool)
		kmem_cache_destroy(priv->tx_cmd_pool);
	kfree(priv->scan_cmd);
	kfree(priv->beacon_cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
+2 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <net/ieee80211_radiotap.h>

#include "iwl-eeprom.h"
@@ -1053,6 +1054,7 @@ struct iwl_priv {
	struct ieee80211_hw *hw;
	struct ieee80211_channel *ieee_channels;
	struct ieee80211_rate *ieee_rates;
	struct kmem_cache *tx_cmd_pool;
	struct iwl_cfg *cfg;

	enum ieee80211_band band;
+20 −37
Original line number Diff line number Diff line
@@ -317,6 +317,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
	if (!txq->meta || !txq->cmd)
		goto error;

	if (txq_id == trans->shrd->cmd_queue)
		for (i = 0; i < slots_num; i++) {
			txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
						GFP_KERNEL);
@@ -355,7 +356,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
	txq->skbs = NULL;
	/* since txq->cmd has been zeroed,
	 * all non allocated cmd[i] will be NULL */
	if (txq->cmd)
	if (txq->cmd && txq_id == trans->shrd->cmd_queue)
		for (i = 0; i < slots_num; i++)
			kfree(txq->cmd[i]);
	kfree(txq->meta);
@@ -442,6 +443,8 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
	iwl_tx_queue_unmap(trans, txq_id);

	/* De-alloc array of command/tx buffers */

	if (txq_id == trans->shrd->cmd_queue)
		for (i = 0; i < txq->q.n_window; i++)
			kfree(txq->cmd[i]);

@@ -1009,37 +1012,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
	iwl_apm_stop(priv(trans));
}

static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_trans *trans,
						int txq_id)
{
	struct iwl_priv *priv = priv(trans);
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
	struct iwl_queue *q = &txq->q;
	struct iwl_device_cmd *dev_cmd;

	if (unlikely(iwl_queue_space(q) < q->high_mark))
		return NULL;

	/*
	 * Set up the Tx-command (not MAC!) header.
	 * Store the chosen Tx queue and TFD index within the sequence field;
	 * after Tx, uCode's Tx response will return this value so driver can
	 * locate the frame within the tx queue and do post-tx processing.
	 */
	dev_cmd = txq->cmd[q->write_ptr];
	memset(dev_cmd, 0, sizeof(*dev_cmd));
	dev_cmd->hdr.cmd = REPLY_TX;
	dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
				INDEX_TO_SEQ(q->write_ptr)));
	return &dev_cmd->cmd.tx;
}

static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb,
		struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu)
		struct iwl_device_cmd *dev_cmd, int txq_id,
		__le16 fc, bool ampdu)
{
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
	struct iwl_queue *q = &txq->q;
	struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr];
	struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx;
	struct iwl_cmd_meta *out_meta;

	dma_addr_t phys_addr = 0;
@@ -1051,6 +1030,11 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb,

	/* Set up driver data for this TFD */
	txq->skbs[q->write_ptr] = skb;
	txq->cmd[q->write_ptr] = dev_cmd;

	dev_cmd->hdr.cmd = REPLY_TX;
	dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
				INDEX_TO_SEQ(q->write_ptr)));

	/* Set up first empty entry in queue's array of Tx/cmd buffers */
	out_meta = &txq->meta[q->write_ptr];
@@ -1862,7 +1846,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
	.send_cmd = iwl_trans_pcie_send_cmd,
	.send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu,

	.get_tx_cmd = iwl_trans_pcie_get_tx_cmd,
	.tx = iwl_trans_pcie_tx,
	.reclaim = iwl_trans_pcie_reclaim,

Loading