pci_device_reset()

Reset a device

Synopsis:

#include <pci/pci.h>

pci_err_t pci_device_reset( pci_devhdl_t hdl,
                            pci_resetType_e resetType );

Arguments:

hdl
The handle of the device, obtained by calling pci_device_attach().
resetType
The type of reset to initiate. The defined types are:
  • pci_resetType_e_BUS
  • pci_resetType_e_FUNCTION

A reset type that's less than pci_resetType_e_BUS is considered to mean “no reset” (a no-op).

A reset type that's greater than pci_resetType_e_FUNCTION is considered to be a hardware-specific reset. The behavior of hardware-specific resets, if supported, is defined by the hardware-dependent module. Refer to the release notes or the usage information in the hardware-dependent module applicable to your platform for details.

Library:

libpci

Use the -l pci option to qcc to link against this library.

Description:

The pci_device_reset() function initiates a reset of a specific device (function-level reset if the device is PCIe and supports FLR as determined by the device capabilities register or if the device is PCI and supports the Advanced Features capability and FLR as per the AF capabilities register) or of a PCI bus segment/PCIe link (secondary bus reset) if the device is a PCI-to-PCI bridge or PCIe Root Port that reports as a PCI-to-PCI bridge.

The hdl arguments identifies the specific device to be reset, or the bus or link on which the device resides.

Note: Since this API can potentially impact multiple devices, you must be sure of what you're doing. During the time that the reset is occurring, configuration space accesses to the device(s) is halted, but there's currently no in-band mechanism for preventing access to device-specific registers obtained from a successful call to pci_device_read_ba() and mmap()'d by other driver software. It's your responsibility to coordinate with such software as required.

The primary types of reset are:

pci_resetType_e_BUS
Reset all devices on the bus or link on which the device identified by hdl resides, including any downstream buses or links for subordinate bridges.
pci_resetType_e_FUNCTION
Reset only the specific device identified by hdl.

In both cases, you must be an owner of the device identified by hdl and the only remaining attacher.

Affected devices

For a function reset, only the device identified by hdl is reset. This includes a specific function of a multifunction device. You must be an owner of the device and the only remaining attacher (all other multiowned attachers, if any, must have detached). In addition, for bus/link resets, all devices that reside on the same bus/link as the device identified by hdl or that reside on a bus/link that's downstream of the bus/link on which the device identified by hdl resides are also reset. In this case, those devices must not have any attachments (i.e., no other software must have successfully called pci_device_attach() on these devices without having called pci_device_detach() prior to the reset operation). It's the responsibility of the application software to coordinate these operations for other affected device software, or the pci_device_reset() call will fail.

A reset of a specific device (i.e., a BDF) is supported by the PCI specification-defined Function Level Reset (FLR) mechanism. In order to initiate this type of reset, the device must either be a PCIe endpoint with bit 28 of the device capabilities register set to 01B or have the Advanced Features (AF) capability with bit 1 of the AF capabilities register set to 0B1, otherwise this reset is unsupported.

Other reset types are allowed, but these have no defined behavior within the PCI server, and so are passed directly to the hardware-dependent module. This allows for platform-specific reset processing to be accommodated. It's the responsibility of the hardware-dependent module to document what additional reset types if any it supports and what the behaviors of those resets are.

Although the hardware-dependent module has complete control over the reset behavior, the PCI server ensures that configuration space accesses to the device being reset are halted, and after reset, that the device is configured into the D0-initialized state unless otherwise prevented from doing so by the hardware-dependent module. All of the discussions that follow regarding post-reset state and interrupts are applicable to hardware-dependent reset types unless the hardware-dependent module documents otherwise.

Post-reset driver state

On return from a successful pci_device_reset(), your hdl is still valid, as are any mappings to address spaces obtained with a successful call to pci_device_read_ba(), but all capabilities are disabled. In order to use the capabilities, you need to:

Device software for other affected devices (if any), must go through the entire initialization phase starting with pci_device_attach(), because they were required to detach in order for the reset to take place.

Regarding interrupts

If the device was configured to use the MSI or MSI-X capability, the IRQs associated with the MSI/MSI-X vectors are released when the capability is disabled. Since MSI/MSI-X vectors are allocated when the capability is enabled, and these could potentially change between the disabling and reenabling of these capabilities, driver software should call InterruptDetach() for previously assigned IRQs, reread them with pci_device_read_irq(), and then reattach them with InterruptAttach() or InterruptAttachEvent().

If you aren't using MSI or MSI-X, you don't need to reread the pin-based IRQs originally returned because they don't change. That is, there's no need for the driver software to call InterruptDetach(), pci_device_read_irq(), and then InterruptAttach() or InterruptAttachEvent() after the reset if using pin-based (i.e., non-MSI or non-MSI-X) interrupts.

Returns:

If successful, a call to pci_device_reset() with a reset type of either pci_resetType_e_BUS or pci_resetType_e_FUNCTION returns PCI_ERR_OK, and all affected devices (as described above) have been reset and reconfigured to the D0-initialized state. Any driver software using those device must comprehend this condition and perform any required device-specific initialization that may have been lost as a result of the reset operation.

For reset types other than pci_resetType_e_BUS or pci_resetType_e_FUNCTION, the hardware-dependent module must document the post-reset state of affected devices.

If any error occurs, pci_device_reset() returns one of the following values, and you should consider all affected devices (as outlined above) to be in an unknown and unusable state. It this situation, it may be possible, and even desirable to reissue the reset command.

PCI_ERR_ENOTSUP
The reset type specified isn't supported by the device identified by hdl.
PCI_ERR_EINVAL
The hdl doesn't refer to a valid device that you attached to, or other parameters are otherwise invalid. The hardware-dependent module can also return this error.
PCI_ERR_ENODEV
The device identified by hdl doesn't exist. Note that this error can also be returned if a device that supports live removal is removed.
PCI_ERR_NOT_OWNER
You don't own the device identified by hdl.
PCI_ERR_ATTACH_SHARED
The device identified by hdl is currently attached to by more than just you.
PCI_ERR_ATTACH_OWNED
Devices on the same bus or link as the device identified by hdl or on a downstream bus or link are still attached.

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler No
Thread Yes