eeh_init_multifunc Kernel Service

Purpose

This kernel service registers a multifunction adapter slot on a PCI/PCI-E bus for EEH function.

Syntax

#include <sys/eeh.h>

eeh_handle_t eeh_init_multifunc(gpbid, pbid, slot, flag, delay_seconds, 
                                callback_ptr, dds_ptr)
long gpbid;
long pbid;
long slot;
long flag;
long delay_seconds;
long (*callback_ptr)();
void *dds_ptr;

Parameters

Item Description
gpbid Bus identifier of grandparent bus.
pbid Bus identifier of parent bus.
slot Slot on the parent bus (device*8+function). This is same as "connwhere" property in CuDv for the device.
flag Flag that enables eeh, checks if the slot is already taken, etc.
delay_seconds Time delay after a reset (in seconds).
callback_ptr Device driver callback routine.
dds_ptr Cookie to a target device driver that is usually a pointer to the adapter structure.

Description

This kernel service is provided for systems that support shared EEH domain, where one or more PCI functions in one or more adapters could belong to the same EEH recovery domain. In the past, this was called "multifunction adapter". The shared EEH domain is a more general concept than just a multifunction adapter. It is also recommended that single function adapters use the shared EEH model. All PCI-E devices, single or multifunction have to use the shared EEH model and hence this kernel service to register for EEH (instead of eeh_init()). In a shared EEH domain, multiple instances of device drivers may be operating. The instances are independent of each other and hence oblivious to each other's existence. Therefore, when recovering a slot from an EEH event, there is a need to coordinate the recovery procedure among them. As with eeh_init(), this service also returns an eeh_handle to the calling device driver.

There are two kinds of adapters: bridged and non-bridged. A bridged adapter has a bridge on the card such as PCI-to-PCI or PCIX-to-PCIX or PCI-E switch. For PCI and PCI-X bridged-adapters, pbid is the bus ID of the parent bus, and gpbid is the bus ID of the grandparent bus. The parent bus for a bridged adapter is the bus generated by the bridge/switch on the adapter. A bid identifies a bus number and type. The bus type is IO_PCI in the case of PCI and PCI-X bus, and IO_PCIE in the case of PCI-E bus. The bus number is a unique identifier determined during bus configuration. The BID_VAL macro defined in ioacc.h is used to generate the bid. For non-bridged adapters, pbid and gpbid are the same and are the bus IDs of the parent bus. Thus, when pbid and gpbid have different values for a PCI or PCI-X device, the kernel knows that this is a bridged adapter and needs to the bridge recovered as part of EEH recovery. It is not necessary to know if a PCI-E device is bridged or not for the purposes of EEH. Therefore, pbid and gpbid must be same and equal to the parent bus bid.

In summary, there are the following cases:
  1. PCI/PCI-X non-bridged adapters and all PCI-E adapters: gpbid and pbid are same and equal to the parent bus bid.
  2. PCI/PCI-X bridged adapters, gpbid is grandparent bus bid, and pbid is parent bus bid.

The slot argument is the device/function combination ((device* 8) + function) as in the PCI addressing scheme. This is the same as the connwhere ODM value of the device.

The following flag values are legal:
Item Description
EEH_ENABLE_FLAG/EEH_DISABLE_FLAG The slot is always enabled for EEH when this service is called by the first driver on that slot. All subsequent requests to enable the slot via the EEH_ENABLE flag are ignored. Therefore, the flag argument of EEH_ENABLE is optional, and a flag of EEH_DISABLE is ignored.
EEH_CHECK_SLOT The flag argument of EEH_CHECK_SLOT verifies whether a given slot is already registered. A value of either EEH_SLOT_ACTIVE or EEH_SLOT_FREE is returned. No registration occurs with the EEH_CHECK_SLOT flag, and it supersedes all other flags. This flag simply checks the slot and returns without any other action.
EEH_ENABLE_NO_SUPPORT_RC If the flag is set to EEH_ENABLE_NO_SUPPORT_RC, eeh_enable_pio() and eeh_enable_dma() return EEH_NO_SUPPORT under certain conditions. See eeh_enable_dma Kernel Service and eeh_enable_pio Kernel Service for more information.

Multiple flags can be logically ORed together.

The slot is always enabled for EEH when this service is called by the first driver on that slot. All subsequent requests to enable the slot via the EEH_ENABLE flag are ignored. Therefore, the flag argument of EEH_ENABLE is optional, and a flag of EEH_DISABLE is ignored. The flag argument of EEH_CHECK_SLOT verifies whether a given slot is already registered. A value of either EEH_SLOT_ACTIVE or EEH_SLOT_FREE is returned. No registration will occur with the EEH_CHECK_SLOT flag, and it supersedes all other flags. This flag just checks the slot and returns without any other action. If the flag is set to EEH_ENABLE_NO_SUPPORT_RC, eeh_enable_pio() and eeh_enable_dma() returns EEH_NO_SUPPORT under certain conditions. See eeh_enable_pio() and eeh_enable_dma() for more information. It is allowed to logically OR multiple flags together.

The delay_seconds argument allows the device driver to set a time delay between completion of PCI reset and configuration of the bridge on the adapter. The delay is enforced even if the adapter is non-bridged. If a value of 0 is specified for delay_seconds, a default delay time of 1 second is set. When several drivers register on the same pbid (under a shared EEH domain), the highest delay time among all registered drivers is used.

The callback_ptr argument is a function pointer to an EEH callback routine. The handler is defined by the device driver and is called by the kernel in order to coordinate recovery among different drivers on the same slot. The driver handles a variety of messages from the kernel in its callback routine. These messages trigger the next step in recovery. The callback routines are called sequentially at INTIODONE interrupt level.

The dds_ptr argument is a cookie that is passed to the driver when the callback routine is invoked. Drivers normally specify a pointer to the device driver's adapter structure.

EEH_SAFE mode: A bridged adapter needs to have its bridge reconfigured at the end of PCI reset. However, if the platform firmware does not support reconfiguration of the bridge, the adapter is marked as EEH_SAFE by the kernel. An EEH_SAFE adapter cannot finish error recovery after an EEH event because of the unsatisfied firmware dependency. See eeh_reset_slot for information on how the error recovery is handled in EEH_SAFE mode.

The macro EEH_INIT_MULTIFUNC(gpbid, pbid, slot, flag, delay_seconds, callback_ptr, dds_ptr) is provided for the device drivers in order to call this service. This is an exported kernel service.

Execution Environment

This kernel service can only be called from the process environment.

Return Values

Item Description
EEH_FAIL Unable to allocate EEH handle.
EEH_NO_SUPPORT EEH is not supported on this system, no handle allocated.
EEH_SLOT_ACTIVE Given slot is already registered.
EEH_SLOT_FREE Given slot free.
EEH_BUSY Unable to continue, because the slot is in the middle of error recovery.
struct eeh_handle * Upon Success.