drivers/gnss/core.c

Source file repositories/reference/linux-study-clean/drivers/gnss/core.c

File Facts

System
Linux kernel
Corpus path
drivers/gnss/core.c
Extension
.c
Size
8419 bytes
Lines
421
Domain
Driver Families
Bucket
drivers/gnss
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.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations gnss_fops = {
	.owner		= THIS_MODULE,
	.open		= gnss_open,
	.release	= gnss_release,
	.read		= gnss_read,
	.write		= gnss_write,
	.poll		= gnss_poll,
};

static struct class *gnss_class;

static void gnss_device_release(struct device *dev)
{
	struct gnss_device *gdev = to_gnss_device(dev);

	kfree(gdev->write_buf);
	kfifo_free(&gdev->read_fifo);
	ida_free(&gnss_minors, gdev->id);
	kfree(gdev);
}

struct gnss_device *gnss_allocate_device(struct device *parent)
{
	struct gnss_device *gdev;
	struct device *dev;
	int id;
	int ret;

	gdev = kzalloc_obj(*gdev);
	if (!gdev)
		return NULL;

	id = ida_alloc_max(&gnss_minors, GNSS_MINORS - 1, GFP_KERNEL);
	if (id < 0) {
		kfree(gdev);
		return NULL;
	}

	gdev->id = id;

	dev = &gdev->dev;
	device_initialize(dev);
	dev->devt = gnss_first + id;
	dev->class = gnss_class;
	dev->parent = parent;
	dev->release = gnss_device_release;
	dev_set_drvdata(dev, gdev);
	dev_set_name(dev, "gnss%d", id);

	init_rwsem(&gdev->rwsem);
	mutex_init(&gdev->read_mutex);
	mutex_init(&gdev->write_mutex);
	init_waitqueue_head(&gdev->read_queue);

	ret = kfifo_alloc(&gdev->read_fifo, GNSS_READ_FIFO_SIZE, GFP_KERNEL);
	if (ret)
		goto err_put_device;

	gdev->write_buf = kzalloc(GNSS_WRITE_BUF_SIZE, GFP_KERNEL);
	if (!gdev->write_buf)
		goto err_put_device;

	cdev_init(&gdev->cdev, &gnss_fops);
	gdev->cdev.owner = THIS_MODULE;

	return gdev;

err_put_device:
	put_device(dev);

	return NULL;
}
EXPORT_SYMBOL_GPL(gnss_allocate_device);

void gnss_put_device(struct gnss_device *gdev)
{
	put_device(&gdev->dev);
}
EXPORT_SYMBOL_GPL(gnss_put_device);

int gnss_register_device(struct gnss_device *gdev)
{
	int ret;

	/* Set a flag which can be accessed without holding the rwsem. */
	if (gdev->ops->write_raw != NULL)
		gdev->flags |= GNSS_FLAG_HAS_WRITE_RAW;

	ret = cdev_device_add(&gdev->cdev, &gdev->dev);
	if (ret) {

Annotation

Implementation Notes