Re: [PATCH v12 5/6] power: reset: Introduce PSCR Recording Framework for Non-Volatile Storage

Francesco Valla <[email protected]>
Newsgroups dev.linux.lists.chrome-platform,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm
Message-ID <178749889134.204450.5740187753642158305.b4-review@b4>
Hi Oleksij,

sorry for the late reply. I was wondering about this series some time
ago and it was a nice surprise to find a new revision in my inbox.

> Introduce the Power State Change Reasons Recording (PSCRR) framework: a
> generic mechanism to record why the last power state change (shutdown or
> reboot) happened - under-voltage, thermal, watchdog, software-triggered,
> etc. - so a postmortem reason survives a reboot or an abrupt power loss.
> 
> PSCRR is built around providers. A provider is either a hardware reason
> source (a PMIC, SoC reset controller or watchdog exposing a reset cause)
> or a recorder that persists the reason across a power cycle (an NVMEM or
> RTC scratch cell). Each provider gets a directory under
> /sys/kernel/pscrr/providerN/ exposing its name, backing device, the set
> of observed reasons (as tokens), its capabilities, the reasons it
> supports and - for recorders - a record policy. The reason set is
> deliberately not collapsed to a single winning cause, since resets are
> often multi-causal.
> 
> Reasons are the numeric enum psc_reason values from reboot.h, shared with
> the POWER_ON_REASON_* vocabulary, so they store compactly in small
> battery-backed cells. The current reason (get/set_psc_reason(), set by
> the thermal/regulator/hw_protection paths) is written to every recorder
> from the reboot notifier.
> 
> Signed-off-by: Oleksij Rempel <[email protected]>
>

[...]

> +/*----------------------------------------------------------------------*/
> +/* Provider registration */
> +/*----------------------------------------------------------------------*/
> +
> +/**
> + * pscrr_provider_register - register a power state change reason provider
> + * @p: caller-owned provider description
> + *
> + * Creates /sys/kernel/pscrr/providerN/ with "name" and "reason" attributes
> + * and, when @p->dev is set, a "device" symlink. @p->reason is writable when
> + * @p provides write_reason(). The provider must outlive the matching
> + * pscrr_provider_unregister() call.
> + *
> + * Return: 0 on success or a negative errno.
> + */
> +int pscrr_provider_register(struct pscrr_provider *p)
> +{
> +	struct pscrr_provider_dir *dir;
> +	int ret;
> +
> +	if (!p || !p->name || !p->ops || !p->ops->read_reasons)
> +		return -EINVAL;
> +
> +	dir = kzalloc_obj(*dir);
> +	if (!dir)
> +		return -ENOMEM;
> +
> +	dir->provider = p;
> +	dir->policy = PSCRR_RECORD_FIRST;
> +
> +	scoped_guard(mutex, &pscrr_lock) {
> +		if (!pscrr_root) {
> +			kfree(dir);
> +			return -ENODEV;
> +		}

Since the existence of pscrr_root is not protected by the lock, consider
to move this check before the allocation. 

> +
> +		dir->id = ida_alloc(&pscrr_ida, GFP_KERNEL);
> +		if (dir->id < 0) {
> +			ret = dir->id;
> +			kfree(dir);
> +			return ret;
> +		}
> +

Given that ida_alloc() should be safe to call without locking, couldn't
the scoped_guard be limited to the list operation below? Or, if the
goal is to protect against sysfs access during a provider registration,
right before the call to sysfs_create_link()?

> +		ret = kobject_init_and_add(&dir->kobj, &pscrr_dir_ktype,
> +					   pscrr_root, "provider%d", dir->id);
> +		if (ret) {
> +			/*
> +			 * kobject_init_and_add() failed: per its contract only
> +			 * kobject_put() may follow, no kobject_del(). The
> +			 * kobject is not in sysfs, so this is safe under the
> +			 * lock.
> +			 */
> +			ida_free(&pscrr_ida, dir->id);
> +			kobject_put(&dir->kobj);
> +			return ret;
> +		}
> +
> +		if (p->dev) {
> +			ret = sysfs_create_link(&dir->kobj, &p->dev->kobj,
> +						"device");
> +			if (ret)
> +				break;
> +		}
> +
> +		list_add_tail(&dir->node, &pscrr_dirs);
> +		return 0;
> +	}
> +
> +	/*
> +	 * sysfs_create_link() failed after the directory was created: tear it
> +	 * down outside pscrr_lock (kobject_del() drains sysfs stores that take
> +	 * the lock) and release the id only once the directory is gone.
> +	 */
> +	kobject_del(&dir->kobj);
> +	ida_free(&pscrr_ida, dir->id);
> +	kobject_put(&dir->kobj);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(pscrr_provider_register);
> +

Regards,

Francesco

-- 
Francesco Valla <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.