Commit bd801a07 authored by David Kershner's avatar David Kershner Committed by Greg Kroah-Hartman

staging: unisys: visorbus: Have unisys_vmcall return Linux error instead of VMCALL error

The function unisys_vmcall was returning VMCALL specific errors and the
calling code was ignoring which error was actually returned. Instead we
should be mapping the VMCALL error into a proper Linux error and then
returning that, since we now have an error we know what to do with, we
don't have to drop it but we can send it up the stack.
Signed-off-by: default avatarDavid Kershner <david.kershner@unisys.com>
Reviewed-by: default avatarReviewed-by: Tim Sell <timothy.sell@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 88845f40
...@@ -1371,22 +1371,37 @@ static int unisys_vmcall(unsigned long tuple, unsigned long param) ...@@ -1371,22 +1371,37 @@ static int unisys_vmcall(unsigned long tuple, unsigned long param)
__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
"a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); "a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
return result; if (result)
goto error;
return 0;
error: /* Need to convert from VMCALL error codes to Linux */
switch (result) {
case VMCALL_RESULT_INVALID_PARAM:
return -EINVAL;
case VMCALL_RESULT_DATA_UNAVAILABLE:
return -ENODEV;
default:
return -EFAULT;
}
} }
static unsigned int static unsigned int
issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
{ {
struct vmcall_io_controlvm_addr_params params; struct vmcall_io_controlvm_addr_params params;
int result = VMCALL_SUCCESS; int err;
u64 physaddr; u64 physaddr;
physaddr = virt_to_phys(&params); physaddr = virt_to_phys(&params);
result = unisys_vmcall(VMCALL_CONTROLVM_ADDR, physaddr); err = unisys_vmcall(VMCALL_CONTROLVM_ADDR, physaddr);
if (VMCALL_SUCCESSFUL(result)) { if (err)
*control_addr = params.address; return err;
*control_bytes = params.channel_bytes;
} *control_addr = params.address;
return result; *control_bytes = params.channel_bytes;
return 0;
} }
static u64 controlvm_get_channel_address(void) static u64 controlvm_get_channel_address(void)
...@@ -1394,7 +1409,7 @@ static u64 controlvm_get_channel_address(void) ...@@ -1394,7 +1409,7 @@ static u64 controlvm_get_channel_address(void)
u64 addr = 0; u64 addr = 0;
u32 size = 0; u32 size = 0;
if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size))) if (issue_vmcall_io_controlvm_addr(&addr, &size))
return 0; return 0;
return addr; return addr;
......
...@@ -62,8 +62,14 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ ...@@ -62,8 +62,14 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */
VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02 VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02
}; };
#define VMCALL_SUCCESS 0 enum vmcall_result {
#define VMCALL_SUCCESSFUL(result) (result == 0) VMCALL_RESULT_SUCCESS = 0,
VMCALL_RESULT_INVALID_PARAM = 1,
VMCALL_RESULT_DATA_UNAVAILABLE = 2,
VMCALL_RESULT_FAILURE_UNAVAILABLE = 3,
VMCALL_RESULT_DEVICE_ERROR = 4,
VMCALL_RESULT_DEVICE_NOT_READY = 5
};
#define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \ #define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \
__unisys_extended_vmcall_gnuc(tuple, reg_ebx, reg_ecx, reg_edx) __unisys_extended_vmcall_gnuc(tuple, reg_ebx, reg_ecx, reg_edx)
......
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