sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/translations/zh_CN/PCI/pcimodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/zh_TW/PCI/pcimodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/it_IT/PCI/pcimodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ja_JP/PCI/pcimodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ko_KR/PCI/pcimodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/sp_SP/PCI/pcimodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhh5/var/lib/git/docbuild/linux/Documentation/PCI/pci.rsthKubhsection)}(hhh](htitle)}(hHow To Write Linux PCI Driversh]hHow To Write Linux PCI Drivers}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh field_list)}(hhh]hfield)}(hhh](h field_name)}(hAuthorsh]hAuthors}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(hH- Martin Mares - Grant Grundler h]h bullet_list)}(hhh](h list_item)}(hMartin Mares h]h paragraph)}(hhh](hMartin Mares <}(hhhhhNhNubh reference)}(h mj@ucw.czh]h mj@ucw.cz}(hhhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:mj@ucw.czuh1hhhubh>}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h+Grant Grundler h]h)}(h*Grant Grundler h](hGrant Grundler <}(hj#hhhNhNubh)}(hgrundler@parisc-linux.orgh]hgrundler@parisc-linux.org}(hj+hhhNhNubah}(h]h ]h"]h$]h&]refuri mailto:grundler@parisc-linux.orguh1hhj#ubh>}(hj#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]bullet-uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(hX{The world of PCI is vast and full of (mostly unpleasant) surprises. Since each CPU architecture implements different chip-sets and PCI devices have different requirements (erm, "features"), the result is the PCI support in the Linux kernel is not as trivial as one would wish. This short paper tries to introduce all potential driver authors to Linux APIs for PCI device drivers.h]hXThe world of PCI is vast and full of (mostly unpleasant) surprises. Since each CPU architecture implements different chip-sets and PCI devices have different requirements (erm, “features”), the result is the PCI support in the Linux kernel is not as trivial as one would wish. This short paper tries to introduce all potential driver authors to Linux APIs for PCI device drivers.}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hA more complete resource is the third edition of "Linux Device Drivers" by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. LDD3 is available for free (under Creative Commons License) from: https://lwn.net/Kernel/LDD3/.h](hA more complete resource is the third edition of “Linux Device Drivers” by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. LDD3 is available for free (under Creative Commons License) from: }(hjshhhNhNubh)}(hhttps://lwn.net/Kernel/LDD3/h]hhttps://lwn.net/Kernel/LDD3/}(hj{hhhNhNubah}(h]h ]h"]h$]h&]refurij}uh1hhjsubh.}(hjshhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hHowever, keep in mind that all documents are subject to "bit rot". Refer to the source code if things are not working as described here.h]hHowever, keep in mind that all documents are subject to “bit rot”. Refer to the source code if things are not working as described here.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hPlease send questions/comments/patches about Linux PCI API to the "Linux PCI" mailing list.h](hSPlease send questions/comments/patches about Linux PCI API to the “Linux PCI” <}(hjhhhNhNubh)}(h"linux-pci@atrey.karlin.mff.cuni.czh]h"linux-pci@atrey.karlin.mff.cuni.cz}(hjhhhNhNubah}(h]h ]h"]h$]h&]refuri)mailto:linux-pci@atrey.karlin.mff.cuni.czuh1hhjubh> mailing list.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(hStructure of PCI driversh]hStructure of PCI drivers}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hPCI drivers "discover" PCI devices in a system via pci_register_driver(). Actually, it's the other way around. When the PCI generic code discovers a new device, the driver with a matching "description" will be notified. Details on this below.h]hPCI drivers “discover” PCI devices in a system via pci_register_driver(). Actually, it’s the other way around. When the PCI generic code discovers a new device, the driver with a matching “description” will be notified. Details on this below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hXUpci_register_driver() leaves most of the probing for devices to the PCI layer and supports online insertion/removal of devices [thus supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver]. pci_register_driver() call requires passing in a table of function pointers and thus dictates the high level structure of a driver.h]hXUpci_register_driver() leaves most of the probing for devices to the PCI layer and supports online insertion/removal of devices [thus supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver]. pci_register_driver() call requires passing in a table of function pointers and thus dictates the high level structure of a driver.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hjhhubh)}(hOnce the driver knows about a PCI device and takes ownership, the driver generally needs to perform the following initialization:h]hOnce the driver knows about a PCI device and takes ownership, the driver generally needs to perform the following initialization:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK*hjhhubh block_quote)}(hXi- Enable the device - Request MMIO/IOP resources - Set the DMA mask size (for both coherent and streaming DMA) - Allocate and initialize shared control data (pci_allocate_coherent()) - Access device configuration space (if needed) - Register IRQ handler (request_irq()) - Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) - Enable DMA/processing engines h]h)}(hhh](h)}(hEnable the deviceh]h)}(hj h]hEnable the device}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK-hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hRequest MMIO/IOP resourcesh]h)}(hj!h]hRequest MMIO/IOP resources}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h;Set the DMA mask size (for both coherent and streaming DMA)h]h)}(hj8h]h;Set the DMA mask size (for both coherent and streaming DMA)}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hj6ubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hEAllocate and initialize shared control data (pci_allocate_coherent())h]h)}(hjOh]hEAllocate and initialize shared control data (pci_allocate_coherent())}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK0hjMubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h-Access device configuration space (if needed)h]h)}(hjfh]h-Access device configuration space (if needed)}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK1hjdubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h$Register IRQ handler (request_irq())h]h)}(hj}h]h$Register IRQ handler (request_irq())}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK2hj{ubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h8Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)h]h)}(hjh]h8Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hEnable DMA/processing engines h]h)}(hEnable DMA/processing enginesh]hEnable DMA/processing engines}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK4hjubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhK-hjubah}(h]h ]h"]h$]h&]uh1jhhhK-hjhhubh)}(hvWhen done using the device, and perhaps the module needs to be unloaded, the driver needs to take the following steps:h]hvWhen done using the device, and perhaps the module needs to be unloaded, the driver needs to take the following steps:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK6hjhhubj)}(hX- Disable the device from generating IRQs - Release the IRQ (free_irq()) - Stop all DMA activity - Release DMA buffers (both streaming and coherent) - Unregister from other subsystems (e.g. scsi or netdev) - Release MMIO/IOP resources - Disable the device h]h)}(hhh](h)}(h'Disable the device from generating IRQsh]h)}(hjh]h'Disable the device from generating IRQs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK9hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hRelease the IRQ (free_irq())h]h)}(hjh]hRelease the IRQ (free_irq())}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK:hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hStop all DMA activityh]h)}(hjh]hStop all DMA activity}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h1Release DMA buffers (both streaming and coherent)h]h)}(hj)h]h1Release DMA buffers (both streaming and coherent)}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hRelease MMIO/IOP resourcesh]h)}(hjWh]hRelease MMIO/IOP resources}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK>hjUubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hDisable the device h]h)}(hDisable the deviceh]hDisable the device}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK?hjlubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhK9hjubah}(h]h ]h"]h$]h&]uh1jhhhK9hjhhubh)}(hhMost of these topics are covered in the following sections. For the rest look at LDD3 or .h]hhMost of these topics are covered in the following sections. For the rest look at LDD3 or .}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhjhhubh)}(hIf the PCI subsystem is not configured (CONFIG_PCI is not set), most of the PCI functions described below are defined as inline functions either completely empty or just returning an appropriate error codes to avoid lots of ifdefs in the drivers.h]hIf the PCI subsystem is not configured (CONFIG_PCI is not set), most of the PCI functions described below are defined as inline functions either completely empty or just returning an appropriate error codes to avoid lots of ifdefs in the drivers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKDhjhhubeh}(h]structure-of-pci-driversah ]h"]structure of pci driversah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hpci_register_driver() callh]hpci_register_driver() call}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKKubh)}(hPCI device drivers call ``pci_register_driver()`` during their initialization with a pointer to a structure describing the driver (``struct pci_driver``):h](hPCI device drivers call }(hjhhhNhNubhliteral)}(h``pci_register_driver()``h]hpci_register_driver()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhR during their initialization with a pointer to a structure describing the driver (}(hjhhhNhNubj)}(h``struct pci_driver``h]hstruct pci_driver}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh):}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKMhjhhubhindex)}(hhh]h}(h]h ]h"]h$]h&]entries](singlepci_driver (C struct) c.pci_driverhNtauh1jhjhhhNhNubhdesc)}(hhh](hdesc_signature)}(h pci_driverh]hdesc_signature_line)}(hstruct pci_driverh](hdesc_sig_keyword)}(hstructh]hstruct}(hjhhhNhNubah}(h]h ]kah"]h$]h&]uh1jhjhhhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMubhdesc_sig_space)}(h h]h }(hj/hhhNhNubah}(h]h ]wah"]h$]h&]uh1j-hjhhhj,hMubh desc_name)}(h pci_driverh]h desc_sig_name)}(hjh]h pci_driver}(hjFhhhNhNubah}(h]h ]nah"]h$]h&]uh1jDhj@ubah}(h]h ](sig-namedescnameeh"]h$]h&]hhuh1j>hjhhhj,hMubeh}(h]h ]h"]h$]h&]hh add_permalinkuh1jsphinx_line_type declaratorhjhhhj,hMubah}(h]jah ](sig sig-objecteh"]h$]h&] is_multiline _toc_parts) _toc_namehuh1jhj,hMhj hhubh desc_content)}(hhh]h)}(hPCI driver structureh]hPCI driver structure}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjrhhubah}(h]h ]h"]h$]h&]uh1jphj hhhj,hMubeh}(h]h ](cstructeh"]h$]h&]domainjobjtypejdesctypejnoindex noindexentrynocontentsentryuh1j hhhjhNhNubh container)}(hX **Definition**:: struct pci_driver { const char *name; const struct pci_device_id *id_table; int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); void (*remove)(struct pci_dev *dev); int (*suspend)(struct pci_dev *dev, pm_message_t state); int (*resume)(struct pci_dev *dev); void (*shutdown)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf); const struct pci_error_handlers *err_handler; const struct attribute_group **groups; const struct attribute_group **dev_groups; struct device_driver driver; struct pci_dynids dynids; bool driver_managed_dma; }; **Members** ``name`` Driver name. ``id_table`` Pointer to table of device IDs the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...). ``probe`` This probing function gets called (during execution of pci_register_driver() for already existing devices or later if a new device gets inserted) for all PCI devices which match the ID table and are not "owned" by the other drivers yet. This function gets passed a "struct pci_dev \*" for each device whose entry in the ID table matches the device. The probe function returns zero when the driver chooses to take "ownership" of the device or an error code (negative number) otherwise. The probe function always gets called from process context, so it can sleep. ``remove`` The remove() function gets called whenever a device being handled by this driver is removed (either during deregistration of the driver or when it's manually pulled out of a hot-pluggable slot). The remove function always gets called from process context, so it can sleep. ``suspend`` Put device into low power state. ``resume`` Wake device from low power state. (Please see Documentation/power/pci.rst for descriptions of PCI Power Management and the related functions.) ``shutdown`` Hook into reboot_notifier_list (kernel/sys.c). Intended to stop any idling DMA operations. Useful for enabling wake-on-lan (NIC) or changing the power state of a device before reboot. e.g. drivers/net/e100.c. ``sriov_configure`` Optional driver callback to allow configuration of number of VFs to enable via sysfs "sriov_numvfs" file. ``sriov_set_msix_vec_count`` PF Driver callback to change number of MSI-X vectors on a VF. Triggered via sysfs "sriov_vf_msix_count". This will change MSI-X Table Size in the VF Message Control registers. ``sriov_get_vf_total_msix`` PF driver callback to get the total number of MSI-X vectors available for distribution to the VFs. ``err_handler`` See Documentation/PCI/pci-error-recovery.rst ``groups`` Sysfs attribute groups. ``dev_groups`` Attributes attached to the device that will be created once it is bound to the driver. ``driver`` Driver model structure. ``dynids`` List of dynamically added device IDs. ``driver_managed_dma`` Device driver doesn't use kernel DMA API for DMA. For most device drivers, no need to care about this flag as long as all DMAs are handled through the kernel DMA API. For some special ones, for example VFIO drivers, they know how to manage the DMA themselves and set this flag so that the IOMMU layer will allow them to setup and manage their own I/O address space.h](h)}(h**Definition**::h](hstrong)}(h**Definition**h]h Definition}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubh literal_block)}(hXstruct pci_driver { const char *name; const struct pci_device_id *id_table; int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); void (*remove)(struct pci_dev *dev); int (*suspend)(struct pci_dev *dev, pm_message_t state); int (*resume)(struct pci_dev *dev); void (*shutdown)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf); const struct pci_error_handlers *err_handler; const struct attribute_group **groups; const struct attribute_group **dev_groups; struct device_driver driver; struct pci_dynids dynids; bool driver_managed_dma; };h]hXstruct pci_driver { const char *name; const struct pci_device_id *id_table; int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); void (*remove)(struct pci_dev *dev); int (*suspend)(struct pci_dev *dev, pm_message_t state); int (*resume)(struct pci_dev *dev); void (*shutdown)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf); const struct pci_error_handlers *err_handler; const struct attribute_group **groups; const struct attribute_group **dev_groups; struct device_driver driver; struct pci_dynids dynids; bool driver_managed_dma; };}hjsbah}(h]h ]h"]h$]h&]hhuh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubh)}(h **Members**h]j)}(hjh]hMembers}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubhdefinition_list)}(hhh](hdefinition_list_item)}(h``name`` Driver name. h](hterm)}(h``name``h]j)}(hjh]hname}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubh definition)}(hhh]h)}(h Driver name.h]h Driver name.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hMhj ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhj hMhjubj)}(h``id_table`` Pointer to table of device IDs the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...). h](j)}(h ``id_table``h]j)}(hj0h]hid_table}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj.ubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhj*ubj )}(hhh]h)}(hPointer to table of device IDs the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...).h]hPointer to table of device IDs the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...).}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjFubah}(h]h ]h"]h$]h&]uh1j hj*ubeh}(h]h ]h"]h$]h&]uh1jhjEhMhjubj)}(hX<``probe`` This probing function gets called (during execution of pci_register_driver() for already existing devices or later if a new device gets inserted) for all PCI devices which match the ID table and are not "owned" by the other drivers yet. This function gets passed a "struct pci_dev \*" for each device whose entry in the ID table matches the device. The probe function returns zero when the driver chooses to take "ownership" of the device or an error code (negative number) otherwise. The probe function always gets called from process context, so it can sleep. h](j)}(h ``probe``h]j)}(hjjh]hprobe}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjdubj )}(hhh]h)}(hX1This probing function gets called (during execution of pci_register_driver() for already existing devices or later if a new device gets inserted) for all PCI devices which match the ID table and are not "owned" by the other drivers yet. This function gets passed a "struct pci_dev \*" for each device whose entry in the ID table matches the device. The probe function returns zero when the driver chooses to take "ownership" of the device or an error code (negative number) otherwise. The probe function always gets called from process context, so it can sleep.h]hX=This probing function gets called (during execution of pci_register_driver() for already existing devices or later if a new device gets inserted) for all PCI devices which match the ID table and are not “owned” by the other drivers yet. This function gets passed a “struct pci_dev *” for each device whose entry in the ID table matches the device. The probe function returns zero when the driver chooses to take “ownership” of the device or an error code (negative number) otherwise. The probe function always gets called from process context, so it can sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjdubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(hX``remove`` The remove() function gets called whenever a device being handled by this driver is removed (either during deregistration of the driver or when it's manually pulled out of a hot-pluggable slot). The remove function always gets called from process context, so it can sleep. h](j)}(h ``remove``h]j)}(hjh]hremove}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hXThe remove() function gets called whenever a device being handled by this driver is removed (either during deregistration of the driver or when it's manually pulled out of a hot-pluggable slot). The remove function always gets called from process context, so it can sleep.h]hXThe remove() function gets called whenever a device being handled by this driver is removed (either during deregistration of the driver or when it’s manually pulled out of a hot-pluggable slot). The remove function always gets called from process context, so it can sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h-``suspend`` Put device into low power state. h](j)}(h ``suspend``h]j)}(hjh]hsuspend}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(h Put device into low power state.h]h Put device into low power state.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h``resume`` Wake device from low power state. (Please see Documentation/power/pci.rst for descriptions of PCI Power Management and the related functions.) h](j)}(h ``resume``h]j)}(hjh]hresume}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hWake device from low power state. (Please see Documentation/power/pci.rst for descriptions of PCI Power Management and the related functions.)h]hWake device from low power state. (Please see Documentation/power/pci.rst for descriptions of PCI Power Management and the related functions.)}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhj-ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhj,hMhjubj)}(h``shutdown`` Hook into reboot_notifier_list (kernel/sys.c). Intended to stop any idling DMA operations. Useful for enabling wake-on-lan (NIC) or changing the power state of a device before reboot. e.g. drivers/net/e100.c. h](j)}(h ``shutdown``h]j)}(hjQh]hshutdown}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1jhjOubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjKubj )}(hhh]h)}(hHook into reboot_notifier_list (kernel/sys.c). Intended to stop any idling DMA operations. Useful for enabling wake-on-lan (NIC) or changing the power state of a device before reboot. e.g. drivers/net/e100.c.h]hHook into reboot_notifier_list (kernel/sys.c). Intended to stop any idling DMA operations. Useful for enabling wake-on-lan (NIC) or changing the power state of a device before reboot. e.g. drivers/net/e100.c.}(hjjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjgubah}(h]h ]h"]h$]h&]uh1j hjKubeh}(h]h ]h"]h$]h&]uh1jhjfhMhjubj)}(h~``sriov_configure`` Optional driver callback to allow configuration of number of VFs to enable via sysfs "sriov_numvfs" file. h](j)}(h``sriov_configure``h]j)}(hjh]hsriov_configure}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hiOptional driver callback to allow configuration of number of VFs to enable via sysfs "sriov_numvfs" file.h]hmOptional driver callback to allow configuration of number of VFs to enable via sysfs “sriov_numvfs” file.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h``sriov_set_msix_vec_count`` PF Driver callback to change number of MSI-X vectors on a VF. Triggered via sysfs "sriov_vf_msix_count". This will change MSI-X Table Size in the VF Message Control registers. h](j)}(h``sriov_set_msix_vec_count``h]j)}(hjh]hsriov_set_msix_vec_count}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hPF Driver callback to change number of MSI-X vectors on a VF. Triggered via sysfs "sriov_vf_msix_count". This will change MSI-X Table Size in the VF Message Control registers.h]hPF Driver callback to change number of MSI-X vectors on a VF. Triggered via sysfs “sriov_vf_msix_count”. This will change MSI-X Table Size in the VF Message Control registers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h``sriov_get_vf_total_msix`` PF driver callback to get the total number of MSI-X vectors available for distribution to the VFs. h](j)}(h``sriov_get_vf_total_msix``h]j)}(hjh]hsriov_get_vf_total_msix}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hbPF driver callback to get the total number of MSI-X vectors available for distribution to the VFs.h]hbPF driver callback to get the total number of MSI-X vectors available for distribution to the VFs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h=``err_handler`` See Documentation/PCI/pci-error-recovery.rst h](j)}(h``err_handler``h]j)}(hj9h]h err_handler}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj7ubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhj3ubj )}(hhh]h)}(h,See Documentation/PCI/pci-error-recovery.rsth]h,See Documentation/PCI/pci-error-recovery.rst}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjNhMhjOubah}(h]h ]h"]h$]h&]uh1j hj3ubeh}(h]h ]h"]h$]h&]uh1jhjNhMhjubj)}(h#``groups`` Sysfs attribute groups. h](j)}(h ``groups``h]j)}(hjrh]hgroups}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1jhjpubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjlubj )}(hhh]h)}(hSysfs attribute groups.h]hSysfs attribute groups.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMhjubah}(h]h ]h"]h$]h&]uh1j hjlubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(hf``dev_groups`` Attributes attached to the device that will be created once it is bound to the driver. h](j)}(h``dev_groups``h]j)}(hjh]h dev_groups}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hVAttributes attached to the device that will be created once it is bound to the driver.h]hVAttributes attached to the device that will be created once it is bound to the driver.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h#``driver`` Driver model structure. h](j)}(h ``driver``h]j)}(hjh]hdriver}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(hDriver model structure.h]hDriver model structure.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhjhMhjubj)}(h1``dynids`` List of dynamically added device IDs. h](j)}(h ``dynids``h]j)}(hjh]hdynids}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjubj )}(hhh]h)}(h%List of dynamically added device IDs.h]h%List of dynamically added device IDs.}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj3hMhj4ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1jhj3hMhjubj)}(hX``driver_managed_dma`` Device driver doesn't use kernel DMA API for DMA. For most device drivers, no need to care about this flag as long as all DMAs are handled through the kernel DMA API. For some special ones, for example VFIO drivers, they know how to manage the DMA themselves and set this flag so that the IOMMU layer will allow them to setup and manage their own I/O address space.h](j)}(h``driver_managed_dma``h]j)}(hjWh]hdriver_managed_dma}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjUubah}(h]h ]h"]h$]h&]uh1jhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjQubj )}(hhh]h)}(hXmDevice driver doesn't use kernel DMA API for DMA. For most device drivers, no need to care about this flag as long as all DMAs are handled through the kernel DMA API. For some special ones, for example VFIO drivers, they know how to manage the DMA themselves and set this flag so that the IOMMU layer will allow them to setup and manage their own I/O address space.h]hXoDevice driver doesn’t use kernel DMA API for DMA. For most device drivers, no need to care about this flag as long as all DMAs are handled through the kernel DMA API. For some special ones, for example VFIO drivers, they know how to manage the DMA themselves and set this flag so that the IOMMU layer will allow them to setup and manage their own I/O address space.}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hhK/var/lib/git/docbuild/linux/Documentation/PCI/pci:81: ./include/linux/pci.hhMhjmubah}(h]h ]h"]h$]h&]uh1j hjQubeh}(h]h ]h"]h$]h&]uh1jhjlhMhjubeh}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ] kernelindentah"]h$]h&]uh1jhjhhhNhNubh)}(hThe ID table is an array of ``struct pci_device_id`` entries ending with an all-zero entry. Definitions with static const are generally preferred.h](hThe ID table is an array of }(hjhhhNhNubj)}(h``struct pci_device_id``h]hstruct pci_device_id}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh_ entries ending with an all-zero entry. Definitions with static const are generally preferred.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKThjhhubj)}(hhh]h}(h]h ]h"]h$]h&]entries](jpci_device_id (C struct)c.pci_device_idhNtauh1jhjhhhNhNubj )}(hhh](j)}(h pci_device_idh]j)}(hstruct pci_device_idh](j)}(hjh]hstruct}(hjhhhNhNubah}(h]h ]j(ah"]h$]h&]uh1jhjhhhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKubj.)}(h h]h }(hjhhhNhNubah}(h]h ]j:ah"]h$]h&]uh1j-hjhhhjhKubj?)}(h pci_device_idh]jE)}(hjh]h pci_device_id}(hjhhhNhNubah}(h]h ]jPah"]h$]h&]uh1jDhjubah}(h]h ](jWjXeh"]h$]h&]hhuh1j>hjhhhjhKubeh}(h]h ]h"]h$]h&]hhjbuh1jjcjdhjhhhjhKubah}(h]jah ](jhjieh"]h$]h&]jmjn)johuh1jhjhKhjhhubjq)}(hhh]h)}(hPCI device ID structureh]hPCI device ID structure}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj hhubah}(h]h ]h"]h$]h&]uh1jphjhhhjhKubeh}(h]h ](jstructeh"]h$]h&]jjjj+ jj+ jjjuh1j hhhjhNhNubj)}(hXm**Definition**:: struct pci_device_id { __u32 vendor, device; __u32 subvendor, subdevice; __u32 class, class_mask; kernel_ulong_t driver_data; __u32 override_only; }; **Members** ``vendor`` Vendor ID to match (or PCI_ANY_ID) ``device`` Device ID to match (or PCI_ANY_ID) ``subvendor`` Subsystem vendor ID to match (or PCI_ANY_ID) ``subdevice`` Subsystem device ID to match (or PCI_ANY_ID) ``class`` Device class, subclass, and "interface" to match. See Appendix D of the PCI Local Bus Spec or include/linux/pci_ids.h for a full list of classes. Most drivers do not need to specify class/class_mask as vendor/device is normally sufficient. ``class_mask`` Limit which sub-fields of the class field are compared. See drivers/scsi/sym53c8xx_2/ for example of usage. ``driver_data`` Data private to the driver. Most drivers don't need to use driver_data field. Best practice is to use driver_data as an index into a static list of equivalent device types, instead of using it as a pointer. ``override_only`` Match only when dev->driver_override is this driver.h](h)}(h**Definition**::h](j)}(h**Definition**h]h Definition}(hj7 hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj3 ubh:}(hj3 hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj/ ubj)}(hstruct pci_device_id { __u32 vendor, device; __u32 subvendor, subdevice; __u32 class, class_mask; kernel_ulong_t driver_data; __u32 override_only; };h]hstruct pci_device_id { __u32 vendor, device; __u32 subvendor, subdevice; __u32 class, class_mask; kernel_ulong_t driver_data; __u32 override_only; };}hjP sbah}(h]h ]h"]h$]h&]hhuh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj/ ubh)}(h **Members**h]j)}(hja h]hMembers}(hjc hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj_ ubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK'hj/ ubj)}(hhh](j)}(h.``vendor`` Vendor ID to match (or PCI_ANY_ID) h](j)}(h ``vendor``h]j)}(hj h]hvendor}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj~ ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhjz ubj )}(hhh]h)}(h"Vendor ID to match (or PCI_ANY_ID)h]h"Vendor ID to match (or PCI_ANY_ID)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKhj ubah}(h]h ]h"]h$]h&]uh1j hjz ubeh}(h]h ]h"]h$]h&]uh1jhj hKhjw ubj)}(h.``device`` Device ID to match (or PCI_ANY_ID) h](j)}(h ``device``h]j)}(hj h]hdevice}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj ubj )}(hhh]h)}(h"Device ID to match (or PCI_ANY_ID)h]h"Device ID to match (or PCI_ANY_ID)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKhj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhjw ubj)}(h;``subvendor`` Subsystem vendor ID to match (or PCI_ANY_ID) h](j)}(h ``subvendor``h]j)}(hj h]h subvendor}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj ubj )}(hhh]h)}(h,Subsystem vendor ID to match (or PCI_ANY_ID)h]h,Subsystem vendor ID to match (or PCI_ANY_ID)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKhj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhjw ubj)}(h;``subdevice`` Subsystem device ID to match (or PCI_ANY_ID) h](j)}(h ``subdevice``h]j)}(hj+ h]h subdevice}(hj- hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj) ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhj% ubj )}(hhh]h)}(h,Subsystem device ID to match (or PCI_ANY_ID)h]h,Subsystem device ID to match (or PCI_ANY_ID)}(hjD hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj@ hKhjA ubah}(h]h ]h"]h$]h&]uh1j hj% ubeh}(h]h ]h"]h$]h&]uh1jhj@ hKhjw ubj)}(h``class`` Device class, subclass, and "interface" to match. See Appendix D of the PCI Local Bus Spec or include/linux/pci_ids.h for a full list of classes. Most drivers do not need to specify class/class_mask as vendor/device is normally sufficient. h](j)}(h ``class``h]j)}(hjd h]hclass}(hjf hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjb ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK#hj^ ubj )}(hhh]h)}(hDevice class, subclass, and "interface" to match. See Appendix D of the PCI Local Bus Spec or include/linux/pci_ids.h for a full list of classes. Most drivers do not need to specify class/class_mask as vendor/device is normally sufficient.h]hDevice class, subclass, and “interface” to match. See Appendix D of the PCI Local Bus Spec or include/linux/pci_ids.h for a full list of classes. Most drivers do not need to specify class/class_mask as vendor/device is normally sufficient.}(hj} hhhNhNubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhKhjz ubah}(h]h ]h"]h$]h&]uh1j hj^ ubeh}(h]h ]h"]h$]h&]uh1jhjy hK#hjw ubj)}(h{``class_mask`` Limit which sub-fields of the class field are compared. See drivers/scsi/sym53c8xx_2/ for example of usage. h](j)}(h``class_mask``h]j)}(hj h]h class_mask}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK%hj ubj )}(hhh]h)}(hkLimit which sub-fields of the class field are compared. See drivers/scsi/sym53c8xx_2/ for example of usage.h]hkLimit which sub-fields of the class field are compared. See drivers/scsi/sym53c8xx_2/ for example of usage.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK$hj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhj hK%hjw ubj)}(h``driver_data`` Data private to the driver. Most drivers don't need to use driver_data field. Best practice is to use driver_data as an index into a static list of equivalent device types, instead of using it as a pointer. h](j)}(h``driver_data``h]j)}(hj h]h driver_data}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK*hj ubj )}(hhh]h)}(hData private to the driver. Most drivers don't need to use driver_data field. Best practice is to use driver_data as an index into a static list of equivalent device types, instead of using it as a pointer.h]hData private to the driver. Most drivers don’t need to use driver_data field. Best practice is to use driver_data as an index into a static list of equivalent device types, instead of using it as a pointer.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK&hj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhj hK*hjw ubj)}(hF``override_only`` Match only when dev->driver_override is this driver.h](j)}(h``override_only``h]j)}(hj h]h override_only}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK*hj ubj )}(hhh]h)}(h4Match only when dev->driver_override is this driver.h]h4Match only when dev->driver_override is this driver.}(hj+ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhW/var/lib/git/docbuild/linux/Documentation/PCI/pci:87: ./include/linux/mod_devicetable.hhK+hj( ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhj' hK*hjw ubeh}(h]h ]h"]h$]h&]uh1jhj/ ubeh}(h]h ] kernelindentah"]h$]h&]uh1jhjhhhNhNubh)}(hbMost drivers only need ``PCI_DEVICE()`` or ``PCI_DEVICE_CLASS()`` to set up a pci_device_id table.h](hMost drivers only need }(hjS hhhNhNubj)}(h``PCI_DEVICE()``h]h PCI_DEVICE()}(hj[ hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjS ubh or }(hjS hhhNhNubj)}(h``PCI_DEVICE_CLASS()``h]hPCI_DEVICE_CLASS()}(hjm hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjS ubh! to set up a pci_device_id table.}(hjS hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKZhjhhubh)}(hUNew PCI IDs may be added to a device driver pci_ids table at runtime as shown below::h]hTNew PCI IDs may be added to a device driver pci_ids table at runtime as shown below:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK]hjhhubj)}(hnecho "vendor device subvendor subdevice class class_mask driver_data" > \ /sys/bus/pci/drivers/{driver}/new_idh]hnecho "vendor device subvendor subdevice class class_mask driver_data" > \ /sys/bus/pci/drivers/{driver}/new_id}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhK`hjhhubh)}(hAll fields are passed in as hexadecimal values (no leading 0x). The vendor and device fields are mandatory, the others are optional. Users need pass only as many optional fields as necessary:h]hAll fields are passed in as hexadecimal values (no leading 0x). The vendor and device fields are mandatory, the others are optional. Users need pass only as many optional fields as necessary:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKchjhhubj)}(h- subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF) - class and classmask fields default to 0 - driver_data defaults to 0UL. - override_only field defaults to 0. h]h)}(hhh](h)}(h?subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)h]h)}(hj h]h?subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKghj ubah}(h]h ]h"]h$]h&]uh1hhj ubh)}(h'class and classmask fields default to 0h]h)}(hj h]h'class and classmask fields default to 0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhj ubah}(h]h ]h"]h$]h&]uh1hhj ubh)}(hdriver_data defaults to 0UL.h]h)}(hj h]hdriver_data defaults to 0UL.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKihj ubah}(h]h ]h"]h$]h&]uh1hhj ubh)}(h#override_only field defaults to 0. h]h)}(h"override_only field defaults to 0.h]h"override_only field defaults to 0.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKjhj ubah}(h]h ]h"]h$]h&]uh1hhj ubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhKghj ubah}(h]h ]h"]h$]h&]uh1jhhhKghjhhubh)}(hNote that driver_data must match the value used by any of the pci_device_id entries defined in the driver. This makes the driver_data field mandatory if all the pci_device_id entries have a non-zero driver_data value.h]hNote that driver_data must match the value used by any of the pci_device_id entries defined in the driver. This makes the driver_data field mandatory if all the pci_device_id entries have a non-zero driver_data value.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKlhjhhubh)}(h~Once added, the driver probe routine will be invoked for any unclaimed PCI devices listed in its (newly updated) pci_ids list.h]h~Once added, the driver probe routine will be invoked for any unclaimed PCI devices listed in its (newly updated) pci_ids list.}(hj- hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKphjhhubh)}(hWhen the driver exits, it just calls pci_unregister_driver() and the PCI layer automatically calls the remove hook for all devices handled by the driver.h]hWhen the driver exits, it just calls pci_unregister_driver() and the PCI layer automatically calls the remove hook for all devices handled by the driver.}(hj; hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKshjhhubh)}(hhh](h)}(h&"Attributes" for driver functions/datah]h*“Attributes” for driver functions/data}(hjL hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjI hhhhhKxubh)}(hPlease mark the initialization and cleanup functions where appropriate (the corresponding macros are defined in ):h]hPlease mark the initialization and cleanup functions where appropriate (the corresponding macros are defined in ):}(hjZ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKzhjI hhubj)}(hX====== ================================================= __init Initialization code. Thrown away after the driver initializes. __exit Exit code. Ignored for non-modular drivers. ====== ================================================= h]htable)}(hhh]htgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jv hjs ubjw )}(hhh]h}(h]h ]h"]h$]h&]colwidthK1uh1jv hjs ubhtbody)}(hhh](hrow)}(hhh](hentry)}(hhh]h)}(h__inith]h__init}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK~hj ubah}(h]h ]h"]h$]h&]uh1j hj ubj )}(hhh]h)}(h>Initialization code. Thrown away after the driver initializes.h]h>Initialization code. Thrown away after the driver initializes.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK~hj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1j hj ubj )}(hhh](j )}(hhh]h)}(h__exith]h__exit}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1j hj ubj )}(hhh]h)}(h+Exit code. Ignored for non-modular drivers.h]h+Exit code. Ignored for non-modular drivers.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1j hjs ubeh}(h]h ]h"]h$]h&]colsKuh1jq hjn ubah}(h]h ]h"]h$]h&]uh1jl hjh ubah}(h]h ]h"]h$]h&]uh1jhhhK}hjI hhubj)}(hhh]j)}(hXdTips on when/where to use the above attributes: - The module_init()/module_exit() functions (and all initialization functions called _only_ from these) should be marked __init/__exit. - Do not mark the struct pci_driver. - Do NOT mark a function if you are not sure which mark to use. Better to not mark the function than mark the function wrong. h](j)}(h/Tips on when/where to use the above attributes:h]h/Tips on when/where to use the above attributes:}(hj# hhhNhNubah}(h]h ]h"]h$]h&]uh1jhhhKhj ubj )}(hhh]h)}(hhh](h)}(hThe module_init()/module_exit() functions (and all initialization functions called _only_ from these) should be marked __init/__exit. h]h)}(hThe module_init()/module_exit() functions (and all initialization functions called _only_ from these) should be marked __init/__exit.h]hThe module_init()/module_exit() functions (and all initialization functions called _only_ from these) should be marked __init/__exit.}(hj; hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj7 ubah}(h]h ]h"]h$]h&]uh1hhj4 ubh)}(h#Do not mark the struct pci_driver. h]h)}(h"Do not mark the struct pci_driver.h]h"Do not mark the struct pci_driver.}(hjS hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjO ubah}(h]h ]h"]h$]h&]uh1hhj4 ubh)}(h}Do NOT mark a function if you are not sure which mark to use. Better to not mark the function than mark the function wrong. h]h)}(h{Do NOT mark a function if you are not sure which mark to use. Better to not mark the function than mark the function wrong.h]h{Do NOT mark a function if you are not sure which mark to use. Better to not mark the function than mark the function wrong.}(hjk hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjg ubah}(h]h ]h"]h$]h&]uh1hhj4 ubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhKhj1 ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1jhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjI hhhNhNubeh}(h]$attributes-for-driver-functions-dataah ]h"]&"attributes" for driver functions/dataah$]h&]uh1hhjhhhhhKxubeh}(h]pci-register-driver-callah ]h"]pci_register_driver() callah$]h&]uh1hhhhhhhhKKubh)}(hhh](h)}(h How to find PCI devices manuallyh]h How to find PCI devices manually}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhKubh)}(hX2PCI drivers should have a really good reason for not using the pci_register_driver() interface to search for PCI devices. The main reason PCI devices are controlled by multiple drivers is because one PCI device implements several different HW services. E.g. combined serial/parallel port/floppy controller.h]hX2PCI drivers should have a really good reason for not using the pci_register_driver() interface to search for PCI devices. The main reason PCI devices are controlled by multiple drivers is because one PCI device implements several different HW services. E.g. combined serial/parallel port/floppy controller.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(h@A manual search may be performed using the following constructs:h]h@A manual search may be performed using the following constructs:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(h#Searching by vendor and device ID::h]h"Searching by vendor and device ID:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hrstruct pci_dev *dev = NULL; while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev)) configure_device(dev);h]hrstruct pci_dev *dev = NULL; while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev)) configure_device(dev);}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(h2Searching by class ID (iterate in a similar way)::h]h1Searching by class ID (iterate in a similar way):}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hpci_get_class(CLASS_ID, dev)h]hpci_get_class(CLASS_ID, dev)}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(h@Searching by both vendor/device and subsystem vendor/device ID::h]h?Searching by both vendor/device and subsystem vendor/device ID:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hMpci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).h]hMpci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(hYou can use the constant PCI_ANY_ID as a wildcard replacement for VENDOR_ID or DEVICE_ID. This allows searching for any device from a specific vendor, for example.h]hYou can use the constant PCI_ANY_ID as a wildcard replacement for VENDOR_ID or DEVICE_ID. This allows searching for any device from a specific vendor, for example.}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(hThese functions are hotplug-safe. They increment the reference count on the pci_dev that they return. You must eventually (possibly at module unload) decrement the reference count on these devices by calling pci_dev_put().h]hThese functions are hotplug-safe. They increment the reference count on the pci_dev that they return. You must eventually (possibly at module unload) decrement the reference count on these devices by calling pci_dev_put().}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubeh}(h] how-to-find-pci-devices-manuallyah ]h"] how to find pci devices manuallyah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hDevice Initialization Stepsh]hDevice Initialization Steps}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjLhhhhhKubh)}(hbAs noted in the introduction, most PCI drivers need the following steps for device initialization:h]hbAs noted in the introduction, most PCI drivers need the following steps for device initialization:}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjLhhubj)}(hXj- Enable the device - Request MMIO/IOP resources - Set the DMA mask size (for both coherent and streaming DMA) - Allocate and initialize shared control data (pci_allocate_coherent()) - Access device configuration space (if needed) - Register IRQ handler (request_irq()) - Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) - Enable DMA/processing engines. h]h)}(hhh](h)}(hEnable the deviceh]h)}(hjth]hEnable the device}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjrubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(hRequest MMIO/IOP resourcesh]h)}(hjh]hRequest MMIO/IOP resources}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(h;Set the DMA mask size (for both coherent and streaming DMA)h]h)}(hjh]h;Set the DMA mask size (for both coherent and streaming DMA)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(hEAllocate and initialize shared control data (pci_allocate_coherent())h]h)}(hjh]hEAllocate and initialize shared control data (pci_allocate_coherent())}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(h-Access device configuration space (if needed)h]h)}(hjh]h-Access device configuration space (if needed)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(h$Register IRQ handler (request_irq())h]h)}(hjh]h$Register IRQ handler (request_irq())}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(h8Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)h]h)}(hjh]h8Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubh)}(hEnable DMA/processing engines. h]h)}(hEnable DMA/processing engines.h]hEnable DMA/processing engines.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjoubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhKhjkubah}(h]h ]h"]h$]h&]uh1jhhhKhjLhhubh)}(hThe driver can access PCI config space registers at any time. (Well, almost. When running BIST, config space can go away...but that will just result in a PCI Bus Master Abort and config reads will return garbage).h]hThe driver can access PCI config space registers at any time. (Well, almost. When running BIST, config space can go away...but that will just result in a PCI Bus Master Abort and config reads will return garbage).}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjLhhubh)}(hhh](h)}(hEnable the PCI deviceh]hEnable the PCI device}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjEhhhhhKubh)}(hzBefore touching any device registers, the driver needs to enable the PCI device by calling pci_enable_device(). This will:`h]hzBefore touching any device registers, the driver needs to enable the PCI device by calling pci_enable_device(). This will:}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjEhhubj)}(h- wake up the device if it was in suspended state, - allocate I/O and memory regions of the device (if BIOS did not), - allocate an IRQ (if BIOS did not). h]h)}(hhh](h)}(h0wake up the device if it was in suspended state,h]h)}(hjmh]h0wake up the device if it was in suspended state,}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjkubah}(h]h ]h"]h$]h&]uh1hhjhubh)}(h@allocate I/O and memory regions of the device (if BIOS did not),h]h)}(hjh]h@allocate I/O and memory regions of the device (if BIOS did not),}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjhubh)}(h#allocate an IRQ (if BIOS did not). h]h)}(h"allocate an IRQ (if BIOS did not).h]h"allocate an IRQ (if BIOS did not).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjhubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhKhjdubah}(h]h ]h"]h$]h&]uh1jhhhKhjEhhubhnote)}(h5pci_enable_device() can fail! Check the return value.h]h)}(hjh]h5pci_enable_device() can fail! Check the return value.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjEhhhhhNubhwarning)}(hXOS BUG: we don't check resource allocations before enabling those resources. The sequence would make more sense if we called pci_request_resources() before calling pci_enable_device(). Currently, the device drivers can't detect the bug when two devices have been allocated the same range. This is not a common problem and unlikely to get fixed soon. This has been discussed before but not changed as of 2.6.19: https://lore.kernel.org/r/20060302180025.GC28895@flint.arm.linux.org.uk/h](h)}(hX]OS BUG: we don't check resource allocations before enabling those resources. The sequence would make more sense if we called pci_request_resources() before calling pci_enable_device(). Currently, the device drivers can't detect the bug when two devices have been allocated the same range. This is not a common problem and unlikely to get fixed soon.h]hXaOS BUG: we don’t check resource allocations before enabling those resources. The sequence would make more sense if we called pci_request_resources() before calling pci_enable_device(). Currently, the device drivers can’t detect the bug when two devices have been allocated the same range. This is not a common problem and unlikely to get fixed soon.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hThis has been discussed before but not changed as of 2.6.19: https://lore.kernel.org/r/20060302180025.GC28895@flint.arm.linux.org.uk/h](h=This has been discussed before but not changed as of 2.6.19: }(hjhhhNhNubh)}(hHhttps://lore.kernel.org/r/20060302180025.GC28895@flint.arm.linux.org.uk/h]hHhttps://lore.kernel.org/r/20060302180025.GC28895@flint.arm.linux.org.uk/}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurijuh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1jhjEhhhhhNubh)}(hpci_set_master() will enable DMA by setting the bus master bit in the PCI_COMMAND register. It also fixes the latency timer value if it's set to something bogus by the BIOS. pci_clear_master() will disable DMA by clearing the bus master bit.h]hpci_set_master() will enable DMA by setting the bus master bit in the PCI_COMMAND register. It also fixes the latency timer value if it’s set to something bogus by the BIOS. pci_clear_master() will disable DMA by clearing the bus master bit.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjEhhubh)}(hXIf the PCI device can use the PCI Memory-Write-Invalidate transaction, call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval and also ensures that the cache line size register is set correctly. Check the return value of pci_set_mwi() as not all architectures or chip-sets may support Memory-Write-Invalidate. Alternatively, if Mem-Wr-Inval would be nice to have but is not required, call pci_try_set_mwi() to have the system do its best effort at enabling Mem-Wr-Inval.h]hXIf the PCI device can use the PCI Memory-Write-Invalidate transaction, call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval and also ensures that the cache line size register is set correctly. Check the return value of pci_set_mwi() as not all architectures or chip-sets may support Memory-Write-Invalidate. Alternatively, if Mem-Wr-Inval would be nice to have but is not required, call pci_try_set_mwi() to have the system do its best effort at enabling Mem-Wr-Inval.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjEhhubeh}(h]enable-the-pci-deviceah ]h"]enable the pci deviceah$]h&]uh1hhjLhhhhhKubh)}(hhh](h)}(hRequest MMIO/IOP resourcesh]hRequest MMIO/IOP resources}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj1hhhhhKubh)}(hXMemory (MMIO), and I/O port addresses should NOT be read directly from the PCI device config space. Use the values in the pci_dev structure as the PCI "bus address" might have been remapped to a "host physical" address by the arch/chip-set specific kernel support.h]hXMemory (MMIO), and I/O port addresses should NOT be read directly from the PCI device config space. Use the values in the pci_dev structure as the PCI “bus address” might have been remapped to a “host physical” address by the arch/chip-set specific kernel support.}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubh)}(h`See Documentation/driver-api/io-mapping.rst for how to access device registers or device memory.h]h`See Documentation/driver-api/io-mapping.rst for how to access device registers or device memory.}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubh)}(hXThe device driver needs to call pci_request_region() to verify no other device is already using the same address resource. Conversely, drivers should call pci_release_region() AFTER calling pci_disable_device(). The idea is to prevent two devices colliding on the same address range.h]hXThe device driver needs to call pci_request_region() to verify no other device is already using the same address resource. Conversely, drivers should call pci_release_region() AFTER calling pci_disable_device(). The idea is to prevent two devices colliding on the same address range.}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubhtip)}(hSee OS BUG comment above. Currently (2.6.19), The driver can only determine MMIO and IO Port resource availability _after_ calling pci_enable_device().h]h)}(hSee OS BUG comment above. Currently (2.6.19), The driver can only determine MMIO and IO Port resource availability _after_ calling pci_enable_device().h]hSee OS BUG comment above. Currently (2.6.19), The driver can only determine MMIO and IO Port resource availability _after_ calling pci_enable_device().}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjnubah}(h]h ]h"]h$]h&]uh1jlhj1hhhhhNubh)}(hGeneric flavors of pci_request_region() are request_mem_region() (for MMIO ranges) and request_region() (for IO Port ranges). Use these for address resources that are not described by "normal" PCI BARs.h]hGeneric flavors of pci_request_region() are request_mem_region() (for MMIO ranges) and request_region() (for IO Port ranges). Use these for address resources that are not described by “normal” PCI BARs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj1hhubh)}(h.Also see pci_request_selected_regions() below.h]h.Also see pci_request_selected_regions() below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj1hhubeh}(h]request-mmio-iop-resourcesah ]h"]request mmio/iop resourcesah$]h&]uh1hhjLhhhhhKubh)}(hhh](h)}(hSet the DMA mask sizeh]hSet the DMA mask size}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM ubj)}(hIf anything below doesn't make sense, please refer to Documentation/core-api/dma-api.rst. This section is just a reminder that drivers need to indicate DMA capabilities of the device and is not an authoritative source for DMA interfaces.h]h)}(hIf anything below doesn't make sense, please refer to Documentation/core-api/dma-api.rst. This section is just a reminder that drivers need to indicate DMA capabilities of the device and is not an authoritative source for DMA interfaces.h]hIf anything below doesn’t make sense, please refer to Documentation/core-api/dma-api.rst. This section is just a reminder that drivers need to indicate DMA capabilities of the device and is not an authoritative source for DMA interfaces.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubh)}(hXWhile all drivers should explicitly indicate the DMA capability (e.g. 32 or 64 bit) of the PCI bus master, devices with more than 32-bit bus master capability for streaming data need the driver to "register" this capability by calling dma_set_mask() with appropriate parameters. In general this allows more efficient DMA on systems where System RAM exists above 4G _physical_ address.h]hXWhile all drivers should explicitly indicate the DMA capability (e.g. 32 or 64 bit) of the PCI bus master, devices with more than 32-bit bus master capability for streaming data need the driver to “register” this capability by calling dma_set_mask() with appropriate parameters. In general this allows more efficient DMA on systems where System RAM exists above 4G _physical_ address.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hiDrivers for all PCI-X and PCIe compliant devices must call dma_set_mask() as they are 64-bit DMA devices.h]hiDrivers for all PCI-X and PCIe compliant devices must call dma_set_mask() as they are 64-bit DMA devices.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hXSimilarly, drivers must also "register" this capability if the device can directly address "coherent memory" in System RAM above 4G physical address by calling dma_set_coherent_mask(). Again, this includes drivers for all PCI-X and PCIe compliant devices. Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are 64-bit DMA capable for payload ("streaming") data but not control ("coherent") data.h]hXSimilarly, drivers must also “register” this capability if the device can directly address “coherent memory” in System RAM above 4G physical address by calling dma_set_coherent_mask(). Again, this includes drivers for all PCI-X and PCIe compliant devices. Many 64-bit “PCI” devices (before PCI-X) and some PCI-X devices are 64-bit DMA capable for payload (“streaming”) data but not control (“coherent”) data.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]set-the-dma-mask-sizeah ]h"]set the dma mask sizeah$]h&]uh1hhjLhhhhhM ubh)}(hhh](h)}(hSetup shared control datah]hSetup shared control data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM%ubh)}(hXOnce the DMA masks are set, the driver can allocate "coherent" (a.k.a. shared) memory. See Documentation/core-api/dma-api.rst for a full description of the DMA APIs. This section is just a reminder that it needs to be done before enabling DMA on the device.h]hXOnce the DMA masks are set, the driver can allocate “coherent” (a.k.a. shared) memory. See Documentation/core-api/dma-api.rst for a full description of the DMA APIs. This section is just a reminder that it needs to be done before enabling DMA on the device.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM&hjhhubeh}(h]setup-shared-control-dataah ]h"]setup shared control dataah$]h&]uh1hhjLhhhhhM%ubh)}(hhh](h)}(hInitialize device registersh]hInitialize device registers}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj,hhhhhM-ubh)}(hSome drivers will need specific "capability" fields programmed or other "vendor specific" register initialized or reset. E.g. clearing pending interrupts.h]hSome drivers will need specific “capability” fields programmed or other “vendor specific” register initialized or reset. E.g. clearing pending interrupts.}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM.hj,hhubeh}(h]initialize-device-registersah ]h"]initialize device registersah$]h&]uh1hhjLhhhhhM-ubh)}(hhh](h)}(hRegister IRQ handlerh]hRegister IRQ handler}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjShhhhhM4ubh)}(hWhile calling request_irq() is the last step described here, this is often just another intermediate step to initialize a device. This step can often be deferred until the device is opened for use.h]hWhile calling request_irq() is the last step described here, this is often just another intermediate step to initialize a device. This step can often be deferred until the device is opened for use.}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM5hjShhubh)}(hAll interrupt handlers for IRQ lines should be registered with IRQF_SHARED and use the devid to map IRQs to devices (remember that all PCI IRQ lines can be shared).h]hAll interrupt handlers for IRQ lines should be registered with IRQF_SHARED and use the devid to map IRQs to devices (remember that all PCI IRQ lines can be shared).}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM9hjShhubh)}(hXrequest_irq() will associate an interrupt handler and device handle with an interrupt number. Historically interrupt numbers represent IRQ lines which run from the PCI device to the Interrupt controller. With MSI and MSI-X (more below) the interrupt number is a CPU "vector".h]hXrequest_irq() will associate an interrupt handler and device handle with an interrupt number. Historically interrupt numbers represent IRQ lines which run from the PCI device to the Interrupt controller. With MSI and MSI-X (more below) the interrupt number is a CPU “vector”.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM=hjShhubh)}(hrequest_irq() also enables the interrupt. Make sure the device is quiesced and does not have any interrupts pending before registering the interrupt handler.h]hrequest_irq() also enables the interrupt. Make sure the device is quiesced and does not have any interrupts pending before registering the interrupt handler.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMBhjShhubh)}(hXEMSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts" which deliver interrupts to the CPU via a DMA write to a Local APIC. The fundamental difference between MSI and MSI-X is how multiple "vectors" get allocated. MSI requires contiguous blocks of vectors while MSI-X can allocate several individual ones.h]hXMMSI and MSI-X are PCI capabilities. Both are “Message Signaled Interrupts” which deliver interrupts to the CPU via a DMA write to a Local APIC. The fundamental difference between MSI and MSI-X is how multiple “vectors” get allocated. MSI requires contiguous blocks of vectors while MSI-X can allocate several individual ones.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMFhjShhubh)}(hXMSI capability can be enabled by calling pci_alloc_irq_vectors() with the PCI_IRQ_MSI and/or PCI_IRQ_MSIX flags before calling request_irq(). This causes the PCI support to program CPU vector data into the PCI device capability registers. Many architectures, chip-sets, or BIOSes do NOT support MSI or MSI-X and a call to pci_alloc_irq_vectors with just the PCI_IRQ_MSI and PCI_IRQ_MSIX flags will fail, so try to always specify PCI_IRQ_INTX as well.h]hXMSI capability can be enabled by calling pci_alloc_irq_vectors() with the PCI_IRQ_MSI and/or PCI_IRQ_MSIX flags before calling request_irq(). This causes the PCI support to program CPU vector data into the PCI device capability registers. Many architectures, chip-sets, or BIOSes do NOT support MSI or MSI-X and a call to pci_alloc_irq_vectors with just the PCI_IRQ_MSI and PCI_IRQ_MSIX flags will fail, so try to always specify PCI_IRQ_INTX as well.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMLhjShhubh)}(hDrivers that have different interrupt handlers for MSI/MSI-X and legacy INTx should chose the right one based on the msi_enabled and msix_enabled flags in the pci_dev structure after calling pci_alloc_irq_vectors.h]hDrivers that have different interrupt handlers for MSI/MSI-X and legacy INTx should chose the right one based on the msi_enabled and msix_enabled flags in the pci_dev structure after calling pci_alloc_irq_vectors.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMThjShhubh)}(h;There are (at least) two really good reasons for using MSI:h]h;There are (at least) two really good reasons for using MSI:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMYhjShhubhenumerated_list)}(hhh](h)}(hMSI is an exclusive interrupt vector by definition. This means the interrupt handler doesn't have to verify its device caused the interrupt. h]h)}(hMSI is an exclusive interrupt vector by definition. This means the interrupt handler doesn't have to verify its device caused the interrupt.h]hMSI is an exclusive interrupt vector by definition. This means the interrupt handler doesn’t have to verify its device caused the interrupt.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM[hjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubh)}(hXMSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed to be visible to the host CPU(s) when the MSI is delivered. This is important for both data coherency and avoiding stale control data. This guarantee allows the driver to omit MMIO reads to flush the DMA stream. h]h)}(hXMSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed to be visible to the host CPU(s) when the MSI is delivered. This is important for both data coherency and avoiding stale control data. This guarantee allows the driver to omit MMIO reads to flush the DMA stream.h]hXMSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed to be visible to the host CPU(s) when the MSI is delivered. This is important for both data coherency and avoiding stale control data. This guarantee allows the driver to omit MMIO reads to flush the DMA stream.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM_hjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix)uh1jhjShhhhhM[ubh)}(hVSee drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples of MSI/MSI-X usage.h]hVSee drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples of MSI/MSI-X usage.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMehjShhubeh}(h]register-irq-handlerah ]h"]register irq handlerah$]h&]uh1hhjLhhhhhM4ubeh}(h]device-initialization-stepsah ]h"]device initialization stepsah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hPCI device shutdownh]hPCI device shutdown}(hj5hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2hhhhhMjubh)}(h]When a PCI device driver is being unloaded, most of the following steps need to be performed:h]h]When a PCI device driver is being unloaded, most of the following steps need to be performed:}(hjChhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMlhj2hhubj)}(hX-- Disable the device from generating IRQs - Release the IRQ (free_irq()) - Stop all DMA activity - Release DMA buffers (both streaming and coherent) - Unregister from other subsystems (e.g. scsi or netdev) - Disable device from responding to MMIO/IO Port addresses - Release MMIO/IO Port resource(s) h]h)}(hhh](h)}(h'Disable the device from generating IRQsh]h)}(hjZh]h'Disable the device from generating IRQs}(hj\hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMohjXubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(hRelease the IRQ (free_irq())h]h)}(hjqh]hRelease the IRQ (free_irq())}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMphjoubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(hStop all DMA activityh]h)}(hjh]hStop all DMA activity}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMqhjubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(h1Release DMA buffers (both streaming and coherent)h]h)}(hjh]h1Release DMA buffers (both streaming and coherent)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMrhjubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(h6Unregister from other subsystems (e.g. scsi or netdev)h]h)}(hjh]h6Unregister from other subsystems (e.g. scsi or netdev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMshjubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(h8Disable device from responding to MMIO/IO Port addressesh]h)}(hjh]h8Disable device from responding to MMIO/IO Port addresses}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMthjubah}(h]h ]h"]h$]h&]uh1hhjUubh)}(h"Release MMIO/IO Port resource(s) h]h)}(h Release MMIO/IO Port resource(s)h]h Release MMIO/IO Port resource(s)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMuhjubah}(h]h ]h"]h$]h&]uh1hhjUubeh}(h]h ]h"]h$]h&]jQjRuh1hhhhMohjQubah}(h]h ]h"]h$]h&]uh1jhhhMohj2hhubh)}(hhh](h)}(hStop IRQs on the deviceh]hStop IRQs on the device}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMyubh)}(hHow to do this is chip/device specific. If it's not done, it opens the possibility of a "screaming interrupt" if (and only if) the IRQ is shared with another device.h]hHow to do this is chip/device specific. If it’s not done, it opens the possibility of a “screaming interrupt” if (and only if) the IRQ is shared with another device.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMzhjhhubh)}(hXWhen the shared IRQ handler is "unhooked", the remaining devices using the same IRQ line will still need the IRQ enabled. Thus if the "unhooked" device asserts IRQ line, the system will respond assuming it was one of the remaining devices asserted the IRQ line. Since none of the other devices will handle the IRQ, the system will "hang" until it decides the IRQ isn't going to get handled and masks the IRQ (100,000 iterations later). Once the shared IRQ is masked, the remaining devices will stop functioning properly. Not a nice situation.h]hX,When the shared IRQ handler is “unhooked”, the remaining devices using the same IRQ line will still need the IRQ enabled. Thus if the “unhooked” device asserts IRQ line, the system will respond assuming it was one of the remaining devices asserted the IRQ line. Since none of the other devices will handle the IRQ, the system will “hang” until it decides the IRQ isn’t going to get handled and masks the IRQ (100,000 iterations later). Once the shared IRQ is masked, the remaining devices will stop functioning properly. Not a nice situation.}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM~hjhhubh)}(hThis is another reason to use MSI or MSI-X if it's available. MSI and MSI-X are defined to be exclusive interrupts and thus are not susceptible to the "screaming interrupt" problem.h]hThis is another reason to use MSI or MSI-X if it’s available. MSI and MSI-X are defined to be exclusive interrupts and thus are not susceptible to the “screaming interrupt” problem.}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]stop-irqs-on-the-deviceah ]h"]stop irqs on the deviceah$]h&]uh1hhj2hhhhhMyubh)}(hhh](h)}(hRelease the IRQh]hRelease the IRQ}(hjLhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjIhhhhhMubh)}(hOnce the device is quiesced (no more IRQs), one can call free_irq(). This function will return control once any pending IRQs are handled, "unhook" the drivers IRQ handler from that IRQ, and finally release the IRQ if no one else is using it.h]hOnce the device is quiesced (no more IRQs), one can call free_irq(). This function will return control once any pending IRQs are handled, “unhook” the drivers IRQ handler from that IRQ, and finally release the IRQ if no one else is using it.}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjIhhubeh}(h]release-the-irqah ]h"]release the irqah$]h&]uh1hhj2hhhhhMubh)}(hhh](h)}(hStop all DMA activityh]hStop all DMA activity}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhjphhhhhMubh)}(hIt's extremely important to stop all DMA operations BEFORE attempting to deallocate DMA control data. Failure to do so can result in memory corruption, hangs, and on some chip-sets a hard crash.h]hIt’s extremely important to stop all DMA operations BEFORE attempting to deallocate DMA control data. Failure to do so can result in memory corruption, hangs, and on some chip-sets a hard crash.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjphhubh)}(heStopping DMA after stopping the IRQs can avoid races where the IRQ handler might restart DMA engines.h]heStopping DMA after stopping the IRQs can avoid races where the IRQ handler might restart DMA engines.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjphhubh)}(hlWhile this step sounds obvious and trivial, several "mature" drivers didn't get this step right in the past.h]hrWhile this step sounds obvious and trivial, several “mature” drivers didn’t get this step right in the past.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjphhubeh}(h]stop-all-dma-activityah ]h"]stop all dma activityah$]h&]uh1hhj2hhhhhMubh)}(hhh](h)}(hRelease DMA buffersh]hRelease DMA buffers}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hOnce DMA is stopped, clean up streaming DMA first. I.e. unmap data buffers and return buffers to "upstream" owners if there is one.h]hOnce DMA is stopped, clean up streaming DMA first. I.e. unmap data buffers and return buffers to “upstream” owners if there is one.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h@Then clean up "coherent" buffers which contain the control data.h]hDThen clean up “coherent” buffers which contain the control data.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hKSee Documentation/core-api/dma-api.rst for details on unmapping interfaces.h]hKSee Documentation/core-api/dma-api.rst for details on unmapping interfaces.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]release-dma-buffersah ]h"]release dma buffersah$]h&]uh1hhj2hhhhhMubh)}(hhh](h)}(h Unregister from other subsystemsh]h Unregister from other subsystems}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hX9Most low level PCI device drivers support some other subsystem like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your driver isn't losing resources from that other subsystem. If this happens, typically the symptom is an Oops (panic) when the subsystem attempts to call into a driver that has been unloaded.h]hX;Most low level PCI device drivers support some other subsystem like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your driver isn’t losing resources from that other subsystem. If this happens, typically the symptom is an Oops (panic) when the subsystem attempts to call into a driver that has been unloaded.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h] unregister-from-other-subsystemsah ]h"] unregister from other subsystemsah$]h&]uh1hhj2hhhhhMubh)}(hhh](h)}(h8Disable Device from responding to MMIO/IO Port addressesh]h8Disable Device from responding to MMIO/IO Port addresses}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hio_unmap() MMIO or IO Port resources and then call pci_disable_device(). This is the symmetric opposite of pci_enable_device(). Do not access device registers after calling pci_disable_device().h]hio_unmap() MMIO or IO Port resources and then call pci_disable_device(). This is the symmetric opposite of pci_enable_device(). Do not access device registers after calling pci_disable_device().}(hj.hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]8disable-device-from-responding-to-mmio-io-port-addressesah ]h"]8disable device from responding to mmio/io port addressesah$]h&]uh1hhj2hhhhhMubh)}(hhh](h)}(h Release MMIO/IO Port Resource(s)h]h Release MMIO/IO Port Resource(s)}(hjGhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjDhhhhhMubh)}(hCall pci_release_region() to mark the MMIO or IO Port range as available. Failure to do so usually results in the inability to reload the driver.h]hCall pci_release_region() to mark the MMIO or IO Port range as available. Failure to do so usually results in the inability to reload the driver.}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjDhhubeh}(h]release-mmio-io-port-resource-sah ]h"] release mmio/io port resource(s)ah$]h&]uh1hhj2hhhhhMubeh}(h]pci-device-shutdownah ]h"]pci device shutdownah$]h&]uh1hhhhhhhhMjubh)}(hhh](h)}(hHow to access PCI config spaceh]hHow to access PCI config space}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjshhhhhMubh)}(hXPYou can use `pci_(read|write)_config_(byte|word|dword)` to access the config space of a device represented by `struct pci_dev *`. All these functions return 0 when successful or an error code (`PCIBIOS_...`) which can be translated to a text string by pcibios_strerror. Most drivers expect that accesses to valid PCI devices don't fail.h](h You can use }(hjhhhNhNubhtitle_reference)}(h+`pci_(read|write)_config_(byte|word|dword)`h]h)pci_(read|write)_config_(byte|word|dword)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh7 to access the config space of a device represented by }(hjhhhNhNubj)}(h`struct pci_dev *`h]hstruct pci_dev *}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhA. All these functions return 0 when successful or an error code (}(hjhhhNhNubj)}(h `PCIBIOS_...`h]h PCIBIOS_...}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh) which can be translated to a text string by pcibios_strerror. Most drivers expect that accesses to valid PCI devices don’t fail.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjshhubh)}(hIf you don't have a struct pci_dev available, you can call `pci_bus_(read|write)_config_(byte|word|dword)` to access a given device and function on that bus.h](h=If you don’t have a struct pci_dev available, you can call }(hjhhhNhNubj)}(h/`pci_bus_(read|write)_config_(byte|word|dword)`h]h-pci_bus_(read|write)_config_(byte|word|dword)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh3 to access a given device and function on that bus.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjshhubh)}(hIf you access fields in the standard portion of the config header, please use symbolic names of locations and bits declared in .h]hIf you access fields in the standard portion of the config header, please use symbolic names of locations and bits declared in .}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjshhubh)}(hIf you need to access Extended PCI Capability registers, just call pci_find_capability() for the particular capability and it will find the corresponding register block for you.h]hIf you need to access Extended PCI Capability registers, just call pci_find_capability() for the particular capability and it will find the corresponding register block for you.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjshhubeh}(h]how-to-access-pci-config-spaceah ]h"]how to access pci config spaceah$]h&]uh1hhhhhhhhMubh)}(hhh](h)}(hOther interesting functionsh]hOther interesting functions}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubjm )}(hhh]jr )}(hhh](jw )}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jv hj"ubjw )}(hhh]h}(h]h ]h"]h$]h&]colwidthK0uh1jv hj"ubj )}(hhh](j )}(hhh](j )}(hhh]h)}(hpci_get_domain_bus_and_slot()h]hpci_get_domain_bus_and_slot()}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj?ubah}(h]h ]h"]h$]h&]uh1j hj<ubj )}(hhh]h)}(h~Find pci_dev corresponding to given domain, bus and slot and number. If the device is found, its reference count is increased.h]h~Find pci_dev corresponding to given domain, bus and slot and number. If the device is found, its reference count is increased.}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjVubah}(h]h ]h"]h$]h&]uh1j hj<ubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_set_power_state()h]hpci_set_power_state()}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjvubah}(h]h ]h"]h$]h&]uh1j hjsubj )}(hhh]h)}(h.Set PCI Power Management state (0=D0 ... 3=D3)h]h.Set PCI Power Management state (0=D0 ... 3=D3)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjsubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_find_capability()h]hpci_find_capability()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h6Find specified capability in device's capability list.h]h8Find specified capability in device’s capability list.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_resource_start()h]hpci_resource_start()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h0Returns bus start address for a given PCI regionh]h0Returns bus start address for a given PCI region}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_resource_end()h]hpci_resource_end()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h.Returns bus end address for a given PCI regionh]h.Returns bus end address for a given PCI region}(hj5hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj2ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_resource_len()h]hpci_resource_len()}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjRubah}(h]h ]h"]h$]h&]uh1j hjOubj )}(hhh]h)}(h'Returns the byte length of a PCI regionh]h'Returns the byte length of a PCI region}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjiubah}(h]h ]h"]h$]h&]uh1j hjOubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_set_drvdata()h]hpci_set_drvdata()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h-Set private driver data pointer for a pci_devh]h-Set private driver data pointer for a pci_dev}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_get_drvdata()h]hpci_get_drvdata()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h0Return private driver data pointer for a pci_devh]h0Return private driver data pointer for a pci_dev}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(h pci_set_mwi()h]h pci_set_mwi()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h,Enable Memory-Write-Invalidate transactions.h]h,Enable Memory-Write-Invalidate transactions.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hj9ubj )}(hhh](j )}(hhh]h)}(hpci_clear_mwi()h]hpci_clear_mwi()}(hj1hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj.ubah}(h]h ]h"]h$]h&]uh1j hj+ubj )}(hhh]h)}(h-Disable Memory-Write-Invalidate transactions.h]h-Disable Memory-Write-Invalidate transactions.}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjEubah}(h]h ]h"]h$]h&]uh1j hj+ubeh}(h]h ]h"]h$]h&]uh1j hj9ubeh}(h]h ]h"]h$]h&]uh1j hj"ubeh}(h]h ]h"]h$]h&]colsKuh1jq hjubah}(h]h ]h"]h$]h&]uh1jl hjhhhhhNubeh}(h]other-interesting-functionsah ]h"]other interesting functionsah$]h&]uh1hhhhhhhhMubh)}(hhh](h)}(hMiscellaneous hintsh]hMiscellaneous hints}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj}hhhhhMubh)}(hWhen displaying PCI device names to the user (for example when a driver wants to tell the user what card has it found), please use pci_name(pci_dev).h]hWhen displaying PCI device names to the user (for example when a driver wants to tell the user what card has it found), please use pci_name(pci_dev).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj}hhubh)}(hX.Always refer to the PCI devices by a pointer to the pci_dev structure. All PCI layer functions use this identification and it's the only reasonable one. Don't use bus/slot/function numbers except for very special purposes -- on systems with multiple primary buses their semantics can be pretty complex.h]hX2Always refer to the PCI devices by a pointer to the pci_dev structure. All PCI layer functions use this identification and it’s the only reasonable one. Don’t use bus/slot/function numbers except for very special purposes -- on systems with multiple primary buses their semantics can be pretty complex.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj}hhubh)}(hDon't try to turn on Fast Back to Back writes in your driver. All devices on the bus need to be capable of doing it, so this is something which needs to be handled by platform and generic code, not individual drivers.h]hDon’t try to turn on Fast Back to Back writes in your driver. All devices on the bus need to be capable of doing it, so this is something which needs to be handled by platform and generic code, not individual drivers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj}hhubeh}(h]miscellaneous-hintsah ]h"]miscellaneous hintsah$]h&]uh1hhhhhhhhMubh)}(hhh](h)}(h!Vendor and device identificationsh]h!Vendor and device identifications}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hDo not add new device or vendor IDs to include/linux/pci_ids.h unless they are shared across multiple drivers. You can add private definitions in your driver if they're helpful, or just use plain hex constants.h]hDo not add new device or vendor IDs to include/linux/pci_ids.h unless they are shared across multiple drivers. You can add private definitions in your driver if they’re helpful, or just use plain hex constants.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hThe device IDs are arbitrary hex numbers (vendor controlled) and normally used only in a single location, the pci_device_id table.h]hThe device IDs are arbitrary hex numbers (vendor controlled) and normally used only in a single location, the pci_device_id table.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hPlease DO submit new vendor/device IDs to https://pci-ids.ucw.cz/. There's a mirror of the pci.ids file at https://github.com/pciutils/pciids.h](h*Please DO submit new vendor/device IDs to }(hjhhhNhNubh)}(hhttps://pci-ids.ucw.cz/h]hhttps://pci-ids.ucw.cz/}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurijuh1hhjubh,. There’s a mirror of the pci.ids file at }(hjhhhNhNubh)}(h"https://github.com/pciutils/pciidsh]h"https://github.com/pciutils/pciids}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurij uh1hhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]!vendor-and-device-identificationsah ]h"]!vendor and device identificationsah$]h&]uh1hhhhhhhhMubh)}(hhh](h)}(hObsolete functionsh]hObsolete functions}(hj,hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj)hhhhhM ubh)}(hThere are several functions which you might come across when trying to port an old driver to the new PCI interface. They are no longer present in the kernel as they aren't compatible with hotplug or PCI domains or having sane locking.h]hThere are several functions which you might come across when trying to port an old driver to the new PCI interface. They are no longer present in the kernel as they aren’t compatible with hotplug or PCI domains or having sane locking.}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hj)hhubjm )}(hhh]jr )}(hhh](jw )}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jv hjKubjw )}(hhh]h}(h]h ]h"]h$]h&]colwidthK+uh1jv hjKubj )}(hhh](j )}(hhh](j )}(hhh]h)}(hpci_find_device()h]hpci_find_device()}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhubah}(h]h ]h"]h$]h&]uh1j hjeubj )}(hhh]h)}(hSuperseded by pci_get_device()h]hSuperseded by pci_get_device()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjeubeh}(h]h ]h"]h$]h&]uh1j hjbubj )}(hhh](j )}(hhh]h)}(hpci_find_subsys()h]hpci_find_subsys()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(hSuperseded by pci_get_subsys()h]hSuperseded by pci_get_subsys()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hjbubj )}(hhh](j )}(hhh]h)}(hpci_find_slot()h]hpci_find_slot()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubj )}(hhh]h)}(h+Superseded by pci_get_domain_bus_and_slot()h]h+Superseded by pci_get_domain_bus_and_slot()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]uh1j hjbubj )}(hhh](j )}(hhh]h)}(hpci_get_slot()h]hpci_get_slot()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1j hj ubj )}(hhh]h)}(h+Superseded by pci_get_domain_bus_and_slot()h]h+Superseded by pci_get_domain_bus_and_slot()}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj$ubah}(h]h ]h"]h$]h&]uh1j hj ubeh}(h]h ]h"]h$]h&]uh1j hjbubeh}(h]h ]h"]h$]h&]uh1j hjKubeh}(h]h ]h"]h$]h&]colsKuh1jq hjHubah}(h]h ]h"]h$]h&]uh1jl hj)hhhhhNubh)}(hyThe alternative is the traditional PCI device driver that walks PCI device lists. This is still possible but discouraged.h]hyThe alternative is the traditional PCI device driver that walks PCI device lists. This is still possible but discouraged.}(hjThhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj)hhubeh}(h]obsolete-functionsah ]h"]obsolete functionsah$]h&]uh1hhhhhhhhM ubh)}(hhh](h)}(hMMIO Space and "Write Posting"h]h"MMIO Space and “Write Posting”}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjjhhhhhMubh)}(hX$Converting a driver from using I/O Port space to using MMIO space often requires some additional changes. Specifically, "write posting" needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2) already do this. I/O Port space guarantees write transactions reach the PCI device before the CPU can continue. Writes to MMIO space allow the CPU to continue before the transaction reaches the PCI device. HW weenies call this "Write Posting" because the write completion is "posted" to the CPU before the transaction has reached its destination.h]hX0Converting a driver from using I/O Port space to using MMIO space often requires some additional changes. Specifically, “write posting” needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2) already do this. I/O Port space guarantees write transactions reach the PCI device before the CPU can continue. Writes to MMIO space allow the CPU to continue before the transaction reaches the PCI device. HW weenies call this “Write Posting” because the write completion is “posted” to the CPU before the transaction has reached its destination.}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjjhhubh)}(hThus, timing sensitive code should add readl() where the CPU is expected to wait before doing other work. The classic "bit banging" sequence works fine for I/O Port space::h]hThus, timing sensitive code should add readl() where the CPU is expected to wait before doing other work. The classic “bit banging” sequence works fine for I/O Port space:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM)hjjhhubj)}(hkfor (i = 8; --i; val >>= 1) { outb(val & 1, ioport_reg); /* write bit */ udelay(10); }h]hkfor (i = 8; --i; val >>= 1) { outb(val & 1, ioport_reg); /* write bit */ udelay(10); }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhM-hjjhhubh)}(h,The same sequence for MMIO space should be::h]h+The same sequence for MMIO space should be:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM2hjjhhubj)}(hfor (i = 8; --i; val >>= 1) { writeb(val & 1, mmio_reg); /* write bit */ readb(safe_mmio_reg); /* flush posted write */ udelay(10); }h]hfor (i = 8; --i; val >>= 1) { writeb(val & 1, mmio_reg); /* write bit */ readb(safe_mmio_reg); /* flush posted write */ udelay(10); }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhM4hjjhhubh)}(hxIt is important that "safe_mmio_reg" not have any side effects that interferes with the correct operation of the device.h]h|It is important that “safe_mmio_reg” not have any side effects that interferes with the correct operation of the device.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM:hjjhhubh)}(hXAnother case to watch out for is when resetting a PCI device. Use PCI Configuration space reads to flush the writel(). This will gracefully handle the PCI master abort on all platforms if the PCI device is expected to not respond to a readl(). Most x86 platforms will allow MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage (e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").h]hXAnother case to watch out for is when resetting a PCI device. Use PCI Configuration space reads to flush the writel(). This will gracefully handle the PCI master abort on all platforms if the PCI device is expected to not respond to a readl(). Most x86 platforms will allow MMIO reads to master abort (a.k.a. “Soft Fail”) and return garbage (e.g. ~0). But many RISC platforms will crash (a.k.a.”Hard Fail”).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM=hjjhhubeh}(h]mmio-space-and-write-postingah ]h"]mmio space and "write posting"ah$]h&]uh1hhhhhhhhMubeh}(h]how-to-write-linux-pci-driversah ]h"]how to write linux pci driversah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksj footnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjjj j j j jIjFj/j,j.j+jjjjj)j&jPjMj'j$jpjmjFjCjmjjjjjjjjjAj>jhjej jjzjwjjj&j#jgjdjju nametypes}(jjj j jIj/j.jjj)jPj'jpjFjmjjjjAjhj jzjj&jgjuh}(jhjjj jjjjjj jI jFj j,jLj+jEjj1jjj&jjMj,j$jSjmj2jCjjjjIjjpjjjjj>jjejDjjsjwjjj}j#jjdj)jjju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.