Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries: Introduce rwlock to gatekeep DTLB usage

Since we would be introducing a new user of the DTL buffer in a
subsequent patch, we need a way to gatekeep use of the DTL buffer.

The current debugfs interface for DTL allows registering and opening
cpu-specific DTL buffers. Cpu specific files are exposed under
debugfs 'powerpc/dtl/' node, and changing 'dtl_event_mask' in the same
directory enables controlling the event mask used when registering DTL
buffer for a particular cpu.

Subsequently, we will be introducing a user of the DTL buffers that
registers access to the DTL buffers across all cpus with the same event
mask. To ensure these two users do not step on each other, we introduce
a rwlock to gatekeep DTL buffer access. This fits the requirement of the
current debugfs interface wanting to allow multiple independent
cpu-specific users (read lock), and the subsequent user wanting
exclusive access (write lock).

Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Naveen N. Rao and committed by
Michael Ellerman
06220d78 1c85a2a1

+16 -1
+2
arch/powerpc/include/asm/lppaca.h
··· 32 32 */ 33 33 #include <linux/cache.h> 34 34 #include <linux/threads.h> 35 + #include <linux/spinlock_types.h> 35 36 #include <asm/types.h> 36 37 #include <asm/mmu.h> 37 38 #include <asm/firmware.h> ··· 167 166 #define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT) 168 167 169 168 extern struct kmem_cache *dtl_cache; 169 + extern rwlock_t dtl_access_lock; 170 170 171 171 /* 172 172 * When CONFIG_VIRT_CPU_ACCOUNTING_NATIVE = y, the cpu accounting code controls
+10 -1
arch/powerpc/platforms/pseries/dtl.c
··· 193 193 if (dtl->buf) 194 194 return -EBUSY; 195 195 196 + /* ensure there are no other conflicting dtl users */ 197 + if (!read_trylock(&dtl_access_lock)) 198 + return -EBUSY; 199 + 196 200 n_entries = dtl_buf_entries; 197 201 buf = kmem_cache_alloc_node(dtl_cache, GFP_KERNEL, cpu_to_node(dtl->cpu)); 198 202 if (!buf) { 199 203 printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", 200 204 __func__, dtl->cpu); 205 + read_unlock(&dtl_access_lock); 201 206 return -ENOMEM; 202 207 } 203 208 ··· 219 214 } 220 215 spin_unlock(&dtl->lock); 221 216 222 - if (rc) 217 + if (rc) { 218 + read_unlock(&dtl_access_lock); 223 219 kmem_cache_free(dtl_cache, buf); 220 + } 221 + 224 222 return rc; 225 223 } 226 224 ··· 235 227 dtl->buf = NULL; 236 228 dtl->buf_entries = 0; 237 229 spin_unlock(&dtl->lock); 230 + read_unlock(&dtl_access_lock); 238 231 } 239 232 240 233 /* file interface */
+4
arch/powerpc/platforms/pseries/lpar.c
··· 113 113 } 114 114 } 115 115 116 + #ifdef CONFIG_PPC_SPLPAR 117 + DEFINE_RWLOCK(dtl_access_lock); 118 + #endif /* CONFIG_PPC_SPLPAR */ 119 + 116 120 void vpa_init(int cpu) 117 121 { 118 122 int hwcpu = get_hard_smp_processor_id(cpu);