Blame view

Documentation/driver-model/porting.txt 12.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  
  Porting Drivers to the New Driver Model
  
  Patrick Mochel
  
  7 January 2003
  
  
  Overview
  
  Please refer to Documentation/driver-model/*.txt for definitions of
  various driver types and concepts. 
  
  Most of the work of porting devices drivers to the new model happens
  at the bus driver layer. This was intentional, to minimize the
  negative effect on kernel drivers, and to allow a gradual transition
  of bus drivers.
  
  In a nutshell, the driver model consists of a set of objects that can
  be embedded in larger, bus-specific objects. Fields in these generic
  objects can replace fields in the bus-specific objects. 
  
  The generic objects must be registered with the driver model core. By
  doing so, they will exported via the sysfs filesystem. sysfs can be
  mounted by doing 
  
  	# mount -t sysfs sysfs /sys
  
  
  
  The Process
  
  Step 0: Read include/linux/device.h for object and function definitions. 
  
  Step 1: Registering the bus driver. 
  
  
  - Define a struct bus_type for the bus driver.
  
  struct bus_type pci_bus_type = {
          .name           = "pci",
  };
  
  
  - Register the bus type.
    This should be done in the initialization function for the bus type,
    which is usually the module_init(), or equivalent, function. 
  
  static int __init pci_driver_init(void)
  {
          return bus_register(&pci_bus_type);
  }
  
  subsys_initcall(pci_driver_init);
  
  
    The bus type may be unregistered (if the bus driver may be compiled
    as a module) by doing:
  
       bus_unregister(&pci_bus_type);
  
  
  - Export the bus type for others to use. 
  
    Other code may wish to reference the bus type, so declare it in a 
    shared header file and export the symbol.
  
  From include/linux/pci.h:
  
  extern struct bus_type pci_bus_type;
  
  
  From file the above code appears in:
  
  EXPORT_SYMBOL(pci_bus_type);
  
  
  
  - This will cause the bus to show up in /sys/bus/pci/ with two
    subdirectories: 'devices' and 'drivers'.
  
  # tree -d /sys/bus/pci/
  /sys/bus/pci/
  |-- devices
  `-- drivers
  
  
  
  Step 2: Registering Devices. 
  
  struct device represents a single device. It mainly contains metadata
  describing the relationship the device has to other entities. 
5d3f083d8   Matt LaPlante   Fix typos in /Doc...
93
  - Embed a struct device in the bus-specific device type. 
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  
  
  struct pci_dev {
         ...
         struct  device  dev;            /* Generic device interface */
         ...
  };
  
    It is recommended that the generic device not be the first item in 
    the struct to discourage programmers from doing mindless casts
    between the object types. Instead macros, or inline functions,
    should be created to convert from the generic object type.
  
  
  #define to_pci_dev(n) container_of(n, struct pci_dev, dev)
  
  or 
  
  static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
  {
  	return container_of(n, struct pci_dev, dev);
  }
  
    This allows the compiler to verify type-safety of the operations 
    that are performed (which is Good).
  
  
  - Initialize the device on registration.
  
    When devices are discovered or registered with the bus type, the 
    bus driver should initialize the generic device. The most important
    things to initialize are the bus_id, parent, and bus fields.
  
    The bus_id is an ASCII string that contains the device's address on
    the bus. The format of this string is bus-specific. This is
    necessary for representing devices in sysfs. 
  
    parent is the physical parent of the device. It is important that
    the bus driver sets this field correctly. 
  
    The driver model maintains an ordered list of devices that it uses
    for power management. This list must be in order to guarantee that
    devices are shutdown before their physical parents, and vice versa.
    The order of this list is determined by the parent of registered
    devices.
  
    Also, the location of the device's sysfs directory depends on a
    device's parent. sysfs exports a directory structure that mirrors 
    the device hierarchy. Accurately setting the parent guarantees that
    sysfs will accurately represent the hierarchy.
  
    The device's bus field is a pointer to the bus type the device
    belongs to. This should be set to the bus_type that was declared
    and initialized before. 
  
    Optionally, the bus driver may set the device's name and release
    fields.
  
    The name field is an ASCII string describing the device, like
  
       "ATI Technologies Inc Radeon QD"
  
    The release field is a callback that the driver model core calls 
    when the device has been removed, and all references to it have 
    been released. More on this in a moment.
  
  
  - Register the device. 
  
    Once the generic device has been initialized, it can be registered
    with the driver model core by doing:
  
         device_register(&dev->dev);
  
    It can later be unregistered by doing: 
  
         device_unregister(&dev->dev);
  
    This should happen on buses that support hotpluggable devices. 
    If a bus driver unregisters a device, it should not immediately free
    it. It should instead wait for the driver model core to call the 
    device's release method, then free the bus-specific object. 
    (There may be other code that is currently referencing the device
    structure, and it would be rude to free the device while that is 
    happening).
  
  
    When the device is registered, a directory in sysfs is created. 
    The PCI tree in sysfs looks like: 
  
  /sys/devices/pci0/
  |-- 00:00.0
  |-- 00:01.0
  |   `-- 01:00.0
  |-- 00:02.0
  |   `-- 02:1f.0
  |       `-- 03:00.0
  |-- 00:1e.0
  |   `-- 04:04.0
  |-- 00:1f.0
  |-- 00:1f.1
  |   |-- ide0
  |   |   |-- 0.0
  |   |   `-- 0.1
  |   `-- ide1
  |       `-- 1.0
  |-- 00:1f.2
  |-- 00:1f.3
  `-- 00:1f.5
  
    Also, symlinks are created in the bus's 'devices' directory
    that point to the device's directory in the physical hierarchy. 
  
  /sys/bus/pci/devices/
  |-- 00:00.0 -> ../../../devices/pci0/00:00.0
  |-- 00:01.0 -> ../../../devices/pci0/00:01.0
  |-- 00:02.0 -> ../../../devices/pci0/00:02.0
  |-- 00:1e.0 -> ../../../devices/pci0/00:1e.0
  |-- 00:1f.0 -> ../../../devices/pci0/00:1f.0
  |-- 00:1f.1 -> ../../../devices/pci0/00:1f.1
  |-- 00:1f.2 -> ../../../devices/pci0/00:1f.2
  |-- 00:1f.3 -> ../../../devices/pci0/00:1f.3
  |-- 00:1f.5 -> ../../../devices/pci0/00:1f.5
  |-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0
  |-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0
  |-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0
  `-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0
  
  
  
  Step 3: Registering Drivers.
  
  struct device_driver is a simple driver structure that contains a set
  of operations that the driver model core may call. 
  
  
  - Embed a struct device_driver in the bus-specific driver. 
  
    Just like with devices, do something like:
  
  struct pci_driver {
         ...
         struct device_driver    driver;
  };
  
  
  - Initialize the generic driver structure. 
  
    When the driver registers with the bus (e.g. doing pci_register_driver()),
    initialize the necessary fields of the driver: the name and bus
    fields. 
  
  
  - Register the driver.
  
    After the generic driver has been initialized, call
  
  	driver_register(&drv->driver);
  
    to register the driver with the core.
  
    When the driver is unregistered from the bus, unregister it from the
    core by doing:
  
          driver_unregister(&drv->driver);
  
    Note that this will block until all references to the driver have
    gone away. Normally, there will not be any.
  
  
  - Sysfs representation.
  
    Drivers are exported via sysfs in their bus's 'driver's directory. 
    For example:
  
  /sys/bus/pci/drivers/
  |-- 3c59x
  |-- Ensoniq AudioPCI
  |-- agpgart-amdk7
  |-- e100
  `-- serial
  
  
  Step 4: Define Generic Methods for Drivers.
  
  struct device_driver defines a set of operations that the driver model
  core calls. Most of these operations are probably similar to
  operations the bus already defines for drivers, but taking different
  parameters. 
  
  It would be difficult and tedious to force every driver on a bus to
  simultaneously convert their drivers to generic format. Instead, the
  bus driver should define single instances of the generic methods that
  forward call to the bus-specific drivers. For instance: 
  
  
  static int pci_device_remove(struct device * dev)
  {
          struct pci_dev * pci_dev = to_pci_dev(dev);
          struct pci_driver * drv = pci_dev->driver;
  
          if (drv) {
                  if (drv->remove)
                          drv->remove(pci_dev);
                  pci_dev->driver = NULL;
          }
          return 0;
  }
  
  
  The generic driver should be initialized with these methods before it
  is registered. 
  
          /* initialize common driver fields */
          drv->driver.name = drv->name;
          drv->driver.bus = &pci_bus_type;
          drv->driver.probe = pci_device_probe;
          drv->driver.resume = pci_device_resume;
          drv->driver.suspend = pci_device_suspend;
          drv->driver.remove = pci_device_remove;
  
          /* register with core */
          driver_register(&drv->driver);
  
  
  Ideally, the bus should only initialize the fields if they are not
  already set. This allows the drivers to implement their own generic
  methods. 
  
  
  Step 5: Support generic driver binding. 
  
  The model assumes that a device or driver can be dynamically
  registered with the bus at any time. When registration happens,
  devices must be bound to a driver, or drivers must be bound to all
  devices that it supports. 
  
  A driver typically contains a list of device IDs that it supports. The
  bus driver compares these IDs to the IDs of devices registered with it. 
  The format of the device IDs, and the semantics for comparing them are
  bus-specific, so the generic model does attempt to generalize them. 
  
  Instead, a bus may supply a method in struct bus_type that does the
  comparison: 
  
    int (*match)(struct device * dev, struct device_driver * drv);
  
  match should return '1' if the driver supports the device, and '0'
  otherwise. 
  
  When a device is registered, the bus's list of drivers is iterated
  over. bus->match() is called for each one until a match is found. 
  
  When a driver is registered, the bus's list of devices is iterated
  over. bus->match() is called for each device that is not already
  claimed by a driver. 
2a7ff1fed   Erik Hovland   [PATCH] changes d...
350
  When a device is successfully bound to a driver, device->driver is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  set, the device is added to a per-driver list of devices, and a
  symlink is created in the driver's sysfs directory that points to the
  device's physical directory:
  
  /sys/bus/pci/drivers/
  |-- 3c59x
  |   `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0
  |-- Ensoniq AudioPCI
  |-- agpgart-amdk7
  |   `-- 00:00.0 -> ../../../../devices/pci0/00:00.0
  |-- e100
  |   `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0
  `-- serial
  
  
  This driver binding should replace the existing driver binding
  mechanism the bus currently uses. 
  
  
  Step 6: Supply a hotplug callback.
  
  Whenever a device is registered with the driver model core, the
  userspace program /sbin/hotplug is called to notify userspace. 
  Users can define actions to perform when a device is inserted or
  removed. 
  
  The driver model core passes several arguments to userspace via
  environment variables, including
  
  - ACTION: set to 'add' or 'remove'
  - DEVPATH: set to the device's physical path in sysfs. 
  
  A bus driver may also supply additional parameters for userspace to
  consume. To do this, a bus must implement the 'hotplug' method in
  struct bus_type:
  
       int (*hotplug) (struct device *dev, char **envp, 
                       int num_envp, char *buffer, int buffer_size);
  
  This is called immediately before /sbin/hotplug is executed. 
  
  
  Step 7: Cleaning up the bus driver.
  
  The generic bus, device, and driver structures provide several fields
  that can replace those defined privately to the bus driver. 
  
  - Device list.
  
  struct bus_type contains a list of all devices registered with the bus
  type. This includes all devices on all instances of that bus type.
  An internal list that the bus uses may be removed, in favor of using
  this one.
  
  The core provides an iterator to access these devices. 
  
  int bus_for_each_dev(struct bus_type * bus, struct device * start, 
                       void * data, int (*fn)(struct device *, void *));
  
  
  - Driver list.
  
  struct bus_type also contains a list of all drivers registered with
  it. An internal list of drivers that the bus driver maintains may 
  be removed in favor of using the generic one. 
  
  The drivers may be iterated over, like devices: 
  
  int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
                       void * data, int (*fn)(struct device_driver *, void *));
  
  
  Please see drivers/base/bus.c for more information.
  
  
  - rwsem 
  
  struct bus_type contains an rwsem that protects all core accesses to
  the device and driver lists. This can be used by the bus driver
  internally, and should be used when accessing the device or driver
  lists the bus maintains. 
  
  
  - Device and driver fields. 
  
  Some of the fields in struct device and struct device_driver duplicate
  fields in the bus-specific representations of these objects. Feel free
  to remove the bus-specific ones and favor the generic ones. Note
  though, that this will likely mean fixing up all the drivers that
  reference the bus-specific fields (though those should all be 1-line
  changes).