transport: Rework BMC event handling

Change-Id: I99b13eca8f25d9855aac2af0a9ec46dfe5390834
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/protocol.c b/protocol.c
index 82c1ca7..2c97f92 100644
--- a/protocol.c
+++ b/protocol.c
@@ -13,6 +13,15 @@
 
 #define BLOCK_SIZE_SHIFT_V1		12 /* 4K */
 
+static inline uint8_t protocol_get_bmc_event_mask(struct mbox_context *context)
+{
+	if (context->version == API_VERSION_1) {
+		return BMC_EVENT_V1_MASK;
+	}
+
+	return BMC_EVENT_V2_MASK;
+}
+
 /*
  * protocol_events_set() - Set BMC events
  * @context:	The mbox context pointer
@@ -22,16 +31,14 @@
  */
 int protocol_events_set(struct mbox_context *context, uint8_t bmc_event)
 {
-	uint8_t mask = 0x00;
+	const uint8_t mask = protocol_get_bmc_event_mask(context);
 
-	switch (context->version) {
-	case API_VERSION_1:
-		mask = BMC_EVENT_V1_MASK;
-		break;
-	default:
-		mask = BMC_EVENT_V2_MASK;
-		break;
-	}
+	/*
+	 * Store the raw value, as we may up- or down- grade the protocol
+	 * version and subsequently need to flush the appropriate set. Instead
+	 * we pass the masked value through to the transport
+	 */
+	context->bmc_events |= bmc_event;
 
 	return context->transport->set_events(context, (bmc_event & mask));
 }
@@ -45,7 +52,11 @@
  */
 int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event)
 {
-	return context->transport->clear_events(context, bmc_event);
+	const uint8_t mask = protocol_get_bmc_event_mask(context);
+
+	context->bmc_events &= ~bmc_event;
+
+	return context->transport->clear_events(context, (bmc_event & mask));
 }
 
 int protocol_v1_reset(struct mbox_context *context)
diff --git a/transport_dbus.c b/transport_dbus.c
index 14fdc24..c1b78e3 100644
--- a/transport_dbus.c
+++ b/transport_dbus.c
@@ -13,12 +13,12 @@
 #include "protocol.h"
 #include "transport.h"
 
-static int transport_dbus_flush_events(struct mbox_context *context,
-				       uint8_t events)
+static int transport_dbus_property_update(struct mbox_context *context,
+					  uint8_t events)
 {
+	/* Two properties plus a terminating NULL */
 	char *props[3] = { 0 };
 	int i = 0;
-	int rc;
 
 	if (events & BMC_EVENT_FLASH_CTRL_LOST) {
 		props[i++] = "FlashControlLost";
@@ -28,15 +28,27 @@
 		props[i++] = "DaemonReady";
 	}
 
-	rc = sd_bus_emit_properties_changed_strv(context->bus,
+	return sd_bus_emit_properties_changed_strv(context->bus,
 						 MBOX_DBUS_OBJECT,
 						 /* FIXME: Hard-coding v2 */
 						 MBOX_DBUS_PROTOCOL_IFACE_V2,
 						 props);
+}
+
+static int transport_dbus_set_events(struct mbox_context *context,
+				     uint8_t events)
+{
+	int rc;
+
+	rc = transport_dbus_property_update(context, events);
 	if (rc < 0) {
 		return rc;
 	}
 
+	/*
+	 * Handle signals - edge triggered, only necessary when they're
+	 * asserted
+	 */
 	if (events & BMC_EVENT_WINDOW_RESET) {
 		sd_bus_message *m = NULL;
 
@@ -76,20 +88,11 @@
 	return 0;
 }
 
-static int transport_dbus_set_events(struct mbox_context *context,
-				     uint8_t events)
-{
-	context->bmc_events |= events;
-
-	return transport_dbus_flush_events(context, events);
-}
-
 static int transport_dbus_clear_events(struct mbox_context *context,
 				       uint8_t events)
 {
-	context->bmc_events &= ~events;
-
-	return transport_dbus_flush_events(context, events);
+	/* No need to emit signals for ackable events on clear */
+	return transport_dbus_property_update(context, events);
 }
 
 static const struct transport_ops transport_dbus_ops = {
@@ -123,7 +126,8 @@
 
 	/* Switch transport to DBus. This is fine as DBus signals are async */
 	context->transport = &transport_dbus_ops;
-	transport_dbus_flush_events(context, context->bmc_events);
+	/* A bit messy, but we need the correct event mask */
+	protocol_events_set(context, context->bmc_events);
 
 	rc = sd_bus_message_new_method_return(m, &n);
 	if (rc < 0) {
diff --git a/transport_mbox.c b/transport_mbox.c
index 671e1c4..340a526 100644
--- a/transport_mbox.c
+++ b/transport_mbox.c
@@ -591,7 +591,8 @@
 
 	if (context->transport != old_transport &&
 			context->transport == &transport_mbox_ops) {
-		transport_mbox_flush_events(context);
+		/* A bit messy, but we need the correct event mask */
+		protocol_events_set(context, context->bmc_events);
 	}
 
 	return rc;