Commit baf009f9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-4.8-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:
 "Fixes for code merged this cycle:

   - Fix restore of SPRs upon wake up from hypervisor state loss from
     Gautham R  Shenoy
   - Fix the state of root PE from Gavin Shan
   - Detach from PE on releasing PCI device from Gavin Shan
   - Fix size of NUM_CPU_FTR_KEYS on 32-bit
   - Fix missed TCE invalidations that should fallback to OPAL"

* tag 'powerpc-4.8-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/powernv/pci: Fix missed TCE invalidations that should fallback to OPAL
  powerpc/powernv: Detach from PE on releasing PCI device
  powerpc/powernv: Fix the state of root PE
  powerpc/kernel: Fix size of NUM_CPU_FTR_KEYS on 32-bit
  powerpc/powernv: Fix restore of SPRs upon wake up from hypervisor state loss
parents 4d2899d7 ed7d9a1d
...@@ -15,7 +15,7 @@ static inline bool early_cpu_has_feature(unsigned long feature) ...@@ -15,7 +15,7 @@ static inline bool early_cpu_has_feature(unsigned long feature)
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
#include <linux/jump_label.h> #include <linux/jump_label.h>
#define NUM_CPU_FTR_KEYS 64 #define NUM_CPU_FTR_KEYS BITS_PER_LONG
extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS]; extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
......
...@@ -411,7 +411,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) ...@@ -411,7 +411,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
* *
* r13 - PACA * r13 - PACA
* cr3 - gt if waking up with partial/complete hypervisor state loss * cr3 - gt if waking up with partial/complete hypervisor state loss
* cr4 - eq if waking up from complete hypervisor state loss. * cr4 - gt or eq if waking up from complete hypervisor state loss.
*/ */
_GLOBAL(pnv_wakeup_tb_loss) _GLOBAL(pnv_wakeup_tb_loss)
ld r1,PACAR1(r13) ld r1,PACAR1(r13)
...@@ -453,7 +453,7 @@ lwarx_loop2: ...@@ -453,7 +453,7 @@ lwarx_loop2:
* At this stage * At this stage
* cr2 - eq if first thread to wakeup in core * cr2 - eq if first thread to wakeup in core
* cr3- gt if waking up with partial/complete hypervisor state loss * cr3- gt if waking up with partial/complete hypervisor state loss
* cr4 - eq if waking up from complete hypervisor state loss. * cr4 - gt or eq if waking up from complete hypervisor state loss.
*/ */
ori r15,r15,PNV_CORE_IDLE_LOCK_BIT ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
...@@ -481,7 +481,7 @@ first_thread_in_subcore: ...@@ -481,7 +481,7 @@ first_thread_in_subcore:
* If waking up from sleep, subcore state is not lost. Hence * If waking up from sleep, subcore state is not lost. Hence
* skip subcore state restore * skip subcore state restore
*/ */
bne cr4,subcore_state_restored blt cr4,subcore_state_restored
/* Restore per-subcore state */ /* Restore per-subcore state */
ld r4,_SDR1(r1) ld r4,_SDR1(r1)
...@@ -526,7 +526,7 @@ timebase_resync: ...@@ -526,7 +526,7 @@ timebase_resync:
* If waking up from sleep, per core state is not lost, skip to * If waking up from sleep, per core state is not lost, skip to
* clear_lock. * clear_lock.
*/ */
bne cr4,clear_lock blt cr4,clear_lock
/* /*
* First thread in the core to wake up and its waking up with * First thread in the core to wake up and its waking up with
...@@ -557,7 +557,7 @@ common_exit: ...@@ -557,7 +557,7 @@ common_exit:
* If waking up from sleep, hypervisor state is not lost. Hence * If waking up from sleep, hypervisor state is not lost. Hence
* skip hypervisor state restore. * skip hypervisor state restore.
*/ */
bne cr4,hypervisor_state_restored blt cr4,hypervisor_state_restored
/* Waking up from winkle */ /* Waking up from winkle */
......
...@@ -2217,7 +2217,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group, ...@@ -2217,7 +2217,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group,
pnv_pci_link_table_and_group(phb->hose->node, num, pnv_pci_link_table_and_group(phb->hose->node, num,
tbl, &pe->table_group); tbl, &pe->table_group);
pnv_pci_phb3_tce_invalidate_pe(pe); pnv_pci_ioda2_tce_invalidate_pe(pe);
return 0; return 0;
} }
...@@ -2355,7 +2355,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group, ...@@ -2355,7 +2355,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group,
if (ret) if (ret)
pe_warn(pe, "Unmapping failed, ret = %ld\n", ret); pe_warn(pe, "Unmapping failed, ret = %ld\n", ret);
else else
pnv_pci_phb3_tce_invalidate_pe(pe); pnv_pci_ioda2_tce_invalidate_pe(pe);
pnv_pci_unlink_table_and_group(table_group->tables[num], table_group); pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
...@@ -3426,6 +3426,16 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe) ...@@ -3426,6 +3426,16 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
} }
} }
/*
* The PE for root bus can be removed because of hotplug in EEH
* recovery for fenced PHB error. We need to mark the PE dead so
* that it can be populated again in PCI hot add path. The PE
* shouldn't be destroyed as it's the global reserved resource.
*/
if (phb->ioda.root_pe_populated &&
phb->ioda.root_pe_idx == pe->pe_number)
phb->ioda.root_pe_populated = false;
else
pnv_ioda_free_pe(pe); pnv_ioda_free_pe(pe);
} }
...@@ -3442,7 +3452,17 @@ static void pnv_pci_release_device(struct pci_dev *pdev) ...@@ -3442,7 +3452,17 @@ static void pnv_pci_release_device(struct pci_dev *pdev)
if (!pdn || pdn->pe_number == IODA_INVALID_PE) if (!pdn || pdn->pe_number == IODA_INVALID_PE)
return; return;
/*
* PCI hotplug can happen as part of EEH error recovery. The @pdn
* isn't removed and added afterwards in this scenario. We should
* set the PE number in @pdn to an invalid one. Otherwise, the PE's
* device count is decreased on removing devices while failing to
* be increased on adding devices. It leads to unbalanced PE's device
* count and eventually make normal PCI hotplug path broken.
*/
pe = &phb->ioda.pe_array[pdn->pe_number]; pe = &phb->ioda.pe_array[pdn->pe_number];
pdn->pe_number = IODA_INVALID_PE;
WARN_ON(--pe->device_count < 0); WARN_ON(--pe->device_count < 0);
if (pe->device_count == 0) if (pe->device_count == 0)
pnv_ioda_release_pe(pe); pnv_ioda_release_pe(pe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment