Make mailbox clearing idempotent.

Change-Id: Ib07df13119eee7b4d916688bdb68a0760aedccaa
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 73c7e66..d263d58 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -145,7 +145,7 @@
  * Clears the caller's mailbox so a new message can be received.
  *
  * Returns:
- *  - -1 on failure, if the mailbox hasn't been read or is already empty.
+ *  - -1 on failure, if the mailbox hasn't been read.
  *  - 0 on success if no further action is needed.
  *  - 1 if it was called by the primary VM and the primary VM now needs to wake
  *    up or kick waiters. Waiters should be retrieved by calling
diff --git a/src/api.c b/src/api.c
index 5e7a033..ba89203 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1028,7 +1028,7 @@
  * overwrite the old and will arrive asynchronously.
  *
  * Returns:
- *  - -1 on failure, if the mailbox hasn't been read or is already empty.
+ *  - -1 on failure, if the mailbox hasn't been read.
  *  - 0 on success if no further action is needed.
  *  - 1 if it was called by the primary VM and the primary VM now needs to wake
  *    up or kick waiters. Waiters should be retrieved by calling
@@ -1041,11 +1041,19 @@
 	int64_t ret;
 
 	vm_lock(vm, &locked);
-	if (vm->mailbox.state == mailbox_state_read) {
+	switch (vm->mailbox.state) {
+	case mailbox_state_empty:
+		ret = 0;
+		break;
+
+	case mailbox_state_received:
+		ret = -1;
+		break;
+
+	case mailbox_state_read:
 		ret = api_waiter_result(locked, current, next);
 		vm->mailbox.state = mailbox_state_empty;
-	} else {
-		ret = -1;
+		break;
 	}
 	vm_unlock(&locked);
 
diff --git a/test/vmapi/primary_with_secondaries/interrupts.c b/test/vmapi/primary_with_secondaries/interrupts.c
index c18c8c9..ad61833 100644
--- a/test/vmapi/primary_with_secondaries/interrupts.c
+++ b/test/vmapi/primary_with_secondaries/interrupts.c
@@ -181,7 +181,6 @@
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_C);
 	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
-	EXPECT_EQ(hf_mailbox_clear(), -1);
 
 	/*
 	 * Now send a message to the secondary to enable the interrupt ID, and
diff --git a/test/vmapi/primary_with_secondaries/mailbox.c b/test/vmapi/primary_with_secondaries/mailbox.c
index c54cdb4..bd5b588 100644
--- a/test/vmapi/primary_with_secondaries/mailbox.c
+++ b/test/vmapi/primary_with_secondaries/mailbox.c
@@ -61,6 +61,16 @@
 }
 
 /**
+ * Clearing an empty mailbox is a noop.
+ */
+TEST(mailbox, clear_empty)
+{
+	EXPECT_EQ(hf_mailbox_clear(), 0);
+	EXPECT_EQ(hf_mailbox_clear(), 0);
+	EXPECT_EQ(hf_mailbox_clear(), 0);
+}
+
+/**
  * Send and receive the same message from the echo VM.
  */
 TEST(mailbox, echo)