| From ce0c12b633846a47e103842149a5bac2e5d261ec Mon Sep 17 00:00:00 2001 |
| From: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Date: Tue, 1 Mar 2016 12:58:06 +0100 |
| Subject: s390/dasd: fix diag 0x250 inline assembly |
| |
| From: Heiko Carstens <heiko.carstens@de.ibm.com> |
| |
| commit ce0c12b633846a47e103842149a5bac2e5d261ec upstream. |
| |
| git commit 1ec2772e0c3c ("s390/diag: add a statistic for diagnose |
| calls") added function calls to gather diagnose statistics. |
| |
| In case of the dasd diag driver the function call was added between a |
| register asm statement which initialized register r2 and the inline |
| assembly itself. The function call clobbers the contents of register |
| r2 and therefore the diag 0x250 call behaves in a more or less random |
| way. |
| |
| Fix this by extracting the function call into a separate function like |
| we do everywhere else. |
| |
| Fixes: 1ec2772e0c3c ("s390/diag: add a statistic for diagnose calls") |
| Reported-and-tested-by: Stefan Haberland <sth@linux.vnet.ibm.com> |
| Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/s390/block/dasd_diag.c | 9 +++++++-- |
| 1 file changed, 7 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/s390/block/dasd_diag.c |
| +++ b/drivers/s390/block/dasd_diag.c |
| @@ -67,7 +67,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc |
| * and function code cmd. |
| * In case of an exception return 3. Otherwise return result of bitwise OR of |
| * resulting condition code and DIAG return code. */ |
| -static inline int dia250(void *iob, int cmd) |
| +static inline int __dia250(void *iob, int cmd) |
| { |
| register unsigned long reg2 asm ("2") = (unsigned long) iob; |
| typedef union { |
| @@ -77,7 +77,6 @@ static inline int dia250(void *iob, int |
| int rc; |
| |
| rc = 3; |
| - diag_stat_inc(DIAG_STAT_X250); |
| asm volatile( |
| " diag 2,%2,0x250\n" |
| "0: ipm %0\n" |
| @@ -91,6 +90,12 @@ static inline int dia250(void *iob, int |
| return rc; |
| } |
| |
| +static inline int dia250(void *iob, int cmd) |
| +{ |
| + diag_stat_inc(DIAG_STAT_X250); |
| + return __dia250(iob, cmd); |
| +} |
| + |
| /* Initialize block I/O to DIAG device using the specified blocksize and |
| * block offset. On success, return zero and set end_block to contain the |
| * number of blocks on the device minus the specified offset. Return non-zero |