Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9564ad1 authored by Linas Vepstas's avatar Linas Vepstas Committed by Paul Mackerras
Browse files

[PATCH] ppc64: mark failed devices



17-eeh-slot-marking-bug.patch

A device that experiences a PCI outage may be just one deivce out
of many that was affected. In order to avoid repeated reports of
a failure, the entire tree of affected devices should be marked
as failed. This patch marks up the entire tree.

Signed-off-by: default avatarLinas Vepstas <linas@linas.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 0c95fbb2
Loading
Loading
Loading
Loading
+32 −16
Original line number Diff line number Diff line
@@ -478,32 +478,47 @@ static struct device_node * find_device_pe(struct device_node *dn)
 *  an interrupt context, which is bad.
 */

static void __eeh_mark_slot (struct device_node *dn)
static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
{
	while (dn) {
		PCI_DN(dn)->eeh_mode |= EEH_MODE_ISOLATED;
		if (PCI_DN(dn)) {
			PCI_DN(dn)->eeh_mode |= mode_flag;

			if (dn->child)
			__eeh_mark_slot (dn->child);
				__eeh_mark_slot (dn->child, mode_flag);
		}
		dn = dn->sibling;
	}
}

static void __eeh_clear_slot (struct device_node *dn)
void eeh_mark_slot (struct device_node *dn, int mode_flag)
{
	dn = find_device_pe (dn);
	PCI_DN(dn)->eeh_mode |= mode_flag;
	__eeh_mark_slot (dn->child, mode_flag);
}

static void __eeh_clear_slot (struct device_node *dn, int mode_flag)
{
	while (dn) {
		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_ISOLATED;
		if (PCI_DN(dn)) {
			PCI_DN(dn)->eeh_mode &= ~mode_flag;
			PCI_DN(dn)->eeh_check_count = 0;
			if (dn->child)
			__eeh_clear_slot (dn->child);
				__eeh_clear_slot (dn->child, mode_flag);
		}
		dn = dn->sibling;
	}
}

static inline void eeh_clear_slot (struct device_node *dn)
void eeh_clear_slot (struct device_node *dn, int mode_flag)
{
	unsigned long flags;
	spin_lock_irqsave(&confirm_error_lock, flags);
	__eeh_clear_slot (dn);
	dn = find_device_pe (dn);
	PCI_DN(dn)->eeh_mode &= ~mode_flag;
	PCI_DN(dn)->eeh_check_count = 0;
	__eeh_clear_slot (dn->child, mode_flag);
	spin_unlock_irqrestore(&confirm_error_lock, flags);
}

@@ -528,7 +543,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
	int rets[3];
	unsigned long flags;
	struct pci_dn *pdn;
	struct device_node *pe_dn;
	int rc = 0;

	__get_cpu_var(total_mmio_ffs)++;
@@ -630,8 +644,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
	/* Avoid repeated reports of this failure, including problems
	 * with other functions on this device, and functions under
	 * bridges. */
	pe_dn = find_device_pe (dn);
	__eeh_mark_slot (pe_dn);
	eeh_mark_slot (dn, EEH_MODE_ISOLATED);
	spin_unlock_irqrestore(&confirm_error_lock, flags);

	eeh_send_failure_event (dn, dev, rets[0], rets[2]);
@@ -743,9 +756,6 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
		        rc, state, pdn->node->full_name);
		return;
	}

	if (state == 0)
		eeh_clear_slot (pdn->node->parent->child);
}

/** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
@@ -764,6 +774,12 @@ rtas_set_slot_reset(struct pci_dn *pdn)

#define PCI_BUS_RST_HOLD_TIME_MSEC 250
	msleep (PCI_BUS_RST_HOLD_TIME_MSEC);
	
	/* We might get hit with another EEH freeze as soon as the 
	 * pci slot reset line is dropped. Make sure we don't miss
	 * these, and clear the flag now. */
	eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED);

	rtas_pci_slot_reset (pdn, 0);

	/* After a PCI slot has been reset, the PCI Express spec requires
+7 −0
Original line number Diff line number Diff line
@@ -87,6 +87,13 @@ void rtas_configure_bridge(struct pci_dn *);

int rtas_write_config(struct pci_dn *, int where, int size, u32 val);

/**
 * mark and clear slots: find "partition endpoint" PE and set or 
 * clear the flags for each subnode of the PE.
 */
void eeh_mark_slot (struct device_node *dn, int mode_flag);
void eeh_clear_slot (struct device_node *dn, int mode_flag);

#endif

#endif /* _ASM_POWERPC_PPC_PCI_H */