Commit fdcfd854 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Alexandre Belloni
Browse files

rtc: rework rtc_register_device() resource management



rtc_register_device() is a managed interface but it doesn't use devres
by itself - instead it marks an rtc_device as "registered" and the devres
callback for devm_rtc_allocate_device() takes care of resource release.

This doesn't correspond with the design behind devres where managed
structures should not be aware of being managed. The correct solution
here is to register a separate devres callback for unregistering the
device.

While at it: rename rtc_register_device() to devm_rtc_register_device()
and add it to the list of managed interfaces in devres.rst. This way we
can avoid any potential confusion of driver developers who may expect
there to exist a corresponding unregister function.

Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20201109163409.24301-8-brgl@bgdev.pl
parent 6746bc09
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -414,6 +414,7 @@ RESET
RTC
  devm_rtc_device_register()
  devm_rtc_allocate_device()
  devm_rtc_register_device()
  devm_rtc_nvmem_register()

SERDEV
+1 −1
Original line number Diff line number Diff line
@@ -216,6 +216,6 @@ alpha_rtc_init(void)
		rtc->ops = &remote_rtc_ops;
#endif

	return rtc_register_device(rtc);
	return devm_rtc_register_device(rtc);
}
device_initcall(alpha_rtc_init);
+1 −1
Original line number Diff line number Diff line
@@ -1119,7 +1119,7 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
		menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
	}

	err = rtc_register_device(m->rtc);
	err = devm_rtc_register_device(m->rtc);
	if (err) {
		if (alarm) {
			menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
+9 −10
Original line number Diff line number Diff line
@@ -321,8 +321,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
 *
 * @rtc: the RTC class device to destroy
 */
static void rtc_device_unregister(struct rtc_device *rtc)
static void devm_rtc_unregister_device(void *data)
{
	struct rtc_device *rtc = data;

	mutex_lock(&rtc->ops_lock);
	/*
	 * Remove innards of this RTC, then disable it, before
@@ -339,9 +341,6 @@ static void devm_rtc_release_device(struct device *dev, void *res)
{
	struct rtc_device *rtc = *(struct rtc_device **)res;

	if (rtc->registered)
		rtc_device_unregister(rtc);
	else
	put_device(&rtc->dev);
}

@@ -383,7 +382,7 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(devm_rtc_allocate_device);

int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
{
	struct rtc_wkalrm alrm;
	int err;
@@ -413,7 +412,6 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)

	rtc_proc_add_device(rtc);

	rtc->registered = true;
	dev_info(rtc->dev.parent, "registered as %s\n",
		 dev_name(&rtc->dev));

@@ -422,9 +420,10 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
		rtc_hctosys(rtc);
#endif

	return 0;
	return devm_add_action_or_reset(rtc->dev.parent,
					devm_rtc_unregister_device, rtc);
}
EXPORT_SYMBOL_GPL(__rtc_register_device);
EXPORT_SYMBOL_GPL(__devm_rtc_register_device);

/**
 * devm_rtc_device_register - resource managed rtc_device_register()
@@ -454,7 +453,7 @@ struct rtc_device *devm_rtc_device_register(struct device *dev,

	rtc->ops = ops;

	err = __rtc_register_device(owner, rtc);
	err = __devm_rtc_register_device(owner, rtc);
	if (err)
		return ERR_PTR(err);

+1 −1
Original line number Diff line number Diff line
@@ -294,7 +294,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
	info->rtc_dev->ops = &pm80x_rtc_ops;
	info->rtc_dev->range_max = U32_MAX;

	ret = rtc_register_device(info->rtc_dev);
	ret = devm_rtc_register_device(info->rtc_dev);
	if (ret)
		goto out_rtc;

Loading