Since we would be introducing a new user of the DTL buffer in a subsequent patch, add helpers to gatekeep use of the DTL buffer. The current usage of the DTL buffer from debugfs is at a per-cpu level (corresponding to the cpu debugfs file that is opened). Subsequently, we will have users enabling/accessing DTLB for all online cpus. These helpers allow any number of per-cpu users, or a single global user exclusively.
Signed-off-by: Naveen N. Rao <naveen.n....@linux.vnet.ibm.com> --- arch/powerpc/include/asm/plpar_wrappers.h | 2 ++ arch/powerpc/platforms/pseries/dtl.c | 10 ++++++- arch/powerpc/platforms/pseries/lpar.c | 36 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h index d08feb1bc2bd..ab7dd454b6eb 100644 --- a/arch/powerpc/include/asm/plpar_wrappers.h +++ b/arch/powerpc/include/asm/plpar_wrappers.h @@ -88,6 +88,8 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa) return vpa_call(H_VPA_REG_DTL, cpu, vpa); } +extern bool register_dtl_buffer_access(bool global); +extern void unregister_dtl_buffer_access(bool global); extern void register_dtl_buffer(int cpu); extern void alloc_dtl_buffers(void); extern void vpa_init(int cpu); diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index fb05804adb2f..dd28296c9903 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c @@ -193,11 +193,15 @@ static int dtl_enable(struct dtl *dtl) if (dtl->buf) return -EBUSY; + if (register_dtl_buffer_access(false)) + return -EBUSY; + n_entries = dtl_buf_entries; buf = kmem_cache_alloc_node(dtl_cache, GFP_KERNEL, cpu_to_node(dtl->cpu)); if (!buf) { printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", __func__, dtl->cpu); + unregister_dtl_buffer_access(false); return -ENOMEM; } @@ -214,8 +218,11 @@ static int dtl_enable(struct dtl *dtl) } spin_unlock(&dtl->lock); - if (rc) + if (rc) { + unregister_dtl_buffer_access(false); kmem_cache_free(dtl_cache, buf); + } + return rc; } @@ -227,6 +234,7 @@ static void dtl_disable(struct dtl *dtl) dtl->buf = NULL; dtl->buf_entries = 0; spin_unlock(&dtl->lock); + unregister_dtl_buffer_access(false); } /* file interface */ diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 3375ca8cefb5..6af5a2a11deb 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -65,6 +65,42 @@ EXPORT_SYMBOL(plpar_hcall); EXPORT_SYMBOL(plpar_hcall9); EXPORT_SYMBOL(plpar_hcall_norets); +static DEFINE_SPINLOCK(dtl_buffer_refctr_lock); +static unsigned int dtl_buffer_global_refctr, dtl_buffer_percpu_refctr; + +bool register_dtl_buffer_access(bool global) +{ + int rc = 0; + + spin_lock(&dtl_buffer_refctr_lock); + + if ((global && (dtl_buffer_global_refctr || dtl_buffer_percpu_refctr)) + || (!global && dtl_buffer_global_refctr)) { + rc = -1; + } else { + if (global) + dtl_buffer_global_refctr++; + else + dtl_buffer_percpu_refctr++; + } + + spin_unlock(&dtl_buffer_refctr_lock); + + return rc; +} + +void unregister_dtl_buffer_access(bool global) +{ + spin_lock(&dtl_buffer_refctr_lock); + + if (global) + dtl_buffer_global_refctr--; + else + dtl_buffer_percpu_refctr--; + + spin_unlock(&dtl_buffer_refctr_lock); +} + void alloc_dtl_buffers(void) { int cpu; -- 2.21.0