struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
 int eeh_pe_set_option(struct eeh_pe *pe, int option);
 int eeh_pe_get_state(struct eeh_pe *pe);
-int eeh_pe_reset(struct eeh_pe *pe, int option);
+int eeh_pe_reset(struct eeh_pe *pe, int option, bool include_passed);
 int eeh_pe_configure(struct eeh_pe *pe);
 int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func,
                      unsigned long addr, unsigned long mask);
 
 struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
 void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
 int eeh_pci_enable(struct eeh_pe *pe, int function);
-int eeh_pe_reset_full(struct eeh_pe *pe);
+int eeh_pe_reset_full(struct eeh_pe *pe, bool include_passed);
 void eeh_save_bars(struct eeh_dev *edev);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 
        return NULL;
 }
 
+static void eeh_pe_refreeze_passed(struct eeh_pe *root)
+{
+       struct eeh_pe *pe;
+       int state;
+
+       eeh_for_each_pe(root, pe) {
+               if (eeh_pe_passed(pe)) {
+                       state = eeh_ops->get_state(pe, NULL);
+                       if (state &
+                          (EEH_STATE_MMIO_ACTIVE | EEH_STATE_MMIO_ENABLED)) {
+                               pr_info("EEH: Passed-through PE PHB#%x-PE#%x was thawed by reset, re-freezing for safety.\n",
+                                       pe->phb->global_number, pe->addr);
+                               eeh_pe_set_option(pe, EEH_OPT_FREEZE_PE);
+                       }
+               }
+       }
+}
+
 /**
  * eeh_pe_reset_full - Complete a full reset process on the indicated PE
  * @pe: EEH PE
  *
  * This function will attempt to reset a PE three times before failing.
  */
-int eeh_pe_reset_full(struct eeh_pe *pe)
+int eeh_pe_reset_full(struct eeh_pe *pe, bool include_passed)
 {
        int reset_state = (EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
        int type = EEH_RESET_HOT;
 
        /* Make three attempts at resetting the bus */
        for (i = 0; i < 3; i++) {
-               ret = eeh_pe_reset(pe, type);
+               ret = eeh_pe_reset(pe, type, include_passed);
                if (ret)
                        break;
 
-               ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
+               ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE, include_passed);
                if (ret)
                        break;
 
                        __func__, state, pe->phb->global_number, pe->addr, (i + 1));
        }
 
+       /* Resetting the PE may have unfrozen child PEs. If those PEs have been
+        * (potentially) passed through to a guest, re-freeze them:
+        */
+       if (!include_passed)
+               eeh_pe_refreeze_passed(pe);
+
        eeh_pe_state_clear(pe, reset_state, true);
        return ret;
 }
 }
 EXPORT_SYMBOL_GPL(eeh_pe_get_state);
 
-static int eeh_pe_reenable_devices(struct eeh_pe *pe)
+static int eeh_pe_reenable_devices(struct eeh_pe *pe, bool include_passed)
 {
        struct eeh_dev *edev, *tmp;
        struct pci_dev *pdev;
        int ret = 0;
 
-       /* Restore config space */
        eeh_pe_restore_bars(pe);
 
        /*
        }
 
        /* The PE is still in frozen state */
-       ret = eeh_unfreeze_pe(pe);
+       if (include_passed || !eeh_pe_passed(pe)) {
+               ret = eeh_unfreeze_pe(pe);
+       } else
+               pr_info("EEH: Note: Leaving passthrough PHB#%x-PE#%x frozen.\n",
+                       pe->phb->global_number, pe->addr);
        if (!ret)
-               eeh_pe_state_clear(pe, EEH_PE_ISOLATED, true);
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED, include_passed);
        return ret;
 }
 
  * indicated type, either fundamental reset or hot reset.
  * PE reset is the most important part for error recovery.
  */
-int eeh_pe_reset(struct eeh_pe *pe, int option)
+int eeh_pe_reset(struct eeh_pe *pe, int option, bool include_passed)
 {
        int ret = 0;
 
        switch (option) {
        case EEH_RESET_DEACTIVATE:
                ret = eeh_ops->reset(pe, option);
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, true);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, include_passed);
                if (ret)
                        break;
 
-               ret = eeh_pe_reenable_devices(pe);
+               ret = eeh_pe_reenable_devices(pe, include_passed);
                break;
        case EEH_RESET_HOT:
        case EEH_RESET_FUNDAMENTAL:
 
         * support EEH. So we just care about PCI devices for
         * simplicity here.
         */
-       if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
-               return NULL;
-
-       /*
-        * We rely on count-based pcibios_release_device() to
-        * detach permanently offlined PEs. Unfortunately, that's
-        * not reliable enough. We might have the permanently
-        * offlined PEs attached, but we needn't take care of
-        * them and their child devices.
-        */
-       if (eeh_dev_removed(edev))
+       if (!eeh_edev_actionable(edev) ||
+           (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
                return NULL;
 
        if (rmv_data) {
-               if (eeh_pe_passed(edev->pe))
-                       return NULL;
                driver = eeh_pcid_get(dev);
                if (driver) {
                        if (driver->err_handler &&
        }
 
        /* Remove it from PCI subsystem */
-       pr_debug("EEH: Removing %s without EEH sensitive driver\n",
-                pci_name(dev));
+       pr_info("EEH: Removing %s without EEH sensitive driver\n",
+               pci_name(dev));
        edev->mode |= EEH_DEV_DISCONNECTED;
        if (rmv_data)
                rmv_data->removed_dev_count++;
        eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
        /* Issue reset */
-       ret = eeh_pe_reset_full(pe);
+       ret = eeh_pe_reset_full(pe, true);
        if (ret) {
                eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
                return ret;
        time64_t tstamp;
        int cnt, rc;
        struct eeh_dev *edev;
+       struct eeh_pe *tmp_pe;
+       bool any_passed = false;
+
+       eeh_for_each_pe(pe, tmp_pe)
+               any_passed |= eeh_pe_passed(tmp_pe);
 
        /* pcibios will clear the counter; save the value */
        cnt = pe->freeze_count;
         * into pci_hp_add_devices().
         */
        eeh_pe_state_mark(pe, EEH_PE_KEEP);
-       if (driver_eeh_aware || (pe->type & EEH_PE_VF)) {
+       if (any_passed || driver_eeh_aware || (pe->type & EEH_PE_VF)) {
                eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data);
        } else {
                pci_lock_rescan_remove();
         * config accesses. So we prefer to block them. However, controlled
         * PCI config accesses initiated from EEH itself are allowed.
         */
-       rc = eeh_pe_reset_full(pe);
+       rc = eeh_pe_reset_full(pe, false);
        if (rc)
                return rc;
 
        eeh_pe_restore_bars(pe);
 
        /* Clear frozen state */
-       rc = eeh_clear_pe_frozen_state(pe, true);
+       rc = eeh_clear_pe_frozen_state(pe, false);
        if (rc) {
                pci_unlock_rescan_remove();
                return rc;
 
                        ret = eeh_pe_get_state(pe);
                        break;
                case VFIO_EEH_PE_RESET_DEACTIVATE:
-                       ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
+                       ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE, true);
                        break;
                case VFIO_EEH_PE_RESET_HOT:
-                       ret = eeh_pe_reset(pe, EEH_RESET_HOT);
+                       ret = eeh_pe_reset(pe, EEH_RESET_HOT, true);
                        break;
                case VFIO_EEH_PE_RESET_FUNDAMENTAL:
-                       ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL);
+                       ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL, true);
                        break;
                case VFIO_EEH_PE_CONFIGURE:
                        ret = eeh_pe_configure(pe);