1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2527dcdccSDavid Howells #ifndef __PARISC_LDCW_H 3527dcdccSDavid Howells #define __PARISC_LDCW_H 4527dcdccSDavid Howells 5527dcdccSDavid Howells #ifndef CONFIG_PA20 6527dcdccSDavid Howells /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, 7527dcdccSDavid Howells and GCC only guarantees 8-byte alignment for stack locals, we can't 8527dcdccSDavid Howells be assured of 16-byte alignment for atomic lock data even if we 9527dcdccSDavid Howells specify "__attribute ((aligned(16)))" in the type declaration. So, 10527dcdccSDavid Howells we use a struct containing an array of four ints for the atomic lock 11527dcdccSDavid Howells type and dynamically select the 16-byte aligned int from the array 12527dcdccSDavid Howells for the semaphore. */ 13527dcdccSDavid Howells 14527dcdccSDavid Howells #define __PA_LDCW_ALIGNMENT 16 15527dcdccSDavid Howells #define __ldcw_align(a) ({ \ 16527dcdccSDavid Howells unsigned long __ret = (unsigned long) &(a)->lock[0]; \ 17527dcdccSDavid Howells __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \ 18527dcdccSDavid Howells & ~(__PA_LDCW_ALIGNMENT - 1); \ 19527dcdccSDavid Howells (volatile unsigned int *) __ret; \ 20527dcdccSDavid Howells }) 21527dcdccSDavid Howells #define __LDCW "ldcw" 22527dcdccSDavid Howells 23527dcdccSDavid Howells #else /*CONFIG_PA20*/ 24527dcdccSDavid Howells /* From: "Jim Hull" <jim.hull of hp.com> 25527dcdccSDavid Howells I've attached a summary of the change, but basically, for PA 2.0, as 26527dcdccSDavid Howells long as the ",CO" (coherent operation) completer is specified, then the 27527dcdccSDavid Howells 16-byte alignment requirement for ldcw and ldcd is relaxed, and instead 28527dcdccSDavid Howells they only require "natural" alignment (4-byte for ldcw, 8-byte for 29527dcdccSDavid Howells ldcd). */ 30527dcdccSDavid Howells 31527dcdccSDavid Howells #define __PA_LDCW_ALIGNMENT 4 32527dcdccSDavid Howells #define __ldcw_align(a) (&(a)->slock) 33527dcdccSDavid Howells #define __LDCW "ldcw,co" 34527dcdccSDavid Howells 35527dcdccSDavid Howells #endif /*!CONFIG_PA20*/ 36527dcdccSDavid Howells 3745db0738SJohn David Anglin /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. 3845db0738SJohn David Anglin We don't explicitly expose that "*a" may be written as reload 3945db0738SJohn David Anglin fails to find a register in class R1_REGS when "a" needs to be 4045db0738SJohn David Anglin reloaded when generating 64-bit PIC code. Instead, we clobber 4145db0738SJohn David Anglin memory to indicate to the compiler that the assembly code reads 4245db0738SJohn David Anglin or writes to items other than those listed in the input and output 4345db0738SJohn David Anglin operands. This may pessimize the code somewhat but __ldcw is 44d14b3dfcSAndrea Gelmini usually used within code blocks surrounded by memory barriers. */ 45527dcdccSDavid Howells #define __ldcw(a) ({ \ 46527dcdccSDavid Howells unsigned __ret; \ 4745db0738SJohn David Anglin __asm__ __volatile__(__LDCW " 0(%1),%0" \ 4845db0738SJohn David Anglin : "=r" (__ret) : "r" (a) : "memory"); \ 49527dcdccSDavid Howells __ret; \ 50527dcdccSDavid Howells }) 51527dcdccSDavid Howells 52527dcdccSDavid Howells #ifdef CONFIG_SMP 53527dcdccSDavid Howells # define __lock_aligned __attribute__((__section__(".data..lock_aligned"))) 54527dcdccSDavid Howells #endif 55527dcdccSDavid Howells 56527dcdccSDavid Howells #endif /* __PARISC_LDCW_H */ 57