Example #1
0
/**
 * eeh_reset_device - Perform actual reset of a pci slot
 * @edev: PE associated EEH device
 * @bus: PCI bus corresponding to the isolcated slot
 *
 * This routine must be called to do reset on the indicated PE.
 * During the reset, udev might be invoked because those affected
 * PCI devices will be removed and then added.
 */
static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
{
	struct device_node *dn;
	int cnt, rc;

	/* pcibios will clear the counter; save the value */
	cnt = edev->freeze_count;

	if (bus)
		pcibios_remove_pci_devices(bus);

	/* Reset the pci controller. (Asserts RST#; resets config space).
	 * Reconfigure bridges and devices. Don't try to bring the system
	 * up if the reset failed for some reason.
	 */
	rc = eeh_reset_pe(edev);
	if (rc)
		return rc;

	/* Walk over all functions on this device. */
	dn = eeh_dev_to_of_node(edev);
	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
		dn = dn->parent->child;

	while (dn) {
		struct eeh_dev *pedev = of_node_to_eeh_dev(dn);

		/* On Power4, always true because eeh_pe_config_addr=0 */
		if (edev->pe_config_addr == pedev->pe_config_addr) {
			eeh_ops->configure_bridge(dn);
			eeh_restore_bars(pedev);
 		}
		dn = dn->sibling;
	}

	/* Give the system 5 seconds to finish running the user-space
	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes, 
	 * this is a hack, but if we don't do this, and try to bring 
	 * the device up before the scripts have taken it down, 
	 * potentially weird things happen.
	 */
	if (bus) {
		ssleep(5);
		pcibios_add_pci_devices(bus);
	}
	edev->freeze_count = cnt;

	return 0;
}
Example #2
0
static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
{
	struct device_node *dn;
	int cnt, rc;

	
	cnt = edev->freeze_count;

	if (bus)
		pcibios_remove_pci_devices(bus);

	rc = eeh_reset_pe(edev);
	if (rc)
		return rc;

	
	dn = eeh_dev_to_of_node(edev);
	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
		dn = dn->parent->child;

	while (dn) {
		struct eeh_dev *pedev = of_node_to_eeh_dev(dn);

		
		if (edev->pe_config_addr == pedev->pe_config_addr) {
			eeh_ops->configure_bridge(dn);
			eeh_restore_bars(pedev);
 		}
		dn = dn->sibling;
	}

	if (bus) {
		ssleep(5);
		pcibios_add_pci_devices(bus);
	}
	edev->freeze_count = cnt;

	return 0;
}
Example #3
0
/**
 * eeh_reset_device - Perform actual reset of a pci slot
 * @pe: EEH PE
 * @bus: PCI bus corresponding to the isolcated slot
 *
 * This routine must be called to do reset on the indicated PE.
 * During the reset, udev might be invoked because those affected
 * PCI devices will be removed and then added.
 */
static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
{
	struct pci_bus *frozen_bus = eeh_pe_bus_get(pe);
	struct timeval tstamp;
	int cnt, rc, removed = 0;

	/* pcibios will clear the counter; save the value */
	cnt = pe->freeze_count;
	tstamp = pe->tstamp;

	/*
	 * We don't remove the corresponding PE instances because
	 * we need the information afterwords. The attached EEH
	 * devices are expected to be attached soon when calling
	 * into pcibios_add_pci_devices().
	 */
	eeh_pe_state_mark(pe, EEH_PE_KEEP);
	if (bus) {
		pci_lock_rescan_remove();
		pcibios_remove_pci_devices(bus);
		pci_unlock_rescan_remove();
	} else if (frozen_bus) {
		eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed);
	}

	/*
	 * Reset the pci controller. (Asserts RST#; resets config space).
	 * Reconfigure bridges and devices. Don't try to bring the system
	 * up if the reset failed for some reason.
	 *
	 * During the reset, it's very dangerous to have uncontrolled PCI
	 * 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_RESET);
	rc = eeh_reset_pe(pe);
	if (rc) {
		eeh_pe_state_clear(pe, EEH_PE_RESET);
		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_RESET);

	/* Clear frozen state */
	rc = eeh_clear_pe_frozen_state(pe);
	if (rc)
		return rc;

	/* Give the system 5 seconds to finish running the user-space
	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
	 * this is a hack, but if we don't do this, and try to bring
	 * the device up before the scripts have taken it down,
	 * potentially weird things happen.
	 */
	if (bus) {
		pr_info("EEH: Sleep 5s ahead of complete hotplug\n");
		ssleep(5);

		/*
		 * The EEH device is still connected with its parent
		 * PE. We should disconnect it so the binding can be
		 * rebuilt when adding PCI devices.
		 */
		eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
		pcibios_add_pci_devices(bus);
	} else if (frozen_bus && removed) {
		pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
		ssleep(5);

		eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
		pcibios_add_pci_devices(frozen_bus);
	}
	eeh_pe_state_clear(pe, EEH_PE_KEEP);

	pe->tstamp = tstamp;
	pe->freeze_count = cnt;

	pci_unlock_rescan_remove();
	return 0;
}