Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: ni903x_wdt: Convert to a platform driver

In all cases in which a struct acpi_driver is used for binding a driver
to an ACPI device object, a corresponding platform device is created by
the ACPI core and that device is regarded as a proper representation of
underlying hardware. Accordingly, a struct platform_driver should be
used by driver code to bind to that device. There are multiple reasons
why drivers should not bind directly to ACPI device objects [1].

In particular, registering a watchdog device under a struct acpi_device
is questionable because it causes the watchdog to be hidden in the ACPI
bus sysfs hierarchy and it goes against the general rule that a struct
acpi_device can only be a parent of another struct acpi_device.

Overall, it is better to bind drivers to platform devices than to their
ACPI companions, so convert the ni903x_wdt watchdog ACPI driver to a
platform one.

While this is not expected to alter functionality, it changes sysfs
layout and so it will be visible to user space.

Note that after this change it actually makes sense to look for
the "timeout-sec" property via device_property_read_u32() under the
device passed to watchdog_init_timeout() because it has an fwnode
handle (unlike a struct acpi_device which is an fwnode itself).

Link: https://lore.kernel.org/all/2396510.ElGaqSPkdT@rafael.j.wysocki/ [1]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://patch.msgid.link/13996583.uLZWGnKmhe@rafael.j.wysocki

+14 -13
+14 -13
drivers/watchdog/ni903x_wdt.c
··· 8 8 #include <linux/interrupt.h> 9 9 #include <linux/io.h> 10 10 #include <linux/module.h> 11 + #include <linux/platform_device.h> 11 12 #include <linux/watchdog.h> 12 13 13 14 #define NIWD_CONTROL 0x01 ··· 178 177 .get_timeleft = ni903x_wdd_get_timeleft, 179 178 }; 180 179 181 - static int ni903x_acpi_add(struct acpi_device *device) 180 + static int ni903x_acpi_probe(struct platform_device *pdev) 182 181 { 183 - struct device *dev = &device->dev; 182 + struct device *dev = &pdev->dev; 184 183 struct watchdog_device *wdd; 185 184 struct ni903x_wdt *wdt; 186 185 acpi_status status; ··· 190 189 if (!wdt) 191 190 return -ENOMEM; 192 191 193 - device->driver_data = wdt; 192 + platform_set_drvdata(pdev, wdt); 194 193 wdt->dev = dev; 195 194 196 - status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, 195 + status = acpi_walk_resources(ACPI_HANDLE(dev), METHOD_NAME__CRS, 197 196 ni903x_resources, wdt); 198 197 if (ACPI_FAILURE(status) || wdt->io_base == 0) { 199 198 dev_err(dev, "failed to get resources\n"); ··· 225 224 return 0; 226 225 } 227 226 228 - static void ni903x_acpi_remove(struct acpi_device *device) 227 + static void ni903x_acpi_remove(struct platform_device *pdev) 229 228 { 230 - struct ni903x_wdt *wdt = acpi_driver_data(device); 229 + struct ni903x_wdt *wdt = platform_get_drvdata(pdev); 231 230 232 231 ni903x_wdd_stop(&wdt->wdd); 233 232 watchdog_unregister_device(&wdt->wdd); ··· 239 238 }; 240 239 MODULE_DEVICE_TABLE(acpi, ni903x_device_ids); 241 240 242 - static struct acpi_driver ni903x_acpi_driver = { 243 - .name = NIWD_NAME, 244 - .ids = ni903x_device_ids, 245 - .ops = { 246 - .add = ni903x_acpi_add, 247 - .remove = ni903x_acpi_remove, 241 + static struct platform_driver ni903x_acpi_driver = { 242 + .probe = ni903x_acpi_probe, 243 + .remove = ni903x_acpi_remove, 244 + .driver = { 245 + .name = NIWD_NAME, 246 + .acpi_match_table = ni903x_device_ids, 248 247 }, 249 248 }; 250 249 251 - module_acpi_driver(ni903x_acpi_driver); 250 + module_platform_driver(ni903x_acpi_driver); 252 251 253 252 MODULE_DESCRIPTION("NI 903x Watchdog"); 254 253 MODULE_AUTHOR("Jeff Westfahl <jeff.westfahl@ni.com>");