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

staging: unisys: visorbus: add error handling to handle_command

Add error handling to the function handle_command.

Since handle_command now returns errors, we need to process them correctly
in process_controlvm_event.

Note: It is invalid to have a controlvm test message in the event queue, so
return -EINVAL if one is discovered.
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 114d5dcf
...@@ -1557,16 +1557,14 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) ...@@ -1557,16 +1557,14 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
* @channel_addr: address of the controlvm channel * @channel_addr: address of the controlvm channel
* *
* Return: * Return:
* false - this function will return false only in the case where the * 0 - Successfully processed the message
* controlvm message was NOT processed, but processing must be * -EAGAIN - ControlVM message was not processed and should be retried
* retried before reading the next controlvm message; a * reading the next controlvm message; a scenario where this can
* scenario where this can occur is when we need to throttle * occur is when we need to throttle the allocation of memory in
* the allocation of memory in which to copy out controlvm * which to copy out controlvm payload data.
* payload data * < 0 - error: ControlVM message was processed but an error occurred.
* true - processing of the controlvm message completed,
* either successfully or with an error
*/ */
static bool static int
handle_command(struct controlvm_message inmsg, u64 channel_addr) handle_command(struct controlvm_message inmsg, u64 channel_addr)
{ {
struct controlvm_message_packet *cmd = &inmsg.cmd; struct controlvm_message_packet *cmd = &inmsg.cmd;
...@@ -1575,11 +1573,13 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) ...@@ -1575,11 +1573,13 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
struct parser_context *parser_ctx = NULL; struct parser_context *parser_ctx = NULL;
bool local_addr; bool local_addr;
struct controlvm_message ackmsg; struct controlvm_message ackmsg;
int err = 0;
/* create parsing context if necessary */ /* create parsing context if necessary */
local_addr = (inmsg.hdr.flags.test_message == 1); local_addr = (inmsg.hdr.flags.test_message == 1);
if (channel_addr == 0) if (channel_addr == 0)
return true; return -EINVAL;
parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
parm_bytes = inmsg.hdr.payload_bytes; parm_bytes = inmsg.hdr.payload_bytes;
...@@ -1595,66 +1595,68 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) ...@@ -1595,66 +1595,68 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
parser_init_byte_stream(parm_addr, parm_bytes, parser_init_byte_stream(parm_addr, parm_bytes,
local_addr, &retry); local_addr, &retry);
if (!parser_ctx && retry) if (!parser_ctx && retry)
return false; return -EAGAIN;
} }
if (!local_addr) { if (!local_addr) {
controlvm_init_response(&ackmsg, &inmsg.hdr, controlvm_init_response(&ackmsg, &inmsg.hdr,
CONTROLVM_RESP_SUCCESS); CONTROLVM_RESP_SUCCESS);
if (chipset_dev->controlvm_channel) err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
visorchannel_signalinsert( CONTROLVM_QUEUE_ACK,
chipset_dev->controlvm_channel, &ackmsg);
CONTROLVM_QUEUE_ACK, &ackmsg); if (err)
return err;
} }
switch (inmsg.hdr.id) { switch (inmsg.hdr.id) {
case CONTROLVM_CHIPSET_INIT: case CONTROLVM_CHIPSET_INIT:
chipset_init(&inmsg); err = chipset_init(&inmsg);
break; break;
case CONTROLVM_BUS_CREATE: case CONTROLVM_BUS_CREATE:
bus_create(&inmsg); err = bus_create(&inmsg);
break; break;
case CONTROLVM_BUS_DESTROY: case CONTROLVM_BUS_DESTROY:
bus_destroy(&inmsg); err = bus_destroy(&inmsg);
break; break;
case CONTROLVM_BUS_CONFIGURE: case CONTROLVM_BUS_CONFIGURE:
bus_configure(&inmsg, parser_ctx); err = bus_configure(&inmsg, parser_ctx);
break; break;
case CONTROLVM_DEVICE_CREATE: case CONTROLVM_DEVICE_CREATE:
my_device_create(&inmsg); err = my_device_create(&inmsg);
break; break;
case CONTROLVM_DEVICE_CHANGESTATE: case CONTROLVM_DEVICE_CHANGESTATE:
if (cmd->device_change_state.flags.phys_device) { if (cmd->device_change_state.flags.phys_device) {
parahotplug_process_message(&inmsg); err = parahotplug_process_message(&inmsg);
} else { } else {
/* /*
* save the hdr and cmd structures for later use * save the hdr and cmd structures for later use
* when sending back the response to Command * when sending back the response to Command
*/ */
my_device_changestate(&inmsg); err = my_device_changestate(&inmsg);
break; break;
} }
break; break;
case CONTROLVM_DEVICE_DESTROY: case CONTROLVM_DEVICE_DESTROY:
my_device_destroy(&inmsg); err = my_device_destroy(&inmsg);
break; break;
case CONTROLVM_DEVICE_CONFIGURE: case CONTROLVM_DEVICE_CONFIGURE:
/* no op for now, just send a respond that we passed */ /* no op just send a respond that we passed */
if (inmsg.hdr.flags.response_expected) if (inmsg.hdr.flags.response_expected)
controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
break; break;
case CONTROLVM_CHIPSET_READY: case CONTROLVM_CHIPSET_READY:
chipset_ready_uevent(&inmsg.hdr); err = chipset_ready_uevent(&inmsg.hdr);
break; break;
case CONTROLVM_CHIPSET_SELFTEST: case CONTROLVM_CHIPSET_SELFTEST:
chipset_selftest_uevent(&inmsg.hdr); err = chipset_selftest_uevent(&inmsg.hdr);
break; break;
case CONTROLVM_CHIPSET_STOP: case CONTROLVM_CHIPSET_STOP:
chipset_notready_uevent(&inmsg.hdr); err = chipset_notready_uevent(&inmsg.hdr);
break; break;
default: default:
err = -ENOMSG;
if (inmsg.hdr.flags.response_expected) if (inmsg.hdr.flags.response_expected)
controlvm_respond controlvm_respond(&inmsg.hdr,
(&inmsg.hdr, -CONTROLVM_RESP_ID_UNKNOWN); -CONTROLVM_RESP_ID_UNKNOWN);
break; break;
} }
...@@ -1662,7 +1664,7 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) ...@@ -1662,7 +1664,7 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
parser_done(parser_ctx); parser_done(parser_ctx);
parser_ctx = NULL; parser_ctx = NULL;
} }
return true; return err;
} }
/* /*
...@@ -1671,19 +1673,23 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) ...@@ -1671,19 +1673,23 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
* channel * channel
* @msg: pointer to the retrieved message * @msg: pointer to the retrieved message
* *
* Return: true if a valid message was retrieved or false otherwise * Return: 0 if valid message was retrieved or -error
*/ */
static bool static int
read_controlvm_event(struct controlvm_message *msg) read_controlvm_event(struct controlvm_message *msg)
{ {
if (!visorchannel_signalremove(chipset_dev->controlvm_channel, int err;
CONTROLVM_QUEUE_EVENT, msg)) {
err = visorchannel_signalremove(chipset_dev->controlvm_channel,
CONTROLVM_QUEUE_EVENT, msg);
if (err)
return err;
/* got a message */ /* got a message */
if (msg->hdr.flags.test_message == 1) if (msg->hdr.flags.test_message == 1)
return false; return -EINVAL;
return true;
} return 0;
return false;
} }
/* /*
...@@ -1739,7 +1745,7 @@ controlvm_periodic_work(struct work_struct *work) ...@@ -1739,7 +1745,7 @@ controlvm_periodic_work(struct work_struct *work)
chipset_dev->controlvm_pending_msg_valid = false; chipset_dev->controlvm_pending_msg_valid = false;
got_command = true; got_command = true;
} else { } else {
got_command = read_controlvm_event(&inmsg); got_command = (read_controlvm_event(&inmsg) == 0);
} }
} }
...@@ -1748,8 +1754,8 @@ controlvm_periodic_work(struct work_struct *work) ...@@ -1748,8 +1754,8 @@ controlvm_periodic_work(struct work_struct *work)
chipset_dev->most_recent_message_jiffies = jiffies; chipset_dev->most_recent_message_jiffies = jiffies;
if (handle_command(inmsg, if (handle_command(inmsg,
visorchannel_get_physaddr visorchannel_get_physaddr
(chipset_dev->controlvm_channel))) (chipset_dev->controlvm_channel) != -EAGAIN))
got_command = read_controlvm_event(&inmsg); got_command = (read_controlvm_event(&inmsg) == 0);
else { else {
/* /*
* this is a scenario where throttling * this is a scenario where throttling
......
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