Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
driver.c
Go to the documentation of this file.
1 /*
2  * driver.c - centralized device driver management
3  *
4  * Copyright (c) 2002-3 Patrick Mochel
5  * Copyright (c) 2002-3 Open Source Development Labs
6  * Copyright (c) 2007 Greg Kroah-Hartman <[email protected]>
7  * Copyright (c) 2007 Novell Inc.
8  *
9  * This file is released under the GPLv2
10  *
11  */
12 
13 #include <linux/device.h>
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/slab.h>
17 #include <linux/string.h>
18 #include "base.h"
19 
20 static struct device *next_device(struct klist_iter *i)
21 {
22  struct klist_node *n = klist_next(i);
23  struct device *dev = NULL;
24  struct device_private *dev_prv;
25 
26  if (n) {
27  dev_prv = to_device_private_driver(n);
28  dev = dev_prv->device;
29  }
30  return dev;
31 }
32 
43  void *data, int (*fn)(struct device *, void *))
44 {
45  struct klist_iter i;
46  struct device *dev;
47  int error = 0;
48 
49  if (!drv)
50  return -EINVAL;
51 
52  klist_iter_init_node(&drv->p->klist_devices, &i,
53  start ? &start->p->knode_driver : NULL);
54  while ((dev = next_device(&i)) && !error)
55  error = fn(dev, data);
56  klist_iter_exit(&i);
57  return error;
58 }
60 
77  struct device *start, void *data,
78  int (*match)(struct device *dev, void *data))
79 {
80  struct klist_iter i;
81  struct device *dev;
82 
83  if (!drv || !drv->p)
84  return NULL;
85 
86  klist_iter_init_node(&drv->p->klist_devices, &i,
87  (start ? &start->p->knode_driver : NULL));
88  while ((dev = next_device(&i)))
89  if (match(dev, data) && get_device(dev))
90  break;
91  klist_iter_exit(&i);
92  return dev;
93 }
95 
102  const struct driver_attribute *attr)
103 {
104  int error;
105  if (drv)
106  error = sysfs_create_file(&drv->p->kobj, &attr->attr);
107  else
108  error = -EINVAL;
109  return error;
110 }
112 
119  const struct driver_attribute *attr)
120 {
121  if (drv)
122  sysfs_remove_file(&drv->p->kobj, &attr->attr);
123 }
125 
126 static int driver_add_groups(struct device_driver *drv,
127  const struct attribute_group **groups)
128 {
129  int error = 0;
130  int i;
131 
132  if (groups) {
133  for (i = 0; groups[i]; i++) {
134  error = sysfs_create_group(&drv->p->kobj, groups[i]);
135  if (error) {
136  while (--i >= 0)
137  sysfs_remove_group(&drv->p->kobj,
138  groups[i]);
139  break;
140  }
141  }
142  }
143  return error;
144 }
145 
146 static void driver_remove_groups(struct device_driver *drv,
147  const struct attribute_group **groups)
148 {
149  int i;
150 
151  if (groups)
152  for (i = 0; groups[i]; i++)
153  sysfs_remove_group(&drv->p->kobj, groups[i]);
154 }
155 
165 {
166  int ret;
167  struct device_driver *other;
168 
169  BUG_ON(!drv->bus->p);
170 
171  if ((drv->bus->probe && drv->probe) ||
172  (drv->bus->remove && drv->remove) ||
173  (drv->bus->shutdown && drv->shutdown))
174  printk(KERN_WARNING "Driver '%s' needs updating - please use "
175  "bus_type methods\n", drv->name);
176 
177  other = driver_find(drv->name, drv->bus);
178  if (other) {
179  printk(KERN_ERR "Error: Driver '%s' is already registered, "
180  "aborting...\n", drv->name);
181  return -EBUSY;
182  }
183 
184  ret = bus_add_driver(drv);
185  if (ret)
186  return ret;
187  ret = driver_add_groups(drv, drv->groups);
188  if (ret) {
189  bus_remove_driver(drv);
190  return ret;
191  }
192  kobject_uevent(&drv->p->kobj, KOBJ_ADD);
193 
194  return ret;
195 }
197 
205 {
206  if (!drv || !drv->p) {
207  WARN(1, "Unexpected driver unregister!\n");
208  return;
209  }
210  driver_remove_groups(drv, drv->groups);
211  bus_remove_driver(drv);
212 }
214 
227 struct device_driver *driver_find(const char *name, struct bus_type *bus)
228 {
229  struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
230  struct driver_private *priv;
231 
232  if (k) {
233  /* Drop reference added by kset_find_obj() */
234  kobject_put(k);
235  priv = to_driver(k);
236  return priv->driver;
237  }
238  return NULL;
239 }