Set error_state to pci_channel_io_normal in eeh_report_reset()
Subsystems (2)
PATCH 1/1 Set error_state to pci_channel_io_normal in eeh_report_reset()
While adding native EEH support to Emulex and Qlogic drivers, it was discovered that dev->error_state was set to pci_io_channel_normal too late in the recovery process. These drivers rely on error_state to determine if they can access the device in their slot_reset callback, thus error_state needs to be set to pci_io_channel_norm in eeh_report_reset(). Below is a detailed explanation (courtesy of Richard Lary) as to why this is necessary.
Background:
PCI MMIO or DMA accesses to a frozen slot generate additional EEH errors. If the number of additional EEH errors exceeds EEH_MAX_FAILS the adapter will be shutdown. To avoid triggering excessive EEH errors and an undesirable adapter shutdown, some drivers use the pci_channel_offline(dev) wrapper function to return a Boolean value based on the value of pci_dev->error_state to determine if PCI MMIO or DMA accesses are safe. If the wrapper returns TRUE, drivers must not make PCI MMIO or DMA access to their hardware.
The pci_dev structure member error_state reflects one of three values, 1) pci_channel_io_normal, 2) pci_channel_io_frozen, 3) pci_channel_io_perm_failure. Function pci_channel_offline(dev) returns TRUE if error_state is pci_channel_io_frozen or pci_channel_io_perm_failure.
The EEH driver sets pci_dev->error_state to pci_channel_io_frozen at the point where the PCI slot is frozen. Currently, the EEH driver restores dev->error_state to pci_channel_io_normal in eeh_report_resume() before calling the driver's resume callback. However, when the EEH driver calls the driver's slot_reset callback() from eeh_report_reset(), it incorrectly indicates the error state is still pci_channel_io_frozen.
Waiting until eeh_report_resume() to restore dev->error_state to pci_channel_io_normal is too late for Emulex and QLogic FC drivers and any other drivers which are designed to use common code paths in these two cases: i) those called after the driver's slot_reset callback() and ii) those called after the PCI slot is frozen but before the driver's slot_reset callback is called. Case i) all driver paths executed to reinitialize the hardware after a reset and case ii) all code paths executed by driver kernel threads that run asynchronous to the main driver thread, such as interrupt handlers and worker threads to process driver work queues.
Emulex and QLogic FC drivers are designed with common code paths which require that pci_channel_offline(dev) reflect the true state of the hardware. The state transitions that the hardware takes from Normal Operations to Slot Frozen to Reset to Normal Operations are documented in the Power Architecture™ Platform Requirements+ (PAPR+) in Table 75. PE State Control.
PAPR defines the following 3 states:
0 -- Not reset, Not EEH stopped, MMIO load/store allowed, DMA allowed (Normal Operations) 1 -- Reset, Not EEH stopped, MMIO load/store disabled, DMA disabled
2 -- Not reset, EEH stopped, MMIO load/store disabled, DMA disabled (Slot Frozen)
An EEH error places the slot in state 2 (Frozen) and the adapter driver is notified that an EEH error was detected. If the adapter driver returns PCI_ERS_RESULT_NEED_RESET, the EEH driver calls eeh_reset_device() to place the slot into state 1 (Reset) and eeh_reset_device completes by placing the slot into State 0 (Normal Operations). Upon return from eeh_reset_device(), the EEH driver calls eeh_report_reset, which then calls the adapter's slot_reset callback. At the time the adapter's slot_reset callback is called, the true state of the hardware is Normal Operations and should be accurately reflected by setting dev->error_state to pci_channel_io_normal.
The current implementation of EEH driver does not do so and requires the following patch to correct this deficiency.
arch/powerpc/platforms/pseries/eeh_driver.c +0 -0
@@ -182,6 +182,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
if (!driver)
return;
+ dev->error_state = pci_channel_io_normal;
+eeh_enable_irq(dev);
if (!driver->err_handler ||
Hi,
2009/4/10 Mike Mason <[email protected]>:
Quoted 2 lines
While adding native EEH support to Emulex and Qlogic drivers, it was discovered that
dev->error_statewas set topci_io_channel_normaltoo lat=
e
Quoted 1 line
in the recovery process. These drivers rely on
error_stateto determine i=
f
Quoted 3 lines
they can access the device in their
slot_resetcallback, thuserror_stateneeds to be set topci_io_channel_normineeh_report_reset(). Below is a detailed explanation (courtesy of Richard Lary) as to why this is necessa=
ry.
Quoted 3 lines
Background:
PCI MMIO or DMA accesses to a frozen slot generate additional EEH errors.=
If
Quoted 1 line
the number of additional EEH errors exceeds
EEH_MAX_FAILSthe adapter wil=
l
Quoted 4 lines
be shutdown. To avoid triggering excessive EEH errors and an undesirable adapter shutdown, some drivers use the
pci_channel_offline(dev)wrapper function to return a Boolean value based on the value ofpci_dev->error_stateto determine if PCI MMIO or DMA accesses are safe. I=
f
Quoted 6 lines
the wrapper returns TRUE, drivers must not make PCI MMIO or DMA access to their hardware.
The
pci_devstructure membererror_statereflects one of three values, 1)pci_channel_io_normal, 2)pci_channel_io_frozen, 3)pci_channel_io_perm_failure. Functionpci_channel_offline(dev)returns TR=
UE
Quoted 6 lines
if
error_stateispci_channel_io_frozenorpci_channel_io_perm_failure.The EEH driver sets
pci_dev->error_statetopci_channel_io_frozenat the point where the PCI slot is frozen. Currently, the EEH driver restoresdev->error_statetopci_channel_io_normalineeh_report_resume()before calling the driver's resume callback. However, when the EEH driver calls =
the
Quoted 5 lines
driver's
slot_resetcallback()fromeeh_report_reset(), it incorrectly indicates the error state is stillpci_channel_io_frozen.Waiting until
eeh_report_resume()to restoredev->error_statetopci_channel_io_normalis too late for Emulex and QLogic FC drivers and an=
y
Quoted 3 lines
other drivers which are designed to use common code paths in these two
cases: i) those called after the driver'sslot_resetcallback()and ii) those called after the PCI slot is frozen but before the driver's slot_re=
set
Quoted 2 lines
callback is called. Case i) all driver paths executed to reinitialize the hardware after a reset and case ii) all code paths executed by driver ker=
nel
Quoted 1 line
threads that run asynchronous to the main driver thread, such as interrup=
t
Quoted 7 lines
handlers and worker threads to process driver work queues.
Emulex and QLogic FC drivers are designed with common code paths which require that
pci_channel_offline(dev)reflect the true state of the hardware. The state transitions that the hardware takes from Normal Operations to Slot Frozen to Reset to Normal Operations are documented in the Power Architecture=E2=84=A2 Platform Requirements+ (PAPR+) in Table 7=
5. PE State
Quoted 11 lines
Control.
PAPR defines the following 3 states:
0 -- Not reset, Not EEH stopped, MMIO load/store allowed, DMA allowed (Normal Operations)
1 -- Reset, Not EEH stopped, MMIO load/store disabled, DMA disabled 2 -- Not reset, EEH stopped, MMIO load/store disabled, DMA disabled (Slot Frozen)An EEH error places the slot in state 2 (Frozen) and the adapter driver i=
s
Quoted 2 lines
notified that an EEH error was detected. If the adapter driver returns
PCI_ERS_RESULT_NEED_RESET, the EEH driver callseeh_reset_device()to pla=
ce
Quoted 1 line
the slot into state 1 (Reset) and
eeh_reset_devicecompletes by placing t=
he
Quoted 1 line
slot into State 0 (Normal Operations). Upon return from eeh_reset_device(=
),
Quoted 4 lines
the EEH driver calls
eeh_report_reset, which then calls the adapter'sslot_resetcallback. At the time the adapter'sslot_resetcallback is called, the true state of the hardware is Normal Operations and should be accurately reflected by settingdev->error_stateto pci_channel_io_normal=
.
Quoted 5 lines
The current implementation of EEH driver does not do so and requires the following patch to correct this deficiency.
Signed-off-by Mike Mason <[email protected]>
Yes, the analysis sounds correct; this looks like the right thing to do.
I'm rather surprised, as this is an "obvious" bug, and should have been long gone. I thought that Emulex, QLogic were not the only ones that were using pci_channel_offline(dev) in this fashion. I thought that the symbios scsi and the e1000 did, too ... Hmm. Perhaps these used their own, private flag for the same purpose, and reset it at the earlier, correct time.
Thanks for the fix!
Quoted 14 lines · Mike Mason
arch/powerpc/platforms/pseries/eeh_driver.c +2
-0@@ -182,6 +182,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)if (!driver)return ; + dev->error_state = pci_channel_io_normal; +eeh_enable_irq (dev);
Quoted 1 line
if (!driver->err_handler ||
Your mail client totally mangled the whitespace. I fixed it up and applied it, since the patch was small, but in future please fix your mail client so it doesn't do that.
It sounds like this patch needs to be applied to earlier kernel versions -- do you agree?
Paul.
Paul Mackerras wrote: Mike Mason writes: diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 380420f..9a2a6e3 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -182,6 +182,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) if (!driver) return; + dev->error_state = pci_channel_io_normal; + eeh_enable_irq(dev); if (!driver->err_handler ||