drivers/net/ipa/gsi_trans.c
Source file repositories/reference/linux-study-clean/drivers/net/ipa/gsi_trans.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ipa/gsi_trans.c- Extension
.c- Size
- 24247 bytes
- Lines
- 789
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/bits.hlinux/dma-direction.hlinux/refcount.hlinux/scatterlist.hlinux/types.hgsi.hgsi_private.hgsi_trans.hipa_cmd.hipa_data.hipa_gsi.h
Detected Declarations
struct gsi_treenum gsi_tre_typefunction gsi_trans_pool_initfunction gsi_trans_pool_exitfunction gsi_trans_pool_init_dmafunction gsi_trans_pool_exit_dmafunction gsi_trans_pool_alloc_commonfunction gsi_trans_mapfunction gsi_channel_trans_mappedfunction gsi_trans_move_committedfunction gsi_trans_move_pendingfunction gsi_trans_move_completefunction gsi_trans_move_polledfunction gsi_trans_tre_reservefunction gsi_trans_tre_releasefunction gsi_channel_trans_idlefunction gsi_trans_freefunction gsi_trans_cmd_addfunction gsi_trans_page_addfunction gsi_trans_skb_addfunction gsi_tre_len_opcodefunction gsi_tre_flagsfunction gsi_trans_tre_fillfunction __gsi_trans_commitfunction gsi_trans_commitfunction gsi_trans_commit_waitfunction gsi_trans_completefunction gsi_channel_trans_cancel_pendingfunction gsi_trans_read_bytefunction gsi_trans_read_byte_donefunction gsi_channel_trans_initfunction gsi_channel_trans_exit
Annotated Snippet
struct gsi_tre {
__le64 addr; /* DMA address */
__le16 len_opcode; /* length in bytes or enum IPA_CMD_* */
__le16 reserved;
__le32 flags; /* TRE_FLAGS_* */
};
/* gsi_tre->flags mask values (in CPU byte order) */
#define TRE_FLAGS_CHAIN_FMASK GENMASK(0, 0)
#define TRE_FLAGS_IEOT_FMASK GENMASK(9, 9)
#define TRE_FLAGS_BEI_FMASK GENMASK(10, 10)
#define TRE_FLAGS_TYPE_FMASK GENMASK(23, 16)
int gsi_trans_pool_init(struct gsi_trans_pool *pool, size_t size, u32 count,
u32 max_alloc)
{
size_t alloc_size;
void *virt;
if (!size)
return -EINVAL;
if (count < max_alloc)
return -EINVAL;
if (!max_alloc)
return -EINVAL;
/* By allocating a few extra entries in our pool (one less
* than the maximum number that will be requested in a
* single allocation), we can always satisfy requests without
* ever worrying about straddling the end of the pool array.
* If there aren't enough entries starting at the free index,
* we just allocate free entries from the beginning of the pool.
*/
alloc_size = size_mul(count + max_alloc - 1, size);
alloc_size = kmalloc_size_roundup(alloc_size);
virt = kzalloc(alloc_size, GFP_KERNEL);
if (!virt)
return -ENOMEM;
pool->base = virt;
/* If the allocator gave us any extra memory, use it */
pool->count = alloc_size / size;
pool->free = 0;
pool->max_alloc = max_alloc;
pool->size = size;
pool->addr = 0; /* Only used for DMA pools */
return 0;
}
void gsi_trans_pool_exit(struct gsi_trans_pool *pool)
{
kfree(pool->base);
memset(pool, 0, sizeof(*pool));
}
/* Home-grown DMA pool. This way we can preallocate the pool, and guarantee
* allocations will succeed. The immediate commands in a transaction can
* require up to max_alloc elements from the pool. But we only allow
* allocation of a single element from a DMA pool at a time.
*/
int gsi_trans_pool_init_dma(struct device *dev, struct gsi_trans_pool *pool,
size_t size, u32 count, u32 max_alloc)
{
size_t total_size;
dma_addr_t addr;
void *virt;
if (!size)
return -EINVAL;
if (count < max_alloc)
return -EINVAL;
if (!max_alloc)
return -EINVAL;
/* Don't let allocations cross a power-of-two boundary */
size = __roundup_pow_of_two(size);
total_size = (count + max_alloc - 1) * size;
/* The allocator will give us a power-of-2 number of pages
* sufficient to satisfy our request. Round up our requested
* size to avoid any unused space in the allocation. This way
* gsi_trans_pool_exit_dma() can assume the total allocated
* size is exactly (count * size).
*/
total_size = PAGE_SIZE << get_order(total_size);
virt = dma_alloc_coherent(dev, total_size, &addr, GFP_KERNEL);
if (!virt)
return -ENOMEM;
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bits.h`, `linux/dma-direction.h`, `linux/refcount.h`, `linux/scatterlist.h`, `linux/types.h`, `gsi.h`, `gsi_private.h`.
- Detected declarations: `struct gsi_tre`, `enum gsi_tre_type`, `function gsi_trans_pool_init`, `function gsi_trans_pool_exit`, `function gsi_trans_pool_init_dma`, `function gsi_trans_pool_exit_dma`, `function gsi_trans_pool_alloc_common`, `function gsi_trans_map`, `function gsi_channel_trans_mapped`, `function gsi_trans_move_committed`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.