mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 01:54:00 +00:00
powerpc/eeh: Set EEH_PE_RESET on PE reset
The patch introduces additional flag EEH_PE_RESET to indicate the corresponding PE is under reset. In turn, the PE retrieval bakcend on PowerNV platform can return unfrozen state for the EEH core to moving forward. Flag EEH_PE_CFG_BLOCKED isn't the correct one for the purpose. In PCI passthrou case, the problem is more worse: Guest doesn't recover 6th EEH error. The PE is left in isolated (frozen) and config blocked state on Broadcom adapters. We can't retrieve the PE's state correctly any more, even from the host side via sysfs /sys/bus/pci/devices/xxx/eeh_pe_state. Reported-by: Rajeshkumar Subramanian <rajeshkumars@in.ibm.com> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
b85743ee95
commit
28bf36f92a
@ -72,6 +72,7 @@ struct device_node;
|
||||
#define EEH_PE_ISOLATED (1 << 0) /* Isolated PE */
|
||||
#define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */
|
||||
#define EEH_PE_CFG_BLOCKED (1 << 2) /* Block config access */
|
||||
#define EEH_PE_RESET (1 << 3) /* PE reset in progress */
|
||||
|
||||
#define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */
|
||||
#define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */
|
||||
|
@ -760,6 +760,9 @@ int eeh_reset_pe(struct eeh_pe *pe)
|
||||
int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
|
||||
int i, state, ret;
|
||||
|
||||
/* Mark as reset and block config space */
|
||||
eeh_pe_state_mark(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
|
||||
|
||||
/* Take three shots at resetting the bus */
|
||||
for (i = 0; i < 3; i++) {
|
||||
eeh_reset_pe_once(pe);
|
||||
@ -788,6 +791,7 @@ int eeh_reset_pe(struct eeh_pe *pe)
|
||||
}
|
||||
|
||||
out:
|
||||
eeh_pe_state_clear(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -528,13 +528,11 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
|
||||
eeh_pe_dev_traverse(pe, eeh_report_error, &result);
|
||||
|
||||
/* Issue reset */
|
||||
eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
|
||||
ret = eeh_reset_pe(pe);
|
||||
if (ret) {
|
||||
eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_CFG_BLOCKED);
|
||||
eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
|
||||
return ret;
|
||||
}
|
||||
eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
|
||||
|
||||
/* Unfreeze the PE */
|
||||
ret = eeh_clear_pe_frozen_state(pe, true);
|
||||
@ -601,19 +599,15 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
|
||||
* config accesses. So we prefer to block them. However, controlled
|
||||
* PCI config accesses initiated from EEH itself are allowed.
|
||||
*/
|
||||
eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
|
||||
rc = eeh_reset_pe(pe);
|
||||
if (rc) {
|
||||
eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
/* Restore PE */
|
||||
eeh_ops->configure_bridge(pe);
|
||||
eeh_pe_restore_bars(pe);
|
||||
eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
|
||||
|
||||
/* Clear frozen state */
|
||||
rc = eeh_clear_pe_frozen_state(pe, false);
|
||||
|
@ -372,7 +372,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
|
||||
* moving forward, we have to return operational
|
||||
* state during PE reset.
|
||||
*/
|
||||
if (pe->state & EEH_PE_CFG_BLOCKED) {
|
||||
if (pe->state & EEH_PE_RESET) {
|
||||
result = (EEH_STATE_MMIO_ACTIVE |
|
||||
EEH_STATE_DMA_ACTIVE |
|
||||
EEH_STATE_MMIO_ENABLED |
|
||||
|
Loading…
x
Reference in New Issue
Block a user