Commit 750137ec authored by Michael Ellerman's avatar Michael Ellerman

Merge branch 'fixes' into topic/ppc-kvm

Merge our fixes branch. In parciular this brings in the KVM TCE handling
fix, which is a prerequisite for a subsequent patch.
parents 1d1cd0f1 ee834849
...@@ -615,23 +615,22 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt) ...@@ -615,23 +615,22 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
return; return;
} }
/* Conditionally hard-enable interrupts. */ /*
if (should_hard_irq_enable()) { * Ensure a positive value is written to the decrementer, or
/* * else some CPUs will continue to take decrementer exceptions.
* Ensure a positive value is written to the decrementer, or * When the PPC_WATCHDOG (decrementer based) is configured,
* else some CPUs will continue to take decrementer exceptions. * keep this at most 31 bits, which is about 4 seconds on most
* When the PPC_WATCHDOG (decrementer based) is configured, * systems, which gives the watchdog a chance of catching timer
* keep this at most 31 bits, which is about 4 seconds on most * interrupt hard lockups.
* systems, which gives the watchdog a chance of catching timer */
* interrupt hard lockups. if (IS_ENABLED(CONFIG_PPC_WATCHDOG))
*/ set_dec(0x7fffffff);
if (IS_ENABLED(CONFIG_PPC_WATCHDOG)) else
set_dec(0x7fffffff); set_dec(decrementer_max);
else
set_dec(decrementer_max);
/* Conditionally hard-enable interrupts. */
if (should_hard_irq_enable())
do_hard_irq_enable(); do_hard_irq_enable();
}
#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC) #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
if (atomic_read(&ppc_n_lost_interrupts) != 0) if (atomic_read(&ppc_n_lost_interrupts) != 0)
......
...@@ -22,12 +22,15 @@ ...@@ -22,12 +22,15 @@
.macro cvdso_call funct call_time=0 .macro cvdso_call funct call_time=0
.cfi_startproc .cfi_startproc
PPC_STLU r1, -PPC_MIN_STKFRM(r1) PPC_STLU r1, -PPC_MIN_STKFRM(r1)
.cfi_adjust_cfa_offset PPC_MIN_STKFRM
mflr r0 mflr r0
.cfi_register lr, r0
PPC_STLU r1, -PPC_MIN_STKFRM(r1) PPC_STLU r1, -PPC_MIN_STKFRM(r1)
.cfi_adjust_cfa_offset PPC_MIN_STKFRM
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
.cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF
#ifdef __powerpc64__ #ifdef __powerpc64__
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
#endif #endif
get_datapage r5 get_datapage r5
.ifeq \call_time .ifeq \call_time
...@@ -39,13 +42,15 @@ ...@@ -39,13 +42,15 @@
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
#ifdef __powerpc64__ #ifdef __powerpc64__
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
.cfi_restore r2
#endif #endif
.ifeq \call_time .ifeq \call_time
cmpwi r3, 0 cmpwi r3, 0
.endif .endif
mtlr r0 mtlr r0
.cfi_restore lr
addi r1, r1, 2 * PPC_MIN_STKFRM addi r1, r1, 2 * PPC_MIN_STKFRM
.cfi_restore lr
.cfi_def_cfa_offset 0
crclr so crclr so
.ifeq \call_time .ifeq \call_time
beqlr+ beqlr+
......
...@@ -122,11 +122,27 @@ ...@@ -122,11 +122,27 @@
/* 0x0 - 0xb */ /* 0x0 - 0xb */
/* 'current->mm' needs to be in r4 */ /* switch_mmu_context() needs paging, let's enable it */
tophys(r4, r2) mfmsr r9
lwz r4, MM(r4) ori r11, r9, MSR_DR
tophys(r4, r4) mtmsr r11
/* This only clobbers r0, r3, r4 and r5 */ sync
/* switch_mmu_context() clobbers r12, rescue it */
SAVE_GPR(12, r1)
/* Calling switch_mmu_context(<inv>, current->mm, <inv>); */
lwz r4, MM(r2)
bl switch_mmu_context bl switch_mmu_context
/* restore r12 */
REST_GPR(12, r1)
/* Disable paging again */
mfmsr r9
li r6, MSR_DR
andc r9, r9, r6
mtmsr r9
sync
.endm .endm
...@@ -420,13 +420,19 @@ static void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt, ...@@ -420,13 +420,19 @@ static void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt,
tbl[idx % TCES_PER_PAGE] = tce; tbl[idx % TCES_PER_PAGE] = tce;
} }
static void kvmppc_clear_tce(struct mm_struct *mm, struct iommu_table *tbl, static void kvmppc_clear_tce(struct mm_struct *mm, struct kvmppc_spapr_tce_table *stt,
unsigned long entry) struct iommu_table *tbl, unsigned long entry)
{ {
unsigned long hpa = 0; unsigned long i;
enum dma_data_direction dir = DMA_NONE; unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
for (i = 0; i < subpages; ++i) {
unsigned long hpa = 0;
enum dma_data_direction dir = DMA_NONE;
iommu_tce_xchg_no_kill(mm, tbl, entry, &hpa, &dir); iommu_tce_xchg_no_kill(mm, tbl, io_entry + i, &hpa, &dir);
}
} }
static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm, static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm,
...@@ -485,6 +491,8 @@ static long kvmppc_tce_iommu_unmap(struct kvm *kvm, ...@@ -485,6 +491,8 @@ static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
break; break;
} }
iommu_tce_kill(tbl, io_entry, subpages);
return ret; return ret;
} }
...@@ -544,6 +552,8 @@ static long kvmppc_tce_iommu_map(struct kvm *kvm, ...@@ -544,6 +552,8 @@ static long kvmppc_tce_iommu_map(struct kvm *kvm,
break; break;
} }
iommu_tce_kill(tbl, io_entry, subpages);
return ret; return ret;
} }
...@@ -590,10 +600,9 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, ...@@ -590,10 +600,9 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl, ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
entry, ua, dir); entry, ua, dir);
iommu_tce_kill(stit->tbl, entry, 1);
if (ret != H_SUCCESS) { if (ret != H_SUCCESS) {
kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry); kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry);
goto unlock_exit; goto unlock_exit;
} }
} }
...@@ -669,13 +678,13 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, ...@@ -669,13 +678,13 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
*/ */
if (get_user(tce, tces + i)) { if (get_user(tce, tces + i)) {
ret = H_TOO_HARD; ret = H_TOO_HARD;
goto invalidate_exit; goto unlock_exit;
} }
tce = be64_to_cpu(tce); tce = be64_to_cpu(tce);
if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) { if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) {
ret = H_PARAMETER; ret = H_PARAMETER;
goto invalidate_exit; goto unlock_exit;
} }
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
...@@ -684,19 +693,15 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, ...@@ -684,19 +693,15 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
iommu_tce_direction(tce)); iommu_tce_direction(tce));
if (ret != H_SUCCESS) { if (ret != H_SUCCESS) {
kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl,
entry); entry + i);
goto invalidate_exit; goto unlock_exit;
} }
} }
kvmppc_tce_put(stt, entry + i, tce); kvmppc_tce_put(stt, entry + i, tce);
} }
invalidate_exit:
list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
iommu_tce_kill(stit->tbl, entry, npages);
unlock_exit: unlock_exit:
srcu_read_unlock(&vcpu->kvm->srcu, idx); srcu_read_unlock(&vcpu->kvm->srcu, idx);
...@@ -735,20 +740,16 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu, ...@@ -735,20 +740,16 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
continue; continue;
if (ret == H_TOO_HARD) if (ret == H_TOO_HARD)
goto invalidate_exit; return ret;
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry); kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry + i);
} }
} }
for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value); kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value);
invalidate_exit:
list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
iommu_tce_kill(stit->tbl, ioba >> stt->page_shift, npages);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce); EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce);
...@@ -247,13 +247,19 @@ static void iommu_tce_kill_rm(struct iommu_table *tbl, ...@@ -247,13 +247,19 @@ static void iommu_tce_kill_rm(struct iommu_table *tbl,
tbl->it_ops->tce_kill(tbl, entry, pages, true); tbl->it_ops->tce_kill(tbl, entry, pages, true);
} }
static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl, static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt,
unsigned long entry) struct iommu_table *tbl, unsigned long entry)
{ {
unsigned long hpa = 0; unsigned long i;
enum dma_data_direction dir = DMA_NONE; unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
for (i = 0; i < subpages; ++i) {
unsigned long hpa = 0;
enum dma_data_direction dir = DMA_NONE;
iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir);
}
} }
static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
...@@ -316,6 +322,8 @@ static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm, ...@@ -316,6 +322,8 @@ static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
break; break;
} }
iommu_tce_kill_rm(tbl, io_entry, subpages);
return ret; return ret;
} }
...@@ -379,6 +387,8 @@ static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, ...@@ -379,6 +387,8 @@ static long kvmppc_rm_tce_iommu_map(struct kvm *kvm,
break; break;
} }
iommu_tce_kill_rm(tbl, io_entry, subpages);
return ret; return ret;
} }
...@@ -420,10 +430,8 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, ...@@ -420,10 +430,8 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
stit->tbl, entry, ua, dir); stit->tbl, entry, ua, dir);
iommu_tce_kill_rm(stit->tbl, entry, 1);
if (ret != H_SUCCESS) { if (ret != H_SUCCESS) {
kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry);
return ret; return ret;
} }
} }
...@@ -561,7 +569,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, ...@@ -561,7 +569,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
ua = 0; ua = 0;
if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) { if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) {
ret = H_PARAMETER; ret = H_PARAMETER;
goto invalidate_exit; goto unlock_exit;
} }
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
...@@ -570,19 +578,15 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, ...@@ -570,19 +578,15 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
iommu_tce_direction(tce)); iommu_tce_direction(tce));
if (ret != H_SUCCESS) { if (ret != H_SUCCESS) {
kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl,
entry); entry + i);
goto invalidate_exit; goto unlock_exit;
} }
} }
kvmppc_rm_tce_put(stt, entry + i, tce); kvmppc_rm_tce_put(stt, entry + i, tce);
} }
invalidate_exit:
list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
iommu_tce_kill_rm(stit->tbl, entry, npages);
unlock_exit: unlock_exit:
if (!prereg) if (!prereg)
arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock); arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock);
...@@ -620,20 +624,16 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu, ...@@ -620,20 +624,16 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
continue; continue;
if (ret == H_TOO_HARD) if (ret == H_TOO_HARD)
goto invalidate_exit; return ret;
WARN_ON_ONCE_RM(1); WARN_ON_ONCE_RM(1);
kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i);
} }
} }
for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value); kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value);
invalidate_exit:
list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
iommu_tce_kill_rm(stit->tbl, ioba >> stt->page_shift, npages);
return ret; return ret;
} }
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
obj-y += callchain.o callchain_$(BITS).o perf_regs.o obj-y += callchain.o callchain_$(BITS).o perf_regs.o
obj-$(CONFIG_COMPAT) += callchain_32.o obj-$(CONFIG_COMPAT) += callchain_32.o
obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o
obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \ obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o \ power5+-pmu.o power6-pmu.o power7-pmu.o \
isa207-common.o power8-pmu.o power9-pmu.o \ isa207-common.o power8-pmu.o power9-pmu.o \
generic-compat-pmu.o power10-pmu.o generic-compat-pmu.o power10-pmu.o bhrb.o
obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o
......
...@@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK; ...@@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK;
/* Table of alternatives, sorted by column 0 */ /* Table of alternatives, sorted by column 0 */
static const unsigned int power10_event_alternatives[][MAX_ALT] = { static const unsigned int power10_event_alternatives[][MAX_ALT] = {
{ PM_CYC_ALT, PM_CYC },
{ PM_INST_CMPL_ALT, PM_INST_CMPL }, { PM_INST_CMPL_ALT, PM_INST_CMPL },
{ PM_CYC_ALT, PM_CYC },
}; };
static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[]) static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[])
......
...@@ -133,11 +133,11 @@ int p9_dd22_bl_ev[] = { ...@@ -133,11 +133,11 @@ int p9_dd22_bl_ev[] = {
/* Table of alternatives, sorted by column 0 */ /* Table of alternatives, sorted by column 0 */
static const unsigned int power9_event_alternatives[][MAX_ALT] = { static const unsigned int power9_event_alternatives[][MAX_ALT] = {
{ PM_INST_DISP, PM_INST_DISP_ALT },
{ PM_RUN_CYC_ALT, PM_RUN_CYC },
{ PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
{ PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
{ PM_BR_2PATH, PM_BR_2PATH_ALT }, { PM_BR_2PATH, PM_BR_2PATH_ALT },
{ PM_INST_DISP, PM_INST_DISP_ALT },
{ PM_RUN_CYC_ALT, PM_RUN_CYC },
{ PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
{ PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
}; };
static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[]) static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[])
......
...@@ -462,7 +462,6 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu ...@@ -462,7 +462,6 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu
{ {
struct papr_scm_perf_stat *stat; struct papr_scm_perf_stat *stat;
struct papr_scm_perf_stats *stats; struct papr_scm_perf_stats *stats;
char *statid;
int index, rc, count; int index, rc, count;
u32 available_events; u32 available_events;
...@@ -493,14 +492,12 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu ...@@ -493,14 +492,12 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu
for (index = 0, stat = stats->scm_statistic, count = 0; for (index = 0, stat = stats->scm_statistic, count = 0;
index < available_events; index++, ++stat) { index < available_events; index++, ++stat) {
statid = kzalloc(strlen(stat->stat_id) + 1, GFP_KERNEL); p->nvdimm_events_map[count] = kmemdup_nul(stat->stat_id, 8, GFP_KERNEL);
if (!statid) { if (!p->nvdimm_events_map[count]) {
rc = -ENOMEM; rc = -ENOMEM;
goto out_nvdimm_events_map; goto out_nvdimm_events_map;
} }
strcpy(statid, stat->stat_id);
p->nvdimm_events_map[count] = statid;
count++; count++;
} }
p->nvdimm_events_map[count] = NULL; p->nvdimm_events_map[count] = NULL;
......
...@@ -27,22 +27,31 @@ struct vas_caps_entry { ...@@ -27,22 +27,31 @@ struct vas_caps_entry {
/* /*
* This function is used to get the notification from the drmgr when * This function is used to get the notification from the drmgr when
* QoS credits are changed. Though receiving the target total QoS * QoS credits are changed.
* credits here, get the official QoS capabilities from the hypervisor.
*/ */
static ssize_t update_total_credits_trigger(struct vas_cop_feat_caps *caps, static ssize_t update_total_credits_store(struct vas_cop_feat_caps *caps,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int err; int err;
u16 creds; u16 creds;
err = kstrtou16(buf, 0, &creds); err = kstrtou16(buf, 0, &creds);
/*
* The user space interface from the management console
* notifies OS with the new QoS credits and then the
* hypervisor. So OS has to use this new credits value
* and reconfigure VAS windows (close or reopen depends
* on the credits available) instead of depending on VAS
* QoS capabilities from the hypervisor.
*/
if (!err) if (!err)
err = vas_reconfig_capabilties(caps->win_type); err = vas_reconfig_capabilties(caps->win_type, creds);
if (err) if (err)
return -EINVAL; return -EINVAL;
pr_info("Set QoS total credits %u\n", creds);
return count; return count;
} }
...@@ -92,7 +101,7 @@ VAS_ATTR_RO(nr_total_credits); ...@@ -92,7 +101,7 @@ VAS_ATTR_RO(nr_total_credits);
VAS_ATTR_RO(nr_used_credits); VAS_ATTR_RO(nr_used_credits);
static struct vas_sysfs_entry update_total_credits_attribute = static struct vas_sysfs_entry update_total_credits_attribute =
__ATTR(update_total_credits, 0200, NULL, update_total_credits_trigger); __ATTR(update_total_credits, 0200, NULL, update_total_credits_store);
static struct attribute *vas_def_capab_attrs[] = { static struct attribute *vas_def_capab_attrs[] = {
&nr_total_credits_attribute.attr, &nr_total_credits_attribute.attr,
......
...@@ -779,10 +779,10 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, ...@@ -779,10 +779,10 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
* changes. Reconfig window configurations based on the credits * changes. Reconfig window configurations based on the credits
* availability from this new capabilities. * availability from this new capabilities.
*/ */
int vas_reconfig_capabilties(u8 type) int vas_reconfig_capabilties(u8 type, int new_nr_creds)
{ {
struct vas_cop_feat_caps *caps; struct vas_cop_feat_caps *caps;
int old_nr_creds, new_nr_creds; int old_nr_creds;
struct vas_caps *vcaps; struct vas_caps *vcaps;
int rc = 0, nr_active_wins; int rc = 0, nr_active_wins;
...@@ -795,12 +795,6 @@ int vas_reconfig_capabilties(u8 type) ...@@ -795,12 +795,6 @@ int vas_reconfig_capabilties(u8 type)
caps = &vcaps->caps; caps = &vcaps->caps;
mutex_lock(&vas_pseries_mutex); mutex_lock(&vas_pseries_mutex);
rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, vcaps->feat,
(u64)virt_to_phys(&hv_cop_caps));
if (rc)
goto out;
new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds);
old_nr_creds = atomic_read(&caps->nr_total_credits); old_nr_creds = atomic_read(&caps->nr_total_credits);
...@@ -832,7 +826,6 @@ int vas_reconfig_capabilties(u8 type) ...@@ -832,7 +826,6 @@ int vas_reconfig_capabilties(u8 type)
false); false);
} }
out:
mutex_unlock(&vas_pseries_mutex); mutex_unlock(&vas_pseries_mutex);
return rc; return rc;
} }
...@@ -850,7 +843,7 @@ static int pseries_vas_notifier(struct notifier_block *nb, ...@@ -850,7 +843,7 @@ static int pseries_vas_notifier(struct notifier_block *nb,
struct of_reconfig_data *rd = data; struct of_reconfig_data *rd = data;
struct device_node *dn = rd->dn; struct device_node *dn = rd->dn;
const __be32 *intserv = NULL; const __be32 *intserv = NULL;
int len, rc = 0; int new_nr_creds, len, rc = 0;
if ((action == OF_RECONFIG_ATTACH_NODE) || if ((action == OF_RECONFIG_ATTACH_NODE) ||
(action == OF_RECONFIG_DETACH_NODE)) (action == OF_RECONFIG_DETACH_NODE))
...@@ -862,7 +855,15 @@ static int pseries_vas_notifier(struct notifier_block *nb, ...@@ -862,7 +855,15 @@ static int pseries_vas_notifier(struct notifier_block *nb,
if (!intserv) if (!intserv)
return NOTIFY_OK; return NOTIFY_OK;
rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE); rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat,
(u64)virt_to_phys(&hv_cop_caps));
if (!rc) {
new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds);
rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE,
new_nr_creds);
}
if (rc) if (rc)
pr_err("Failed reconfig VAS capabilities with DLPAR\n"); pr_err("Failed reconfig VAS capabilities with DLPAR\n");
......
...@@ -135,7 +135,7 @@ struct pseries_vas_window { ...@@ -135,7 +135,7 @@ struct pseries_vas_window {
}; };
int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps); int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);
int vas_reconfig_capabilties(u8 type); int vas_reconfig_capabilties(u8 type, int new_nr_creds);
int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps); int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps);
#ifdef CONFIG_PPC_VAS #ifdef CONFIG_PPC_VAS
......
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