drivers/watchdog/watchdog_dev.c

Source file repositories/reference/linux-study-clean/drivers/watchdog/watchdog_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/watchdog_dev.c
Extension
.c
Size
34183 bytes
Lines
1323
Domain
Driver Families
Bucket
drivers/watchdog
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 watchdog_fops = {
	.owner		= THIS_MODULE,
	.write		= watchdog_write,
	.unlocked_ioctl	= watchdog_ioctl,
	.compat_ioctl	= compat_ptr_ioctl,
	.open		= watchdog_open,
	.release	= watchdog_release,
};

static struct miscdevice watchdog_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &watchdog_fops,
};

static const struct class watchdog_class = {
	.name =		"watchdog",
	.dev_groups =	wdt_groups,
};

/**
 * watchdog_cdev_register - register watchdog character device
 * @wdd: Watchdog device
 *
 * Register a watchdog character device including handling the legacy
 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and
 * thus we set it up like that.
 *
 * Return: 0 if successful, error otherwise.
 */
static int watchdog_cdev_register(struct watchdog_device *wdd)
{
	struct watchdog_core_data *wd_data;
	int err;

	wd_data = kzalloc_obj(struct watchdog_core_data);
	if (!wd_data)
		return -ENOMEM;
	mutex_init(&wd_data->lock);

	wd_data->wdd = wdd;
	wdd->wd_data = wd_data;

	if (IS_ERR_OR_NULL(watchdog_kworker)) {
		kfree(wd_data);
		return -ENODEV;
	}

	device_initialize(&wd_data->dev);
	wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id);
	wd_data->dev.class = &watchdog_class;
	wd_data->dev.parent = wdd->parent;
	wd_data->dev.groups = wdd->groups;
	wd_data->dev.release = watchdog_core_data_release;
	dev_set_drvdata(&wd_data->dev, wdd);
	err = dev_set_name(&wd_data->dev, "watchdog%d", wdd->id);
	if (err) {
		put_device(&wd_data->dev);
		return err;
	}

	kthread_init_work(&wd_data->work, watchdog_ping_work);
	hrtimer_setup(&wd_data->timer, watchdog_timer_expired, CLOCK_MONOTONIC,
		      HRTIMER_MODE_REL_HARD);
	watchdog_hrtimer_pretimeout_init(wdd);

	if (wdd->id == 0) {
		old_wd_data = wd_data;
		watchdog_miscdev.parent = wdd->parent;
		err = misc_register(&watchdog_miscdev);
		if (err != 0) {
			pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
				wdd->info->identity, WATCHDOG_MINOR, err);
			if (err == -EBUSY)
				pr_err("%s: a legacy watchdog module is probably present.\n",
					wdd->info->identity);
			old_wd_data = NULL;
			put_device(&wd_data->dev);
			return err;
		}
	}

	/* Fill in the data structures */
	cdev_init(&wd_data->cdev, &watchdog_fops);
	wd_data->cdev.owner = wdd->ops->owner;

	/* Add the device */
	err = cdev_device_add(&wd_data->cdev, &wd_data->dev);
	if (err) {
		pr_err("watchdog%d unable to add device %d:%d\n",

Annotation

Implementation Notes