LCOV - code coverage report
Current view: top level - drivers/base - driver.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 31 87 35.6 %
Date: 2023-08-24 13:40:31 Functions: 6 9 66.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * driver.c - centralized device driver management
       4             :  *
       5             :  * Copyright (c) 2002-3 Patrick Mochel
       6             :  * Copyright (c) 2002-3 Open Source Development Labs
       7             :  * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
       8             :  * Copyright (c) 2007 Novell Inc.
       9             :  */
      10             : 
      11             : #include <linux/device/driver.h>
      12             : #include <linux/device.h>
      13             : #include <linux/module.h>
      14             : #include <linux/errno.h>
      15             : #include <linux/slab.h>
      16             : #include <linux/string.h>
      17             : #include <linux/sysfs.h>
      18             : #include "base.h"
      19             : 
      20             : static struct device *next_device(struct klist_iter *i)
      21             : {
      22           0 :         struct klist_node *n = klist_next(i);
      23           0 :         struct device *dev = NULL;
      24             :         struct device_private *dev_prv;
      25             : 
      26           0 :         if (n) {
      27           0 :                 dev_prv = to_device_private_driver(n);
      28           0 :                 dev = dev_prv->device;
      29             :         }
      30             :         return dev;
      31             : }
      32             : 
      33             : /**
      34             :  * driver_set_override() - Helper to set or clear driver override.
      35             :  * @dev: Device to change
      36             :  * @override: Address of string to change (e.g. &device->driver_override);
      37             :  *            The contents will be freed and hold newly allocated override.
      38             :  * @s: NUL-terminated string, new driver name to force a match, pass empty
      39             :  *     string to clear it ("" or "\n", where the latter is only for sysfs
      40             :  *     interface).
      41             :  * @len: length of @s
      42             :  *
      43             :  * Helper to set or clear driver override in a device, intended for the cases
      44             :  * when the driver_override field is allocated by driver/bus code.
      45             :  *
      46             :  * Returns: 0 on success or a negative error code on failure.
      47             :  */
      48           0 : int driver_set_override(struct device *dev, const char **override,
      49             :                         const char *s, size_t len)
      50             : {
      51             :         const char *new, *old;
      52             :         char *cp;
      53             : 
      54           0 :         if (!override || !s)
      55             :                 return -EINVAL;
      56             : 
      57             :         /*
      58             :          * The stored value will be used in sysfs show callback (sysfs_emit()),
      59             :          * which has a length limit of PAGE_SIZE and adds a trailing newline.
      60             :          * Thus we can store one character less to avoid truncation during sysfs
      61             :          * show.
      62             :          */
      63           0 :         if (len >= (PAGE_SIZE - 1))
      64             :                 return -EINVAL;
      65             : 
      66             :         /*
      67             :          * Compute the real length of the string in case userspace sends us a
      68             :          * bunch of \0 characters like python likes to do.
      69             :          */
      70           0 :         len = strlen(s);
      71             : 
      72           0 :         if (!len) {
      73             :                 /* Empty string passed - clear override */
      74           0 :                 device_lock(dev);
      75           0 :                 old = *override;
      76           0 :                 *override = NULL;
      77           0 :                 device_unlock(dev);
      78           0 :                 kfree(old);
      79             : 
      80           0 :                 return 0;
      81             :         }
      82             : 
      83           0 :         cp = strnchr(s, len, '\n');
      84           0 :         if (cp)
      85           0 :                 len = cp - s;
      86             : 
      87           0 :         new = kstrndup(s, len, GFP_KERNEL);
      88           0 :         if (!new)
      89             :                 return -ENOMEM;
      90             : 
      91           0 :         device_lock(dev);
      92           0 :         old = *override;
      93           0 :         if (cp != s) {
      94           0 :                 *override = new;
      95             :         } else {
      96             :                 /* "\n" passed - clear override */
      97           0 :                 kfree(new);
      98           0 :                 *override = NULL;
      99             :         }
     100           0 :         device_unlock(dev);
     101             : 
     102           0 :         kfree(old);
     103             : 
     104           0 :         return 0;
     105             : }
     106             : EXPORT_SYMBOL_GPL(driver_set_override);
     107             : 
     108             : /**
     109             :  * driver_for_each_device - Iterator for devices bound to a driver.
     110             :  * @drv: Driver we're iterating.
     111             :  * @start: Device to begin with
     112             :  * @data: Data to pass to the callback.
     113             :  * @fn: Function to call for each device.
     114             :  *
     115             :  * Iterate over the @drv's list of devices calling @fn for each one.
     116             :  */
     117           0 : int driver_for_each_device(struct device_driver *drv, struct device *start,
     118             :                            void *data, int (*fn)(struct device *, void *))
     119             : {
     120             :         struct klist_iter i;
     121             :         struct device *dev;
     122           0 :         int error = 0;
     123             : 
     124           0 :         if (!drv)
     125             :                 return -EINVAL;
     126             : 
     127           0 :         klist_iter_init_node(&drv->p->klist_devices, &i,
     128           0 :                              start ? &start->p->knode_driver : NULL);
     129           0 :         while (!error && (dev = next_device(&i)))
     130           0 :                 error = fn(dev, data);
     131           0 :         klist_iter_exit(&i);
     132           0 :         return error;
     133             : }
     134             : EXPORT_SYMBOL_GPL(driver_for_each_device);
     135             : 
     136             : /**
     137             :  * driver_find_device - device iterator for locating a particular device.
     138             :  * @drv: The device's driver
     139             :  * @start: Device to begin with
     140             :  * @data: Data to pass to match function
     141             :  * @match: Callback function to check device
     142             :  *
     143             :  * This is similar to the driver_for_each_device() function above, but
     144             :  * it returns a reference to a device that is 'found' for later use, as
     145             :  * determined by the @match callback.
     146             :  *
     147             :  * The callback should return 0 if the device doesn't match and non-zero
     148             :  * if it does.  If the callback returns non-zero, this function will
     149             :  * return to the caller and not iterate over any more devices.
     150             :  */
     151           0 : struct device *driver_find_device(struct device_driver *drv,
     152             :                                   struct device *start, const void *data,
     153             :                                   int (*match)(struct device *dev, const void *data))
     154             : {
     155             :         struct klist_iter i;
     156             :         struct device *dev;
     157             : 
     158           0 :         if (!drv || !drv->p)
     159             :                 return NULL;
     160             : 
     161           0 :         klist_iter_init_node(&drv->p->klist_devices, &i,
     162           0 :                              (start ? &start->p->knode_driver : NULL));
     163           0 :         while ((dev = next_device(&i)))
     164           0 :                 if (match(dev, data) && get_device(dev))
     165             :                         break;
     166           0 :         klist_iter_exit(&i);
     167           0 :         return dev;
     168             : }
     169             : EXPORT_SYMBOL_GPL(driver_find_device);
     170             : 
     171             : /**
     172             :  * driver_create_file - create sysfs file for driver.
     173             :  * @drv: driver.
     174             :  * @attr: driver attribute descriptor.
     175             :  */
     176          63 : int driver_create_file(struct device_driver *drv,
     177             :                        const struct driver_attribute *attr)
     178             : {
     179             :         int error;
     180             : 
     181          63 :         if (drv)
     182         126 :                 error = sysfs_create_file(&drv->p->kobj, &attr->attr);
     183             :         else
     184             :                 error = -EINVAL;
     185          63 :         return error;
     186             : }
     187             : EXPORT_SYMBOL_GPL(driver_create_file);
     188             : 
     189             : /**
     190             :  * driver_remove_file - remove sysfs file for driver.
     191             :  * @drv: driver.
     192             :  * @attr: driver attribute descriptor.
     193             :  */
     194          18 : void driver_remove_file(struct device_driver *drv,
     195             :                         const struct driver_attribute *attr)
     196             : {
     197          18 :         if (drv)
     198          18 :                 sysfs_remove_file(&drv->p->kobj, &attr->attr);
     199          18 : }
     200             : EXPORT_SYMBOL_GPL(driver_remove_file);
     201             : 
     202          21 : int driver_add_groups(struct device_driver *drv,
     203             :                       const struct attribute_group **groups)
     204             : {
     205          42 :         return sysfs_create_groups(&drv->p->kobj, groups);
     206             : }
     207             : 
     208           6 : void driver_remove_groups(struct device_driver *drv,
     209             :                           const struct attribute_group **groups)
     210             : {
     211          12 :         sysfs_remove_groups(&drv->p->kobj, groups);
     212           6 : }
     213             : 
     214             : /**
     215             :  * driver_register - register driver with bus
     216             :  * @drv: driver to register
     217             :  *
     218             :  * We pass off most of the work to the bus_add_driver() call,
     219             :  * since most of the things we have to do deal with the bus
     220             :  * structures.
     221             :  */
     222          21 : int driver_register(struct device_driver *drv)
     223             : {
     224             :         int ret;
     225             :         struct device_driver *other;
     226             : 
     227          21 :         if (!bus_is_registered(drv->bus)) {
     228           0 :                 pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",
     229             :                            drv->name, drv->bus->name);
     230           0 :                 return -EINVAL;
     231             :         }
     232             : 
     233          42 :         if ((drv->bus->probe && drv->probe) ||
     234          63 :             (drv->bus->remove && drv->remove) ||
     235          31 :             (drv->bus->shutdown && drv->shutdown))
     236           0 :                 pr_warn("Driver '%s' needs updating - please use "
     237             :                         "bus_type methods\n", drv->name);
     238             : 
     239          21 :         other = driver_find(drv->name, drv->bus);
     240          21 :         if (other) {
     241           0 :                 pr_err("Error: Driver '%s' is already registered, "
     242             :                         "aborting...\n", drv->name);
     243           0 :                 return -EBUSY;
     244             :         }
     245             : 
     246          21 :         ret = bus_add_driver(drv);
     247          21 :         if (ret)
     248             :                 return ret;
     249          42 :         ret = driver_add_groups(drv, drv->groups);
     250          21 :         if (ret) {
     251           0 :                 bus_remove_driver(drv);
     252           0 :                 return ret;
     253             :         }
     254          21 :         kobject_uevent(&drv->p->kobj, KOBJ_ADD);
     255          21 :         deferred_probe_extend_timeout();
     256             : 
     257          21 :         return ret;
     258             : }
     259             : EXPORT_SYMBOL_GPL(driver_register);
     260             : 
     261             : /**
     262             :  * driver_unregister - remove driver from system.
     263             :  * @drv: driver.
     264             :  *
     265             :  * Again, we pass off most of the work to the bus-level call.
     266             :  */
     267           6 : void driver_unregister(struct device_driver *drv)
     268             : {
     269           6 :         if (!drv || !drv->p) {
     270           0 :                 WARN(1, "Unexpected driver unregister!\n");
     271           0 :                 return;
     272             :         }
     273          12 :         driver_remove_groups(drv, drv->groups);
     274           6 :         bus_remove_driver(drv);
     275             : }
     276             : EXPORT_SYMBOL_GPL(driver_unregister);

Generated by: LCOV version 1.14