drivers/gpio/gpio-sloppy-logic-analyzer.c
Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-sloppy-logic-analyzer.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpio/gpio-sloppy-logic-analyzer.c- Extension
.c- Size
- 8859 bytes
- Lines
- 346
- Domain
- Driver Families
- Bucket
- drivers/gpio
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/ctype.hlinux/debugfs.hlinux/delay.hlinux/device.hlinux/err.hlinux/gpio/consumer.hlinux/init.hlinux/ktime.hlinux/mod_devicetable.hlinux/module.hlinux/mutex.hlinux/platform_device.hlinux/property.hlinux/slab.hlinux/sizes.hlinux/timekeeping.hlinux/types.hlinux/vmalloc.h
Detected Declarations
struct gpio_la_poll_privfunction gpio_la_get_arrayfunction fops_capture_setfunction fops_buf_size_getfunction fops_buf_size_setfunction trigger_openfunction trigger_writefunction gpio_la_poll_probefunction gpio_la_poll_removefunction gpio_la_poll_initfunction gpio_la_poll_exit
Annotated Snippet
static const struct file_operations fops_trigger = {
.owner = THIS_MODULE,
.open = trigger_open,
.write = trigger_write,
.release = single_release,
};
static int gpio_la_poll_probe(struct platform_device *pdev)
{
struct gpio_la_poll_priv *priv;
struct device *dev = &pdev->dev;
const char *devname = dev_name(dev);
const char *gpio_names[GPIO_LA_MAX_PROBES];
char *meta = NULL;
unsigned int i, meta_len = 0;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
ret = devm_mutex_init(dev, &priv->blob_lock);
if (ret)
return ret;
fops_buf_size_set(priv, GPIO_LA_DEFAULT_BUF_SIZE);
priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN);
if (IS_ERR(priv->descs))
return PTR_ERR(priv->descs);
/* artificial limit to keep 1 byte per sample for now */
if (priv->descs->ndescs > GPIO_LA_MAX_PROBES)
return -EFBIG;
ret = device_property_read_string_array(dev, "probe-names", gpio_names,
priv->descs->ndescs);
if (ret >= 0 && ret != priv->descs->ndescs)
ret = -EBADR;
if (ret < 0)
return dev_err_probe(dev, ret, "error naming the GPIOs");
for (i = 0; i < priv->descs->ndescs; i++) {
unsigned int add_len;
char *new_meta, *consumer_name;
if (gpiod_cansleep(priv->descs->desc[i]))
return -EREMOTE;
consumer_name = kasprintf(GFP_KERNEL, "%s: %s", devname, gpio_names[i]);
if (!consumer_name)
return -ENOMEM;
gpiod_set_consumer_name(priv->descs->desc[i], consumer_name);
kfree(consumer_name);
/* '10' is length of 'probe00=\n\0' */
add_len = strlen(gpio_names[i]) + 10;
new_meta = devm_krealloc(dev, meta, meta_len + add_len, GFP_KERNEL);
if (!new_meta)
return -ENOMEM;
meta = new_meta;
meta_len += snprintf(meta + meta_len, add_len, "probe%02u=%s\n",
i + 1, gpio_names[i]);
}
platform_set_drvdata(pdev, priv);
priv->dev = dev;
priv->meta.data = meta;
priv->meta.size = meta_len;
priv->debug_dir = debugfs_create_dir(devname, gpio_la_poll_debug_dir);
debugfs_create_blob("meta_data", 0400, priv->debug_dir, &priv->meta);
debugfs_create_ulong("delay_ns", 0600, priv->debug_dir, &priv->delay_ns);
debugfs_create_ulong("delay_ns_acquisition", 0400, priv->debug_dir, &priv->acq_delay);
debugfs_create_file_unsafe("buf_size", 0600, priv->debug_dir, priv, &fops_buf_size);
debugfs_create_file_unsafe("capture", 0200, priv->debug_dir, priv, &fops_capture);
debugfs_create_file_unsafe("trigger", 0200, priv->debug_dir, priv, &fops_trigger);
return 0;
}
static void gpio_la_poll_remove(struct platform_device *pdev)
{
struct gpio_la_poll_priv *priv = platform_get_drvdata(pdev);
mutex_lock(&priv->blob_lock);
debugfs_remove_recursive(priv->debug_dir);
mutex_unlock(&priv->blob_lock);
Annotation
- Immediate include surface: `linux/ctype.h`, `linux/debugfs.h`, `linux/delay.h`, `linux/device.h`, `linux/err.h`, `linux/gpio/consumer.h`, `linux/init.h`, `linux/ktime.h`.
- Detected declarations: `struct gpio_la_poll_priv`, `function gpio_la_get_array`, `function fops_capture_set`, `function fops_buf_size_get`, `function fops_buf_size_set`, `function trigger_open`, `function trigger_write`, `function gpio_la_poll_probe`, `function gpio_la_poll_remove`, `function gpio_la_poll_init`.
- Atlas domain: Driver Families / drivers/gpio.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.