powerpc/eeh: Device bars restore based on PE
The patch introduces the function to traverse the devices of the specified PE and its child PEs. Also, the restore on device bars is implemented based on the traverse function. Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:

committed by
Benjamin Herrenschmidt

부모
371a395d2f
커밋
9e6d2cf65e
@@ -610,85 +610,6 @@ int eeh_reset_pe(struct eeh_dev *edev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Save and restore of PCI BARs
|
||||
*
|
||||
* Although firmware will set up BARs during boot, it doesn't
|
||||
* set up device BAR's after a device reset, although it will,
|
||||
* if requested, set up bridge configuration. Thus, we need to
|
||||
* configure the PCI devices ourselves.
|
||||
*/
|
||||
|
||||
/**
|
||||
* eeh_restore_one_device_bars - Restore the Base Address Registers for one device
|
||||
* @edev: PCI device associated EEH device
|
||||
*
|
||||
* Loads the PCI configuration space base address registers,
|
||||
* the expansion ROM base address, the latency timer, and etc.
|
||||
* from the saved values in the device node.
|
||||
*/
|
||||
static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)
|
||||
{
|
||||
int i;
|
||||
u32 cmd;
|
||||
struct device_node *dn = eeh_dev_to_of_node(edev);
|
||||
|
||||
if (!edev->phb)
|
||||
return;
|
||||
|
||||
for (i=4; i<10; i++) {
|
||||
eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
|
||||
}
|
||||
|
||||
/* 12 == Expansion ROM Address */
|
||||
eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
|
||||
|
||||
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
|
||||
#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
|
||||
|
||||
eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
|
||||
SAVED_BYTE(PCI_CACHE_LINE_SIZE));
|
||||
|
||||
eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
|
||||
SAVED_BYTE(PCI_LATENCY_TIMER));
|
||||
|
||||
/* max latency, min grant, interrupt pin and line */
|
||||
eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
|
||||
|
||||
/* Restore PERR & SERR bits, some devices require it,
|
||||
* don't touch the other command bits
|
||||
*/
|
||||
eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
|
||||
if (edev->config_space[1] & PCI_COMMAND_PARITY)
|
||||
cmd |= PCI_COMMAND_PARITY;
|
||||
else
|
||||
cmd &= ~PCI_COMMAND_PARITY;
|
||||
if (edev->config_space[1] & PCI_COMMAND_SERR)
|
||||
cmd |= PCI_COMMAND_SERR;
|
||||
else
|
||||
cmd &= ~PCI_COMMAND_SERR;
|
||||
eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeh_restore_bars - Restore the PCI config space info
|
||||
* @edev: EEH device
|
||||
*
|
||||
* This routine performs a recursive walk to the children
|
||||
* of this device as well.
|
||||
*/
|
||||
void eeh_restore_bars(struct eeh_dev *edev)
|
||||
{
|
||||
struct device_node *dn;
|
||||
if (!edev)
|
||||
return;
|
||||
|
||||
if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))
|
||||
eeh_restore_one_device_bars(edev);
|
||||
|
||||
for_each_child_of_node(eeh_dev_to_of_node(edev), dn)
|
||||
eeh_restore_bars(of_node_to_eeh_dev(dn));
|
||||
}
|
||||
|
||||
/**
|
||||
* eeh_save_bars - Save device bars
|
||||
* @edev: PCI device associated EEH device
|
||||
|
Reference in New Issue
Block a user