Commit 49200658 authored by Alex Elder's avatar Alex Elder Committed by Jakub Kicinski
Browse files

net: ipa: rearrange transaction initialization



The transaction map is really associated with the transaction pool;
move its definition earlier in the gsi_trans_info structure.

Rearrange initialization in gsi_channel_trans_init() so it
sets the tre_avail value first, then initializes the transaction
pool, and finally allocating the transaction map.

Update comments.

Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b63f507c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -83,9 +83,10 @@ struct gsi_trans_pool {
struct gsi_trans_info {
	atomic_t tre_avail;		/* TREs available for allocation */
	struct gsi_trans_pool pool;	/* transaction pool */
	struct gsi_trans **map;		/* TRE -> transaction map */

	struct gsi_trans_pool sg_pool;	/* scatterlist pool */
	struct gsi_trans_pool cmd_pool;	/* command payload DMA pool */
	struct gsi_trans **map;		/* TRE -> transaction map */

	spinlock_t spinlock;		/* protects updates to the lists */
	struct list_head alloc;		/* allocated, not committed */
+31 −29
Original line number Diff line number Diff line
@@ -709,6 +709,7 @@ void gsi_trans_read_byte_done(struct gsi *gsi, u32 channel_id)
int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)
{
	struct gsi_channel *channel = &gsi->channel[channel_id];
	u32 tre_count = channel->tre_count;
	struct gsi_trans_info *trans_info;
	u32 tre_max;
	int ret;
@@ -716,30 +717,40 @@ int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)
	/* Ensure the size of a channel element is what's expected */
	BUILD_BUG_ON(sizeof(struct gsi_tre) != GSI_RING_ELEMENT_SIZE);

	/* The map array is used to determine what transaction is associated
	 * with a TRE that the hardware reports has completed.  We need one
	 * map entry per TRE.
	 */
	trans_info = &channel->trans_info;
	trans_info->map = kcalloc(channel->tre_count, sizeof(*trans_info->map),
				  GFP_KERNEL);
	if (!trans_info->map)
		return -ENOMEM;

	/* We can't use more TREs than there are available in the ring.
	 * This limits the number of transactions that can be outstanding.
	 * Worst case is one TRE per transaction (but we actually limit
	 * it to something a little less than that).  We allocate resources
	 * for transactions (including transaction structures) based on
	 * this maximum number.
	/* The tre_avail field is what ultimately limits the number of
	 * outstanding transactions and their resources.  A transaction
	 * allocation succeeds only if the TREs available are sufficient
	 * for what the transaction might need.
	 */
	tre_max = gsi_channel_tre_max(channel->gsi, channel_id);
	atomic_set(&trans_info->tre_avail, tre_max);

	/* Transactions are allocated one at a time. */
	/* We can't use more TREs than the number available in the ring.
	 * This limits the number of transactions that can be outstanding.
	 * Worst case is one TRE per transaction (but we actually limit
	 * it to something a little less than that).  By allocating a
	 * power-of-two number of transactions we can use an index
	 * modulo that number to determine the next one that's free.
	 * Transactions are allocated one at a time.
	 */
	ret = gsi_trans_pool_init(&trans_info->pool, sizeof(struct gsi_trans),
				  tre_max, 1);
	if (ret)
		goto err_kfree;
		return -ENOMEM;

	/* A completion event contains a pointer to the TRE that caused
	 * the event (which will be the last one used by the transaction).
	 * Each entry in this map records the transaction associated
	 * with a corresponding completed TRE.
	 */
	trans_info->map = kcalloc(tre_count, sizeof(*trans_info->map),
				  GFP_KERNEL);
	if (!trans_info->map) {
		ret = -ENOMEM;
		goto err_trans_free;
	}

	/* A transaction uses a scatterlist array to represent the data
	 * transfers implemented by the transaction.  Each scatterlist
@@ -751,16 +762,7 @@ int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)
				  sizeof(struct scatterlist),
				  tre_max, channel->trans_tre_max);
	if (ret)
		goto err_trans_pool_exit;

	/* Finally, the tre_avail field is what ultimately limits the number
	 * of outstanding transactions and their resources.  A transaction
	 * allocation succeeds only if the TREs available are sufficient for
	 * what the transaction might need.  Transaction resource pools are
	 * sized based on the maximum number of outstanding TREs, so there
	 * will always be resources available if there are TREs available.
	 */
	atomic_set(&trans_info->tre_avail, tre_max);
		goto err_map_free;

	spin_lock_init(&trans_info->spinlock);
	INIT_LIST_HEAD(&trans_info->alloc);
@@ -771,10 +773,10 @@ int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)

	return 0;

err_trans_pool_exit:
	gsi_trans_pool_exit(&trans_info->pool);
err_kfree:
err_map_free:
	kfree(trans_info->map);
err_trans_free:
	gsi_trans_pool_exit(&trans_info->pool);

	dev_err(gsi->dev, "error %d initializing channel %u transactions\n",
		ret, channel_id);