drivers/net/wireless/intel/iwlwifi/fw/paging.c
Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/fw/paging.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/wireless/intel/iwlwifi/fw/paging.c- Extension
.c- Size
- 8228 bytes
- Lines
- 297
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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
iwl-drv.hruntime.hfw/api/commands.h
Detected Declarations
function Copyrightfunction iwl_alloc_fw_paging_memfunction iwl_fill_paging_memfunction iwl_save_fw_pagingfunction iwl_send_paging_cmdfunction iwl_init_paging
Annotated Snippet
if (!paging->fw_paging_block) {
IWL_DEBUG_FW(fwrt,
"Paging: block %d already freed, continue to next page\n",
i);
continue;
}
dma_unmap_page(fwrt->trans->dev, paging->fw_paging_phys,
paging->fw_paging_size, DMA_BIDIRECTIONAL);
__free_pages(paging->fw_paging_block,
get_order(paging->fw_paging_size));
paging->fw_paging_block = NULL;
}
memset(fwrt->fw_paging_db, 0, sizeof(fwrt->fw_paging_db));
}
IWL_EXPORT_SYMBOL(iwl_free_fw_paging);
static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt,
const struct fw_img *image)
{
struct page *block;
dma_addr_t phys = 0;
int blk_idx, order, num_of_pages, size;
if (fwrt->fw_paging_db[0].fw_paging_block)
return 0;
/* ensure BLOCK_2_EXP_SIZE is power of 2 of PAGING_BLOCK_SIZE */
BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE);
num_of_pages = image->paging_mem_size / FW_PAGING_SIZE;
fwrt->num_of_paging_blk =
DIV_ROUND_UP(num_of_pages, NUM_OF_PAGE_PER_GROUP);
fwrt->num_of_pages_in_last_blk =
num_of_pages -
NUM_OF_PAGE_PER_GROUP * (fwrt->num_of_paging_blk - 1);
IWL_DEBUG_FW(fwrt,
"Paging: allocating mem for %d paging blocks, each block holds 8 pages, last block holds %d pages\n",
fwrt->num_of_paging_blk,
fwrt->num_of_pages_in_last_blk);
/*
* Allocate CSS and paging blocks in dram.
*/
for (blk_idx = 0; blk_idx < fwrt->num_of_paging_blk + 1; blk_idx++) {
/* For CSS allocate 4KB, for others PAGING_BLOCK_SIZE (32K) */
size = blk_idx ? PAGING_BLOCK_SIZE : FW_PAGING_SIZE;
order = get_order(size);
block = alloc_pages(GFP_KERNEL, order);
if (!block) {
/* free all the previous pages since we failed */
iwl_free_fw_paging(fwrt);
return -ENOMEM;
}
fwrt->fw_paging_db[blk_idx].fw_paging_block = block;
fwrt->fw_paging_db[blk_idx].fw_paging_size = size;
phys = dma_map_page(fwrt->trans->dev, block, 0,
PAGE_SIZE << order,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(fwrt->trans->dev, phys)) {
/*
* free the previous pages and the current one
* since we failed to map_page.
*/
iwl_free_fw_paging(fwrt);
return -ENOMEM;
}
fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys;
if (!blk_idx)
IWL_DEBUG_FW(fwrt,
"Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n",
order);
else
IWL_DEBUG_FW(fwrt,
"Paging: allocated 32K bytes (order %d) for firmware paging.\n",
order);
}
return 0;
}
static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
const struct fw_img *image)
{
Annotation
- Immediate include surface: `iwl-drv.h`, `runtime.h`, `fw/api/commands.h`.
- Detected declarations: `function Copyright`, `function iwl_alloc_fw_paging_mem`, `function iwl_fill_paging_mem`, `function iwl_save_fw_paging`, `function iwl_send_paging_cmd`, `function iwl_init_paging`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: integration implementation candidate.
- 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.