drivers/spi/spi-loopback-test.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-loopback-test.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-loopback-test.c- Extension
.c- Size
- 27733 bytes
- Lines
- 1125
- Domain
- Driver Families
- Bucket
- drivers/spi
- 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.
- 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/delay.hlinux/kernel.hlinux/ktime.hlinux/list.hlinux/list_sort.hlinux/mod_devicetable.hlinux/module.hlinux/printk.hlinux/vmalloc.hlinux/spi/spi.hspi-test.h
Detected Declarations
struct rx_rangesfunction spi_loopback_test_probefunction spi_test_print_hex_dumpfunction spi_test_dump_messagefunction list_for_each_entryfunction rx_ranges_cmpfunction spi_check_rx_rangesfunction list_for_each_entryfunction spi_test_check_elapsed_timefunction spi_test_check_loopback_resultfunction spi_test_translatefunction spi_test_fill_patternfunction _spi_test_run_iterfunction spi_test_run_iterfunction spi_test_execute_msgfunction spi_test_run_testfunction FOR_EACH_ALIGNMENTfunction spi_test_run_testsexport spi_test_execute_msgexport spi_test_run_testexport spi_test_run_tests
Annotated Snippet
struct rx_ranges {
struct list_head list;
u8 *start;
u8 *end;
};
static int rx_ranges_cmp(void *priv, const struct list_head *a,
const struct list_head *b)
{
const struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list);
const struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list);
if (rx_a->start > rx_b->start)
return 1;
if (rx_a->start < rx_b->start)
return -1;
return 0;
}
static int spi_check_rx_ranges(struct spi_device *spi,
struct spi_message *msg,
void *rx)
{
struct spi_transfer *xfer;
struct rx_ranges ranges[SPI_TEST_MAX_TRANSFERS], *r;
int i = 0;
LIST_HEAD(ranges_list);
u8 *addr;
int ret = 0;
/* loop over all transfers to fill in the rx_ranges */
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
/* if there is no rx, then no check is needed */
if (!xfer->rx_buf)
continue;
/* fill in the rx_range */
if (RANGE_CHECK(xfer->rx_buf, xfer->len,
rx, SPI_TEST_MAX_SIZE_PLUS)) {
ranges[i].start = xfer->rx_buf;
ranges[i].end = xfer->rx_buf + xfer->len;
list_add(&ranges[i].list, &ranges_list);
i++;
}
}
/* if no ranges, then we can return and avoid the checks...*/
if (!i)
return 0;
/* sort the list */
list_sort(NULL, &ranges_list, rx_ranges_cmp);
/* and iterate over all the rx addresses */
for (addr = rx; addr < (u8 *)rx + SPI_TEST_MAX_SIZE_PLUS; addr++) {
/* if we are the DO not write pattern,
* then continue with the loop...
*/
if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE)
continue;
/* check if we are inside a range */
list_for_each_entry(r, &ranges_list, list) {
/* if so then set to end... */
if ((addr >= r->start) && (addr < r->end))
addr = r->end;
}
/* second test after a (hopefull) translation */
if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE)
continue;
/* if still not found then something has modified too much */
/* we could list the "closest" transfer here... */
dev_err(&spi->dev,
"loopback strangeness - rx changed outside of allowed range at: %p\n",
addr);
/* do not return, only set ret,
* so that we list all addresses
*/
ret = -ERANGE;
}
return ret;
}
static int spi_test_check_elapsed_time(struct spi_device *spi,
struct spi_test *test)
{
int i;
unsigned long long estimated_time = 0;
unsigned long long delay_usecs = 0;
Annotation
- Immediate include surface: `linux/delay.h`, `linux/kernel.h`, `linux/ktime.h`, `linux/list.h`, `linux/list_sort.h`, `linux/mod_devicetable.h`, `linux/module.h`, `linux/printk.h`.
- Detected declarations: `struct rx_ranges`, `function spi_loopback_test_probe`, `function spi_test_print_hex_dump`, `function spi_test_dump_message`, `function list_for_each_entry`, `function rx_ranges_cmp`, `function spi_check_rx_ranges`, `function list_for_each_entry`, `function spi_test_check_elapsed_time`, `function spi_test_check_loopback_result`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: integration implementation candidate.
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.