|
@@ -278,108 +278,6 @@ struct device_node *eeh_find_device_pe(struct device_node *dn)
|
|
|
return dn;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * __eeh_mark_slot - Mark all child devices as failed
|
|
|
- * @parent: parent device
|
|
|
- * @mode_flag: failure flag
|
|
|
- *
|
|
|
- * Mark all devices that are children of this device as failed.
|
|
|
- * Mark the device driver too, so that it can see the failure
|
|
|
- * immediately; this is critical, since some drivers poll
|
|
|
- * status registers in interrupts ... If a driver is polling,
|
|
|
- * and the slot is frozen, then the driver can deadlock in
|
|
|
- * an interrupt context, which is bad.
|
|
|
- */
|
|
|
-static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
|
|
|
-{
|
|
|
- struct device_node *dn;
|
|
|
-
|
|
|
- for_each_child_of_node(parent, dn) {
|
|
|
- if (of_node_to_eeh_dev(dn)) {
|
|
|
- /* Mark the pci device driver too */
|
|
|
- struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
|
|
|
-
|
|
|
- of_node_to_eeh_dev(dn)->mode |= mode_flag;
|
|
|
-
|
|
|
- if (dev && dev->driver)
|
|
|
- dev->error_state = pci_channel_io_frozen;
|
|
|
-
|
|
|
- __eeh_mark_slot(dn, mode_flag);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * eeh_mark_slot - Mark the indicated device and its children as failed
|
|
|
- * @dn: parent device
|
|
|
- * @mode_flag: failure flag
|
|
|
- *
|
|
|
- * Mark the indicated device and its child devices as failed.
|
|
|
- * The device drivers are marked as failed as well.
|
|
|
- */
|
|
|
-void eeh_mark_slot(struct device_node *dn, int mode_flag)
|
|
|
-{
|
|
|
- struct pci_dev *dev;
|
|
|
- dn = eeh_find_device_pe(dn);
|
|
|
-
|
|
|
- /* Back up one, since config addrs might be shared */
|
|
|
- if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
|
|
|
- dn = dn->parent;
|
|
|
-
|
|
|
- of_node_to_eeh_dev(dn)->mode |= mode_flag;
|
|
|
-
|
|
|
- /* Mark the pci device too */
|
|
|
- dev = of_node_to_eeh_dev(dn)->pdev;
|
|
|
- if (dev)
|
|
|
- dev->error_state = pci_channel_io_frozen;
|
|
|
-
|
|
|
- __eeh_mark_slot(dn, mode_flag);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * __eeh_clear_slot - Clear failure flag for the child devices
|
|
|
- * @parent: parent device
|
|
|
- * @mode_flag: flag to be cleared
|
|
|
- *
|
|
|
- * Clear failure flag for the child devices.
|
|
|
- */
|
|
|
-static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
|
|
|
-{
|
|
|
- struct device_node *dn;
|
|
|
-
|
|
|
- for_each_child_of_node(parent, dn) {
|
|
|
- if (of_node_to_eeh_dev(dn)) {
|
|
|
- of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
|
|
|
- of_node_to_eeh_dev(dn)->check_count = 0;
|
|
|
- __eeh_clear_slot(dn, mode_flag);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * eeh_clear_slot - Clear failure flag for the indicated device and its children
|
|
|
- * @dn: parent device
|
|
|
- * @mode_flag: flag to be cleared
|
|
|
- *
|
|
|
- * Clear failure flag for the indicated device and its children.
|
|
|
- */
|
|
|
-void eeh_clear_slot(struct device_node *dn, int mode_flag)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
- raw_spin_lock_irqsave(&confirm_error_lock, flags);
|
|
|
-
|
|
|
- dn = eeh_find_device_pe(dn);
|
|
|
-
|
|
|
- /* Back up one, since config addrs might be shared */
|
|
|
- if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
|
|
|
- dn = dn->parent;
|
|
|
-
|
|
|
- of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
|
|
|
- of_node_to_eeh_dev(dn)->check_count = 0;
|
|
|
- __eeh_clear_slot(dn, mode_flag);
|
|
|
- raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
|
|
|
* @dn: device node
|