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: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
b63f507c06
commit
4920065888
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue