protocol: Add close

Change-Id: I222a8f60edba0a5f5f2c938a6e2d78e2e0441a23
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/protocol.c b/protocol.c
index 6622cd4..b112231 100644
--- a/protocol.c
+++ b/protocol.c
@@ -248,14 +248,41 @@
 	 * command not when we call flush because we've implicitly closed a
 	 * window because we might not have the required args in req.
 	 */
-	rc = protocol_v1_mark_dirty(context, (struct protocol_mark_dirty *)io);
-	if (rc < 0) {
-		return rc;
+	if (io) {
+		struct protocol_mark_dirty *mdio = (void *)io;
+		rc = protocol_v1_mark_dirty(context, mdio);
+		if (rc < 0) {
+			return rc;
+		}
 	}
 
 	return generic_flush(context);
 }
 
+int protocol_v1_close(struct mbox_context *context, struct protocol_close *io)
+{
+	int rc;
+
+	/* Close the current window if there is one */
+	if (!context->current) {
+		return 0;
+	}
+
+	/* There is an implicit flush if it was a write window */
+	if (context->current_is_write) {
+		rc = protocol_v1_flush(context, NULL);
+		if (rc < 0) {
+			MSG_ERR("Couldn't Flush Write Window\n");
+			return rc;
+		}
+	}
+
+	/* Host asked for it -> Don't set the BMC Event */
+	windows_close_current(context, NO_BMC_EVENT, io->req.flags);
+
+	return 0;
+}
+
 /*
  * get_suggested_timeout() - get the suggested timeout value in seconds
  * @context:	The mbox context pointer
@@ -391,6 +418,30 @@
 	return generic_flush(context);
 }
 
+int protocol_v2_close(struct mbox_context *context, struct protocol_close *io)
+{
+	int rc;
+
+	/* Close the current window if there is one */
+	if (!context->current) {
+		return 0;
+	}
+
+	/* There is an implicit flush if it was a write window */
+	if (context->current_is_write) {
+		rc = protocol_v2_flush(context, NULL);
+		if (rc < 0) {
+			MSG_ERR("Couldn't Flush Write Window\n");
+			return rc;
+		}
+	}
+
+	/* Host asked for it -> Don't set the BMC Event */
+	windows_close_current(context, NO_BMC_EVENT, io->req.flags);
+
+	return 0;
+}
+
 static const struct protocol_ops protocol_ops_v1 = {
 	.reset = protocol_v1_reset,
 	.get_info = protocol_v1_get_info,
@@ -399,6 +450,7 @@
 	.mark_dirty = protocol_v1_mark_dirty,
 	.erase = NULL,
 	.flush = protocol_v1_flush,
+	.close = protocol_v1_close,
 };
 
 static const struct protocol_ops protocol_ops_v2 = {
@@ -409,6 +461,7 @@
 	.mark_dirty = protocol_v2_mark_dirty,
 	.erase = protocol_v2_erase,
 	.flush = protocol_v2_flush,
+	.close = protocol_v2_close,
 };
 
 static const struct protocol_ops *protocol_ops_map[] = {
diff --git a/protocol.h b/protocol.h
index c22f94b..c948e80 100644
--- a/protocol.h
+++ b/protocol.h
@@ -87,6 +87,12 @@
 	} req;
 };
 
+struct protocol_close {
+	struct {
+		uint8_t flags;
+	} req;
+};
+
 struct protocol_ops {
 	int (*reset)(struct mbox_context *context);
 	int (*get_info)(struct mbox_context *context,
@@ -99,6 +105,7 @@
 			  struct protocol_mark_dirty *io);
 	int (*erase)(struct mbox_context *context, struct protocol_erase *io);
 	int (*flush)(struct mbox_context *context, struct protocol_flush *io);
+	int (*close)(struct mbox_context *context, struct protocol_close *io);
 };
 
 int protocol_init(struct mbox_context *context);
@@ -117,6 +124,7 @@
 int protocol_v1_mark_dirty(struct mbox_context *context,
 			   struct protocol_mark_dirty *io);
 int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io);
+int protocol_v1_close(struct mbox_context *context, struct protocol_close *io);
 
 /* Protocol v2 */
 int protocol_v2_get_info(struct mbox_context *context,
@@ -130,5 +138,6 @@
 int protocol_v2_erase(struct mbox_context *context,
 		      struct protocol_erase *io);
 int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io);
+int protocol_v2_close(struct mbox_context *context, struct protocol_close *io);
 
 #endif /* PROTOCOL_H */
diff --git a/transport_mbox.c b/transport_mbox.c
index 825fed7..89562e8 100644
--- a/transport_mbox.c
+++ b/transport_mbox.c
@@ -491,29 +491,19 @@
 int mbox_handle_close_window(struct mbox_context *context,
 				    union mbox_regs *req, struct mbox_msg *resp)
 {
-	uint8_t flags = 0;
+	struct protocol_close io = { 0 };
 	int rc;
 
-	/* Close the current window if there is one */
-	if (context->current) {
-		/* There is an implicit flush if it was a write window */
-		if (context->current_is_write) {
-			rc = mbox_handle_flush_window(context, NULL, NULL);
-			if (rc < 0) {
-				MSG_ERR("Couldn't Flush Write Window\n");
-				return rc;
-			}
-		}
-
-		if (context->version >= API_VERSION_2) {
-			flags = req->msg.args[0];
-		}
-
-		/* Host asked for it -> Don't set the BMC Event */
-		windows_close_current(context, NO_BMC_EVENT, flags);
+	if (context->version >= API_VERSION_2) {
+		io.req.flags = req->msg.args[0];
 	}
 
-	return 0;
+	rc = context->protocol->close(context, &io);
+	if (rc < 0) {
+		return mbox_xlate_errno(context, rc);
+	}
+
+	return rc;
 }
 
 /*