€•K¾Œsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ3/translations/zh_CN/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/zh_TW/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/it_IT/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/ja_JP/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/ko_KR/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/pt_BR/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ3/translations/sp_SP/driver-api/driver-model/porting”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒ'Porting Drivers to the New Driver Model”h]”hŒ'Porting Drivers to the New Driver Model”…”�”}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒM/var/lib/git/docbuild/linux/Documentation/driver-api/driver-model/porting.rst”h´KubhŒ paragraph”“”)�”}”(hŒPatrick Mochel”h]”hŒPatrick Mochel”…”�”}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒ7 January 2003”h]”hŒ7 January 2003”…”�”}”(hhÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒOverview”h]”hŒOverview”…”�”}”(hhéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhÌ)�”}”(hŒsPlease refer to `Documentation/driver-api/driver-model/*.rst` for definitions of various driver types and concepts.”h]”(hŒPlease refer to ”…”�”}”(hh÷h²hh³Nh´NubhŒtitle_reference”“”)�”}”(hŒ-`Documentation/driver-api/driver-model/*.rst`”h]”hŒ+Documentation/driver-api/driver-model/*.rst”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿhh÷ubhŒ6 for definitions of various driver types and concepts.”…”�”}”(hh÷h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhÌ)�”}”(hŒØ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.”h]”hŒØ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.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒÂ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.”h]”hŒÂ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.”…”�”}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒœ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::”h]”hŒ›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:”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhŒ literal_block”“”)�”}”(hŒ# mount -t sysfs sysfs /sys”h]”hŒ# mount -t sysfs sysfs /sys”…”�”}”hjEsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jCh³hÊh´Khh·h²hubhÌ)�”}”(hŒ The Process”h]”hŒ The Process”…”�”}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhÌ)�”}”(hŒHStep 0: Read include/linux/device.h for object and function definitions.”h]”hŒHStep 0: Read include/linux/device.h for object and function definitions.”…”�”}”(hjch²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K"hh·h²hubhÌ)�”}”(hŒ#Step 1: Registering the bus driver.”h]”hŒ#Step 1: Registering the bus driver.”…”�”}”(hjqh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K$hh·h²hubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hŒyDefine a struct bus_type for the bus driver:: struct bus_type pci_bus_type = { .name = "pci", }; ”h]”(hÌ)�”}”(hŒ-Define a struct bus_type for the bus driver::”h]”hŒ,Define a struct bus_type for the bus driver:”…”�”}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K'hj†ubjD)�”}”(hŒBstruct bus_type pci_bus_type = { .name = "pci", };”h]”hŒBstruct bus_type pci_bus_type = { .name = "pci", };”…”�”}”hj˜sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´K)hj†ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj�h²hh³hÊh´Nubj…)�”}”(hX£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); ”h]”(hÌ)�”}”(hŒRegister the bus type.”h]”hŒRegister the bus type.”…”�”}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K.hj¬ubhÌ)�”}”(hŒ‚This should be done in the initialization function for the bus type, which is usually the module_init(), or equivalent, function::”h]”hŒ�This should be done in the initialization function for the bus type, which is usually the module_init(), or equivalent, function:”…”�”}”(hj¾h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K0hj¬ubjD)�”}”(hŒzstatic int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } subsys_initcall(pci_driver_init);”h]”hŒzstatic int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } subsys_initcall(pci_driver_init);”…”�”}”hjÌsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´K3hj¬ubhÌ)�”}”(hŒ[The bus type may be unregistered (if the bus driver may be compiled as a module) by doing::”h]”hŒZThe bus type may be unregistered (if the bus driver may be compiled as a module) by doing:”…”�”}”(hjÚh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K;hj¬ubjD)�”}”(hŒbus_unregister(&pci_bus_type);”h]”hŒbus_unregister(&pci_bus_type);”…”�”}”hjèsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´K>hj¬ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj�h²hh³hÊh´Nubj…)�”}”(hŒ”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. ”h]”(hÌ)�”}”(hŒ&Export the bus type for others to use.”h]”hŒ&Export the bus type for others to use.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KAhjüubhÌ)�”}”(hŒkOther code may wish to reference the bus type, so declare it in a shared header file and export the symbol.”h]”hŒkOther code may wish to reference the bus type, so declare it in a shared header file and export the symbol.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KChjüubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj�h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jh³hÊh´K'hh·h²hubhÌ)�”}”(hŒFrom include/linux/pci.h::”h]”hŒFrom include/linux/pci.h:”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KFhh·h²hubjD)�”}”(hŒ$extern struct bus_type pci_bus_type;”h]”hŒ$extern struct bus_type pci_bus_type;”…”�”}”hj8sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´KHhh·h²hubhÌ)�”}”(hŒ%From file the above code appears in::”h]”hŒ$From file the above code appears in:”…”�”}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KKhh·h²hubjD)�”}”(hŒEXPORT_SYMBOL(pci_bus_type);”h]”hŒEXPORT_SYMBOL(pci_bus_type);”…”�”}”hjTsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´KMhh·h²hubj€)�”}”(hhh]”j…)�”}”(hŒ°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 ”h]”(hÌ)�”}”(hŒfThis will cause the bus to show up in /sys/bus/pci/ with two subdirectories: 'devices' and 'drivers'::”h]”hŒmThis will cause the bus to show up in /sys/bus/pci/ with two subdirectories: ‘devices’ and ‘drivers’:”…”�”}”(hjih²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KQhjeubjD)�”}”(hŒ=# tree -d /sys/bus/pci/ /sys/bus/pci/ |-- devices `-- drivers”h]”hŒ=# tree -d /sys/bus/pci/ /sys/bus/pci/ |-- devices `-- drivers”…”�”}”hjwsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´KThjeubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hjbh²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´KQhh·h²hubhÌ)�”}”(hŒStep 2: Registering Devices.”h]”hŒStep 2: Registering Devices.”…”�”}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K[hh·h²hubhÌ)�”}”(hŒƒstruct device represents a single device. It mainly contains metadata describing the relationship the device has to other entities.”h]”hŒƒstruct device represents a single device. It mainly contains metadata describing the relationship the device has to other entities.”…”�”}”(hjŸh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K]hh·h²hubj€)�”}”(hhh]”(j…)�”}”(hXÝEmbed a struct device in the bus-specific device type:: 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). ”h]”(hÌ)�”}”(hŒ7Embed a struct device in the bus-specific device type::”h]”hŒ6Embed a struct device in the bus-specific device type:”…”�”}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kahj°ubjD)�”}”(hŒostruct pci_dev { ... struct device dev; /* Generic device interface */ ... };”h]”hŒostruct pci_dev { ... struct device dev; /* Generic device interface */ ... };”…”�”}”hjÂsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Kdhj°ubhÌ)�”}”(hŒü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::”h]”hŒû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:”…”�”}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kjhj°ubjD)�”}”(hŒµ#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); }”h]”hŒµ#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); }”…”�”}”hjÞsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Kphj°ubhÌ)�”}”(hŒdThis allows the compiler to verify type-safety of the operations that are performed (which is Good).”h]”hŒdThis allows the compiler to verify type-safety of the operations that are performed (which is Good).”…”�”}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kyhj°ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj­h²hh³hÊh´Nubj…)�”}”(hXInitialize 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. ”h]”(hÌ)�”}”(hŒ&Initialize the device on registration.”h]”hŒ&Initialize the device on registration.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K}hjubhÌ)�”}”(hŒÁ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.”h]”hŒÁ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.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjubhÌ)�”}”(hŒ¬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.”h]”hŒ®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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KƒhjubhÌ)�”}”(hŒkparent is the physical parent of the device. It is important that the bus driver sets this field correctly.”h]”hŒkparent is the physical parent of the device. It is important that the bus driver sets this field correctly.”…”�”}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K‡hjubhÌ)�”}”(hXThe 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.”h]”hXThe 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.”…”�”}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KŠhjubhÌ)�”}”(hŒô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.”h]”hŒø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.”…”�”}”(hjJh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K�hjubhÌ)�”}”(hŒ—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.”h]”hŒ™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.”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K•hjubhÌ)�”}”(hŒHOptionally, the bus driver may set the device's name and release fields.”h]”hŒJOptionally, the bus driver may set the device’s name and release fields.”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K™hjubhÌ)�”}”(hŒ=The name field is an ASCII string describing the device, like”h]”hŒ=The name field is an ASCII string describing the device, like”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KœhjubhŒ block_quote”“”)�”}”(hŒ!"ATI Technologies Inc Radeon QD" ”h]”hÌ)�”}”(hŒ "ATI Technologies Inc Radeon QD"”h]”hŒ$“ATI Technologies Inc Radeon QDâ€�”…”�”}”(hjˆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kžhj„ubah}”(h]”h ]”h"]”h$]”h&]”uh1j‚h³hÊh´KžhjubhÌ)�”}”(hŒ©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.”h]”hŒ©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.”…”�”}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj­h²hh³hÊh´Nubj…)�”}”(hX<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 ”h]”(hÌ)�”}”(hŒRegister the device.”h]”hŒRegister the device.”…”�”}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¥hj°ubhÌ)�”}”(hŒhOnce the generic device has been initialized, it can be registered with the driver model core by doing::”h]”hŒgOnce the generic device has been initialized, it can be registered with the driver model core by doing:”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K§hj°ubjD)�”}”(hŒdevice_register(&dev->dev);”h]”hŒdevice_register(&dev->dev);”…”�”}”hjÐsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Kªhj°ubhÌ)�”}”(hŒ'It can later be unregistered by doing::”h]”hŒ&It can later be unregistered by doing:”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¬hj°ubjD)�”}”(hŒdevice_unregister(&dev->dev);”h]”hŒdevice_unregister(&dev->dev);”…”�”}”hjìsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´K®hj°ubhÌ)�”}”(hX�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).”h]”hX‘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).”…”�”}”(hjúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K°hj°ubhÌ)�”}”(hŒbWhen the device is registered, a directory in sysfs is created. The PCI tree in sysfs looks like::”h]”hŒaWhen the device is registered, a directory in sysfs is created. The PCI tree in sysfs looks like:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¹hj°ubjD)�”}”(hX /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”h]”hX /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”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´K¼hj°ubhÌ)�”}”(hŒ|Also, symlinks are created in the bus's 'devices' directory that point to the device's directory in the physical hierarchy::”h]”hŒƒAlso, symlinks are created in the bus’s ‘devices’ directory that point to the device’s directory in the physical hierarchy:”…”�”}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÐhj°ubjD)�”}”(hX†/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”h]”hX†/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”…”�”}”hj2sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´KÓhj°ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hj­h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´Kahh·h²hubhÌ)�”}”(hŒStep 3: Registering Drivers.”h]”hŒStep 3: Registering Drivers.”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kähh·h²hubhÌ)�”}”(hŒxstruct device_driver is a simple driver structure that contains a set of operations that the driver model core may call.”h]”hŒxstruct device_driver is a simple driver structure that contains a set of operations that the driver model core may call.”…”�”}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kæhh·h²hubj€)�”}”(hhh]”(j…)�”}”(hŒ¹Embed a struct device_driver in the bus-specific driver. Just like with devices, do something like:: struct pci_driver { ... struct device_driver driver; }; ”h]”(hÌ)�”}”(hŒ8Embed a struct device_driver in the bus-specific driver.”h]”hŒ8Embed a struct device_driver in the bus-specific driver.”…”�”}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KêhjkubhÌ)�”}”(hŒ+Just like with devices, do something like::”h]”hŒ*Just like with devices, do something like:”…”�”}”(hj}h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KìhjkubjD)�”}”(hŒHstruct pci_driver { ... struct device_driver driver; };”h]”hŒHstruct pci_driver { ... struct device_driver driver; };”…”�”}”hj‹sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Kîhjkubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hjhh²hh³hÊh´Nubj…)�”}”(hŒ¾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. ”h]”(hÌ)�”}”(hŒ(Initialize the generic driver structure.”h]”hŒ(Initialize the generic driver structure.”…”�”}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KôhjŸubhÌ)�”}”(hŒ’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.”h]”hŒ’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.”…”�”}”(hj±h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KöhjŸubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hjhh²hh³hÊh´Nubj…)�”}”(hX‡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. ”h]”(hÌ)�”}”(hŒRegister the driver.”h]”hŒRegister the driver.”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KûhjÅubhÌ)�”}”(hŒ5After the generic driver has been initialized, call::”h]”hŒ4After the generic driver has been initialized, call:”…”�”}”(hj×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KýhjÅubjD)�”}”(hŒdriver_register(&drv->driver);”h]”hŒdriver_register(&drv->driver);”…”�”}”hjåsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´KÿhjÅubhÌ)�”}”(hŒ%to register the driver with the core.”h]”hŒ%to register the driver with the core.”…”�”}”(hjóh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÅubhÌ)�”}”(hŒTWhen the driver is unregistered from the bus, unregister it from the core by doing::”h]”hŒSWhen the driver is unregistered from the bus, unregister it from the core by doing:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÅubjD)�”}”(hŒ driver_unregister(&drv->driver);”h]”hŒ driver_unregister(&drv->driver);”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´MhjÅubhÌ)�”}”(hŒmNote that this will block until all references to the driver have gone away. Normally, there will not be any.”h]”hŒmNote that this will block until all references to the driver have gone away. Normally, there will not be any.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÅubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hjhh²hh³hÊh´Nubj…)�”}”(hŒÑ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 ”h]”(hÌ)�”}”(hŒSysfs representation.”h]”hŒSysfs representation.”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj1ubhÌ)�”}”(hŒPDrivers are exported via sysfs in their bus's 'driver's directory. For example::”h]”hŒUDrivers are exported via sysfs in their bus’s ‘driver’s directory. For example:”…”�”}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj1ubjD)�”}”(hŒZ/sys/bus/pci/drivers/ |-- 3c59x |-- Ensoniq AudioPCI |-- agpgart-amdk7 |-- e100 `-- serial”h]”hŒZ/sys/bus/pci/drivers/ |-- 3c59x |-- Ensoniq AudioPCI |-- agpgart-amdk7 |-- e100 `-- serial”…”�”}”hjQsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Mhj1ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j„hjhh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´Kêhh·h²hubhÌ)�”}”(hŒ+Step 4: Define Generic Methods for Drivers.”h]”hŒ+Step 4: Define Generic Methods for Drivers.”…”�”}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhh·h²hubhÌ)�”}”(hŒÔ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.”h]”hŒÔ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.”…”�”}”(hjyh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhh·h²hubhÌ)�”}”(hXIt 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::”h]”hXIt 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:”…”�”}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hh·h²hubjD)�”}”(hXCstatic 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; }”h]”hXCstatic 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; }”…”�”}”hj•sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´M&hh·h²hubhÌ)�”}”(hŒUThe generic driver should be initialized with these methods before it is registered::”h]”hŒTThe generic driver should be initialized with these methods before it is registered:”…”�”}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M4hh·h²hubjD)�”}”(hX=/* 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);”h]”hX=/* 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);”…”�”}”hj±sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´M7hh·h²hubhÌ)�”}”(hŒ�Ideally, the bus should only initialize the fields if they are not already set. This allows the drivers to implement their own generic methods.”h]”hŒ�Ideally, the bus should only initialize the fields if they are not already set. This allows the drivers to implement their own generic methods.”…”�”}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MChh·h²hubhÌ)�”}”(hŒ'Step 5: Support generic driver binding.”h]”hŒ'Step 5: Support generic driver binding.”…”�”}”(hjÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MHhh·h²hubhÌ)�”}”(hŒÙ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.”h]”hŒÙ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.”…”�”}”(hjÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MJhh·h²hubhÌ)�”}”(hXA 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.”h]”hXA 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.”…”�”}”(hjéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MOhh·h²hubhÌ)�”}”(hŒPInstead, a bus may supply a method in struct bus_type that does the comparison::”h]”hŒOInstead, a bus may supply a method in struct bus_type that does the comparison:”…”�”}”(hj÷h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MThh·h²hubjD)�”}”(hŒ>int (*match)(struct device * dev, struct device_driver * drv);”h]”hŒ>int (*match)(struct device * dev, struct device_driver * drv);”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´MWhh·h²hubhÌ)�”}”(hŒÙmatch should return positive value if the driver supports the device, and zero otherwise. It may also return error code (for example -EPROBE_DEFER) if determining that given driver supports the device is not possible.”h]”hŒÙmatch should return positive value if the driver supports the device, and zero otherwise. It may also return error code (for example -EPROBE_DEFER) if determining that given driver supports the device is not possible.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MYhh·h²hubhÌ)�”}”(hŒ„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.”h]”hŒ†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.”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M^hh·h²hubhÌ)�”}”(hŒ˜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.”h]”hŒš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.”…”�”}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mahh·h²hubhÌ)�”}”(hŒæWhen a device is successfully bound to a driver, device->driver is 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::”h]”hŒéWhen a device is successfully bound to a driver, device->driver is 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:”…”�”}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mehh·h²hubjD)�”}”(hŒö/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”h]”hŒö/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”…”�”}”hjKsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Mjhh·h²hubhÌ)�”}”(hŒ`This driver binding should replace the existing driver binding mechanism the bus currently uses.”h]”hŒ`This driver binding should replace the existing driver binding mechanism the bus currently uses.”…”�”}”(hjYh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Muhh·h²hubhÌ)�”}”(hŒ"Step 6: Supply a hotplug callback.”h]”hŒ"Step 6: Supply a hotplug callback.”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Myhh·h²hubhÌ)�”}”(hŒÈ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.”h]”hŒÈ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.”…”�”}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M{hh·h²hubhÌ)�”}”(hŒ`The driver model core passes several arguments to userspace via environment variables, including”h]”hŒ`The driver model core passes several arguments to userspace via environment variables, including”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M€hh·h²hubj€)�”}”(hhh]”(j…)�”}”(hŒ ACTION: set to 'add' or 'remove'”h]”hÌ)�”}”(hj–h]”hŒ(ACTION: set to ‘add’ or ‘remove’”…”�”}”(hj˜h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mƒhj”ubah}”(h]”h ]”h"]”h$]”h&]”uh1j„hj‘h²hh³hÊh´Nubj…)�”}”(hŒ5DEVPATH: set to the device's physical path in sysfs. ”h]”hÌ)�”}”(hŒ4DEVPATH: set to the device's physical path in sysfs.”h]”hŒ6DEVPATH: set to the device’s physical path in sysfs.”…”�”}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M„hj«ubah}”(h]”h ]”h"]”h$]”h&]”uh1j„hj‘h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´Mƒhh·h²hubhÌ)�”}”(hŒ—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::”h]”hŒš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:”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M†hh·h²hubjD)�”}”(hŒnint (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);”h]”hŒnint (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);”…”�”}”hj×sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´MŠhh·h²hubhÌ)�”}”(hŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mœhh·h²hubjD)�”}”(hŒ‰int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *));”h]”hŒ‰int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *));”…”�”}”hjLsbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Mžhh·h²hubj€)�”}”(hhh]”j…)�”}”(hŒ Driver list. ”h]”hÌ)�”}”(hŒ Driver list.”h]”hŒ Driver list.”…”�”}”(hjah²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¢hj]ubah}”(h]”h ]”h"]”h$]”h&]”uh1j„hjZh²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´M¢hh·h²hubhÌ)�”}”(hŒ³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.”h]”hŒ³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.”…”�”}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¤hh·h²hubhÌ)�”}”(hŒ0The drivers may be iterated over, like devices::”h]”hŒ/The drivers may be iterated over, like devices:”…”�”}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¨hh·h²hubjD)�”}”(hŒ—int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *));”h]”hŒ—int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *));”…”�”}”hj—sbah}”(h]”h ]”h"]”h$]”h&]”jSjTuh1jCh³hÊh´Mªhh·h²hubhÌ)�”}”(hŒ3Please see drivers/base/bus.c for more information.”h]”hŒ3Please see drivers/base/bus.c for more information.”…”�”}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M®hh·h²hubj€)�”}”(hhh]”j…)�”}”(hŒrwsem ”h]”hÌ)�”}”(hŒrwsem”h]”hŒrwsem”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M±hj¶ubah}”(h]”h ]”h"]”h$]”h&]”uh1j„hj³h²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´M±hh·h²hubhÌ)�”}”(hŒà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.”h]”hŒà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.”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M³hh·h²hubj€)�”}”(hhh]”j…)�”}”(hŒDevice and driver fields. ”h]”hÌ)�”}”(hŒDevice and driver fields.”h]”hŒDevice and driver fields.”…”�”}”(hjéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¹hjåubah}”(h]”h ]”h"]”h$]”h&]”uh1j„hjâh²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”j(j)uh1jh³hÊh´M¹hh·h²hubhÌ)�”}”(hX_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).”h]”hX_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).”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M»hh·h²hubeh}”(h]”Œ'porting-drivers-to-the-new-driver-model”ah ]”h"]”Œ'porting drivers to the new driver model”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j<Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”jjsŒ nametypes”}”j‰sh}”jh·sŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.