From: harry <harry@hebutterworth.freeserve.co.uk>
To: xen-devel@lists.xensource.com
Subject: [PATCH][9/17] USB virt 2.6 split driver---gateway
Date: Mon, 21 Nov 2005 13:19:05 +0000 [thread overview]
Message-ID: <1132579145.31295.120.camel@localhost.localdomain> (raw)
[-- Attachment #1: Type: text/plain, Size: 230 bytes --]
This patch implements xenidc_gateway which uses a xenidc_channel to
implement an interdomain service for sending messages and transactions
between domains bi-directionally.
Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>
[-- Attachment #2: p9-gateway.patch --]
[-- Type: text/x-patch, Size: 77091 bytes --]
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile Sun Nov 20 17:45:16 2005
@@ -12,3 +12,6 @@
xenidc-objs += xenidc_vaddress.o
xenidc-objs += xenidc_gnttab_channel.o
xenidc-objs += xenidc_xbgt_channel.o
+xenidc-objs += xenidc_gateway.o
+xenidc-objs += xenidc_gateway_initiator_resource.o
+xenidc-objs += xenidc_gateway_target_resource.o
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway.c
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway.c Sun Nov 20 17:45:16 2005
@@ -0,0 +1,1216 @@
+/*****************************************************************************/
+/* A communication 'gateway' object which allows the client to send messages */
+/* and transactions bi-directionally over a xenidc_channel. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_gateway.h>
+#include <asm-xen/xenidc_vaddress.h>
+#include <linux/vmalloc.h>
+#include "xenidc_gateway_initiator_resource.h"
+#include "xenidc_gateway_target_resource.h"
+#include "xenidc_trace.h"
+
+typedef enum {
+ xenidc_gateway_stimulus_mt, /* Message or transaction queued. */
+ xenidc_gateway_stimulus_cc, /* Channel connect. */
+ xenidc_gateway_stimulus_cm, /* Channel message. */
+ xenidc_gateway_stimulus_cd, /* Channel disconnect. */
+ xenidc_gateway_stimulus_km, /* Kick messages and transactions completed. */
+ xenidc_gateway_stimulus_kc, /* Kick channel messages completed. */
+ xenidc_gateway_stimulus_ic, /* Initiator resource completed. */
+ xenidc_gateway_stimulus_ii, /* Initiator resources idle. */
+ xenidc_gateway_stimulus_tc, /* Target resource completed. */
+ xenidc_gateway_stimulus_ti, /* Target resources idle. */
+ xenidc_gateway_stimulus_lc, /* Client connect completed. */
+ xenidc_gateway_stimulus_lg, /* Client disconnect called. */
+ xenidc_gateway_stimulus_ld, /* Client disconnect completed. */
+} xenidc_gateway_stimulus;
+
+static void xenidc_gateway_handle_stimulus
+ (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus);
+
+static void xenidc_gateway_channel_connect(void *context);
+
+static void xenidc_gateway_handle_channel_message
+ (void *context, xenidc_channel_message * message);
+
+static void xenidc_gateway_channel_disconnect
+ (void *context, xenidc_callback * callback);
+
+static int xenidc_gateway_init_or_exit(xenidc_gateway * gateway, int exit);
+
+int xenidc_gateway_init
+ (xenidc_gateway * gateway,
+ xenidc_channel * channel,
+ void (*connect) (xenidc_gateway * gateway), void (*handle_message)
+ (xenidc_gateway * gateway, xenidc_gateway_message * message),
+ void (*handle_transaction)
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction),
+ void (*disconnect)
+ (xenidc_gateway * gateway, xenidc_callback * callback),
+ u32 initiator_quota,
+ xenidc_buffer_byte_count initiator_maximum_byte_count,
+ u32 target_quota, xenidc_buffer_byte_count target_maximum_byte_count) {
+ trace();
+
+ gateway->channel = channel;
+ gateway->connect = connect;
+ gateway->handle_message = handle_message;
+ gateway->handle_transaction = handle_transaction;
+ gateway->disconnect = disconnect;
+
+ gateway->initiator_quota = initiator_quota;
+ gateway->target_quota = target_quota;
+ gateway->target_maximum_byte_count = target_maximum_byte_count;
+
+ xenidc_channel_install_client
+ (channel,
+ gateway,
+ xenidc_gateway_channel_connect,
+ xenidc_gateway_handle_channel_message,
+ xenidc_gateway_channel_disconnect);
+
+ return xenidc_gateway_init_or_exit(gateway, 0);
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_1(void *data);
+
+static void xenidc_gateway_kick_messages_and_transactions_2
+ (xenidc_callback * callback);
+
+static void xenidc_gateway_kick_channel_messages_1(void *data);
+
+static void xenidc_gateway_kick_channel_messages_2(xenidc_callback * callback);
+
+static void xenidc_gateway_connect_client_1(void *data);
+
+static void xenidc_gateway_disconnect_client_1(void *data);
+
+static void xenidc_gateway_disconnect_client_2(xenidc_callback * callback);
+
+static int xenidc_gateway_init_or_exit(xenidc_gateway * gateway, int exit)
+{
+ trace();
+
+ {
+ int return_value = 0;
+
+ if (exit) {
+ goto EXIT;
+ }
+
+ INIT_LIST_HEAD(&gateway->initiator_resource_list);
+
+ if (gateway->initiator_quota != 0) {
+ gateway->initiator_resources = vmalloc
+ (sizeof(xenidc_gateway_initiator_resource)
+ * gateway->initiator_quota);
+
+ if (gateway->initiator_resources == NULL) {
+ trace0
+ ("failed to allocate initiator resources");
+
+ return_value = -ENOMEM;
+
+ goto EXIT_NO_INITIATOR_RESOURCES;
+ }
+
+ {
+ u32 i;
+
+ for (i = 0; i < gateway->initiator_quota; i++) {
+ xenidc_gateway_initiator_resource
+ *resource =
+ &gateway->initiator_resources[i];
+
+ xenidc_gateway_initiator_resource_init
+ (resource,
+ gateway,
+ xenidc_gateway_kick_messages_and_transactions_2,
+ i);
+
+ list_add_tail
+ (xenidc_gateway_initiator_resource_to_link
+ (resource),
+ &gateway->initiator_resource_list);
+ }
+ }
+ }
+
+ INIT_LIST_HEAD(&gateway->target_resource_list);
+
+ if (gateway->target_quota != 0) {
+ gateway->target_resources = vmalloc
+ ((sizeof(xenidc_gateway_target_resource)
+ * gateway->target_quota)
+ +
+ (gateway->target_maximum_byte_count
+ * gateway->target_quota)
+ );
+
+ if (gateway->target_resources == NULL) {
+ trace0("failed to allocate target resources");
+
+ return_value = -ENOMEM;
+
+ goto EXIT_NO_TARGET_RESOURCES;
+ }
+
+ {
+ xenidc_local_buffer_reference buffer_area =
+ xenidc_vaddress_create_lbr
+ (&gateway->target_resources
+ [gateway->target_quota],
+ gateway->target_maximum_byte_count *
+ gateway->target_quota);
+
+ u32 i;
+
+ for (i = 0; i < gateway->target_quota; i++) {
+ xenidc_gateway_target_resource *resource
+ = &gateway->target_resources[i];
+
+ xenidc_local_buffer_reference buffer =
+ buffer_area;
+
+ xenidc_local_buffer_reference_truncate
+ (&buffer,
+ gateway->
+ target_maximum_byte_count);
+
+ xenidc_gateway_target_resource_init
+ (resource,
+ gateway,
+ xenidc_gateway_kick_channel_messages_2,
+ buffer);
+
+ list_add_tail
+ (xenidc_gateway_target_resource_to_link
+ (resource),
+ &gateway->target_resource_list);
+
+ xenidc_local_buffer_reference_advance
+ (&buffer_area,
+ gateway->
+ target_maximum_byte_count);
+ }
+ }
+ }
+
+ spin_lock_init(&gateway->lock);
+
+ gateway->state = xenidc_gateway_state_i;
+
+ INIT_LIST_HEAD(&gateway->message_and_transaction_list);
+ INIT_LIST_HEAD(&gateway->channel_message_list);
+
+ xenidc_work_init
+ (&gateway->kick_messages_and_transactions_1_work,
+ xenidc_gateway_kick_messages_and_transactions_1, gateway);
+
+ xenidc_work_init
+ (&gateway->kick_channel_messages_1_work,
+ xenidc_gateway_kick_channel_messages_1, gateway);
+
+ xenidc_work_init
+ (&gateway->connect_client_1_work,
+ xenidc_gateway_connect_client_1, gateway);
+
+ xenidc_work_init
+ (&gateway->disconnect_client_1_work,
+ xenidc_gateway_disconnect_client_1, gateway);
+
+ xenidc_callback_init
+ (&gateway->disconnect_client_2_callback,
+ xenidc_gateway_disconnect_client_2);
+
+ gateway->kick_messages_and_transactions_out = 0;
+ gateway->kick_channel_messages_out = 0;
+ gateway->initiator_resources_out = 0;
+ gateway->target_resources_out = 0;
+
+ return 0;
+
+ EXIT:
+
+ if (gateway->target_quota != 0) {
+ vfree(gateway->target_resources);
+ }
+
+ EXIT_NO_TARGET_RESOURCES:
+
+ if (gateway->initiator_quota != 0) {
+ vfree(gateway->initiator_resources);
+ }
+
+ EXIT_NO_INITIATOR_RESOURCES:
+
+ return return_value;
+ }
+}
+
+void xenidc_gateway_submit_message
+ (xenidc_gateway * gateway, xenidc_gateway_message * message) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ list_add_tail
+ (xenidc_gateway_message_to_link(message),
+ &gateway->message_and_transaction_list);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_mt);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+void xenidc_gateway_submit_transaction
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ list_add_tail
+ (xenidc_gateway_transaction_to_link(transaction),
+ &gateway->message_and_transaction_list);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_mt);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+void xenidc_gateway_exit(xenidc_gateway * gateway)
+{
+ trace();
+
+ (void)xenidc_gateway_init_or_exit(gateway, 1);
+}
+
+static void xenidc_gateway_channel_connect(void *context)
+{
+ trace();
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_cc);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_handle_channel_message
+ (void *context, xenidc_channel_message * message) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+ xenidc_gateway_ring_element_header header;
+
+ if (xenidc_local_buffer_reference_copy_out
+ (&message->message_lbr, &header, sizeof(header))
+ != sizeof(header)
+ ) {
+ goto PROTOCOL_ERROR;
+ }
+
+ if (header.type == XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS) {
+ xenidc_local_buffer_reference status_lbr =
+ message->message_lbr;
+
+ xenidc_gateway_status_ring_element status_element;
+
+ if (xenidc_local_buffer_reference_copy_out
+ (&status_lbr, &status_element,
+ sizeof(status_element))
+ != sizeof(status_element)
+ ) {
+ goto PROTOCOL_ERROR;
+ }
+
+ xenidc_local_buffer_reference_advance
+ (&status_lbr, sizeof(status_element));
+
+ if (status_element.id >= gateway->initiator_quota) {
+ goto PROTOCOL_ERROR;
+ }
+
+ {
+ xenidc_gateway_initiator_resource *resource =
+ &gateway->
+ initiator_resources[status_element.id];
+
+ if (xenidc_gateway_initiator_resource_handle_status(resource, status_element.error, status_lbr)
+ != 0) {
+ goto PROTOCOL_ERROR;
+ }
+ }
+
+ xenidc_callback_success
+ (xenidc_channel_message_to_callback(message));
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ list_add_tail
+ (xenidc_channel_message_to_link(message),
+ &gateway->channel_message_list);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_cm);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+ }
+
+ return;
+
+ PROTOCOL_ERROR:
+
+ xenidc_callback_complete
+ (xenidc_channel_message_to_callback(message),
+ XENIDC_ERROR_INVALID_PROTOCOL);
+}
+
+static void xenidc_gateway_channel_disconnect
+ (void *context, xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ gateway->channel_disconnect_callback = callback;
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_cd);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+void xenidc_gateway_submit_channel_message
+ (xenidc_gateway * gateway, xenidc_channel_message * message) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ xenidc_channel_submit_message(gateway->channel, message);
+}
+
+void xenidc_gateway_submit_message_to_client
+ (xenidc_gateway * gateway, xenidc_gateway_message * message) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ gateway->handle_message(gateway, message);
+}
+
+void xenidc_gateway_submit_transaction_to_client
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ gateway->handle_transaction(gateway, transaction);
+}
+
+static void xenidc_gateway_invalid_stimulus
+ (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus);
+
+static void xenidc_gateway_kick_messages_and_transactions
+ (xenidc_gateway * gateway);
+
+static void xenidc_gateway_fail_out_messages_and_transactions
+ (xenidc_gateway * gateway);
+
+static void xenidc_gateway_kick_channel_messages(xenidc_gateway * gateway);
+
+static void xenidc_gateway_complete_channel_messages(xenidc_gateway * gateway);
+
+static void xenidc_gateway_connect_client(xenidc_gateway * gateway);
+
+static void xenidc_gateway_disconnect_client(xenidc_gateway * gateway);
+
+static void xenidc_gateway_abort_initiator_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_test_initiator_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_test_target_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_complete_channel_disconnect
+ (xenidc_gateway * gateway);
+
+static void xenidc_gateway_handle_stimulus
+ (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus) {
+ trace3
+ ("gateway %p in state %d received stimulus %d",
+ gateway, gateway->state, stimulus);
+
+ switch (gateway->state) {
+ case xenidc_gateway_state_i:
+ /* Channel disconnected. */
+ /* Client disconnected. */
+ /* No messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Initiator resources idle. */
+ /* Target resources idle. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_cc:
+ gateway->state = xenidc_gateway_state_i_cc;
+ xenidc_gateway_connect_client(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc:
+ /* Channel connected. */
+ /* Client connecting. */
+ /* Maybe messages or transactions queued. */
+ /* Maybe channel messages queued. */
+ /* Initiator resources idle. */
+ /* Target resources idle. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ case xenidc_gateway_stimulus_cm:
+ break;
+ case xenidc_gateway_stimulus_cd:
+ gateway->state = xenidc_gateway_state_i_cc_cd;
+ xenidc_gateway_complete_channel_messages(gateway);
+ break;
+ case xenidc_gateway_stimulus_lc:
+ gateway->state = xenidc_gateway_state_i_cc_lc;
+ xenidc_gateway_kick_messages_and_transactions(gateway);
+ xenidc_gateway_kick_channel_messages(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd:
+ /* Channel disconnecting. */
+ /* Client connecting. */
+ /* Maybe messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Initiator resources idle. */
+ /* Target resources idle. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ break;
+ case xenidc_gateway_stimulus_lc:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc;
+ xenidc_gateway_disconnect_client(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_lc:
+ /* Channel connected. */
+ /* Client connected. */
+ /* Maybe messages or transactions queued. */
+ /* Maybe channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* Maybe kicking m/t. */
+ /* Maybe kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ xenidc_gateway_kick_messages_and_transactions(gateway);
+ break;
+ case xenidc_gateway_stimulus_cm:
+ xenidc_gateway_kick_channel_messages(gateway);
+ break;
+ case xenidc_gateway_stimulus_cd:
+ gateway->state = xenidc_gateway_state_i_cc_lc_cd;
+ xenidc_gateway_complete_channel_messages(gateway);
+ xenidc_gateway_kick_messages_and_transactions(gateway);
+ xenidc_gateway_kick_channel_messages(gateway);
+ break;
+ case xenidc_gateway_stimulus_km:
+ case xenidc_gateway_stimulus_kc:
+ break;
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ xenidc_gateway_kick_messages_and_transactions(gateway);
+ break;
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ xenidc_gateway_kick_channel_messages(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_lc_cd:
+ /* Channel disconnecting. */
+ /* Client connected. */
+ /* Maybe messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* Kicking m/t. */
+ /* Kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ break;
+ case xenidc_gateway_stimulus_km:
+ case xenidc_gateway_stimulus_kc:
+ gateway->state = xenidc_gateway_state_i_cc_lc_cd_km;
+ break;
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_lc_cd_km:
+ /* Channel disconnecting. */
+ /* Client connected. */
+ /* Maybe messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* One of kicking m/t or cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ break;
+ case xenidc_gateway_stimulus_km:
+ case xenidc_gateway_stimulus_kc:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc;
+ xenidc_gateway_disconnect_client(gateway);
+ break;
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd_lc:
+ /* Channel disconnecting. */
+ /* Calling client disconnect. */
+ /* Maybe messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ break;
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ break;
+ case xenidc_gateway_stimulus_lg:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg;
+ xenidc_gateway_fail_out_messages_and_transactions
+ (gateway);
+ xenidc_gateway_abort_initiator_resources(gateway);
+ break;
+ case xenidc_gateway_stimulus_ld:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc_ld;
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd_lc_lg:
+ /* Channel disconnecting. */
+ /* Client disconnecting. */
+ /* No messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_mt:
+ break;
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ break;
+ case xenidc_gateway_stimulus_ld:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg_ld;
+ xenidc_gateway_test_target_resources(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd_lc_ld:
+ /* Channel disconnecting. */
+ /* Client disconnected but call still in progress. */
+ /* No messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Maybe target resources busy. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ case xenidc_gateway_stimulus_ti:
+ break;
+ case xenidc_gateway_stimulus_lg:
+ gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg_ld;
+ xenidc_gateway_test_target_resources(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd_lc_lg_ld:
+ /* Channel disconnecting. */
+ /* Client disconnected. */
+ /* No messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Maybe initiator resources busy. */
+ /* Test target resources or target resources busy. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_ic:
+ case xenidc_gateway_stimulus_ii:
+ case xenidc_gateway_stimulus_tc:
+ break;
+ case xenidc_gateway_stimulus_ti:
+ gateway->state =
+ xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti;
+ xenidc_gateway_test_initiator_resources(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti:
+ /* Channel disconnecting. */
+ /* Client disconnected. */
+ /* No messages or transactions queued. */
+ /* No channel messages queued. */
+ /* Test initiator resources or initiator resources busy. */
+ /* Target resources idle. */
+ /* Not kicking m/t. */
+ /* Not kicking cm. */
+ switch (stimulus) {
+ case xenidc_gateway_stimulus_ic:
+ break;
+ case xenidc_gateway_stimulus_ii:
+ gateway->state = xenidc_gateway_state_i;
+ xenidc_gateway_complete_channel_disconnect(gateway);
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+ break;
+ default:
+ xenidc_gateway_invalid_stimulus(gateway, stimulus);
+ break;
+ }
+}
+
+static void xenidc_gateway_invalid_stimulus
+ (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus) {
+ trace();
+
+ printk
+ (KERN_ERR "xenidc: gateway %p in state %d"
+ "received invalid stimulus %d", gateway, gateway->state, stimulus);
+}
+
+static void xenidc_gateway_kick_messages_and_transactions
+ (xenidc_gateway * gateway) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ if (!gateway->kick_messages_and_transactions_out) {
+ gateway->kick_messages_and_transactions_out = 1;
+
+ (void)xenidc_work_schedule
+ (&gateway->kick_messages_and_transactions_1_work);
+ }
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_1(void *data)
+{
+ trace();
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ while ((!list_empty(&gateway->message_and_transaction_list))
+ && (!list_empty(&gateway->initiator_resource_list))
+ ) {
+ xenidc_gateway_message_and_transaction_header *header =
+ list_entry(gateway->message_and_transaction_list.
+ next,
+ xenidc_gateway_message_and_transaction_header,
+ XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK);
+
+ xenidc_gateway_initiator_resource *resource = list_entry
+ (gateway->initiator_resource_list.next,
+ xenidc_gateway_initiator_resource,
+ XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK);
+
+ list_del_init
+ (xenidc_gateway_message_and_transaction_header_to_link
+ (header)
+ );
+
+ list_del_init
+ (xenidc_gateway_initiator_resource_to_link
+ (resource));
+
+ gateway->initiator_resources_out++;
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+
+ xenidc_gateway_initiator_resource_start(resource,
+ header);
+
+ spin_lock_irqsave(&gateway->lock, flags);
+ }
+
+ gateway->kick_messages_and_transactions_out = 0;
+
+ xenidc_gateway_handle_stimulus(gateway,
+ xenidc_gateway_stimulus_km);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_2
+ (xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_initiator_resource *resource =
+ xenidc_gateway_initiator_resource_callback_to(callback);
+
+ xenidc_gateway *gateway =
+ xenidc_gateway_initiator_resource_query_gateway(resource);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ list_add_tail
+ (xenidc_gateway_initiator_resource_to_link(resource),
+ &gateway->initiator_resource_list);
+
+ if (--gateway->initiator_resources_out != 0) {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ic);
+ } else {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ii);
+ }
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_fail_out_messages_and_transactions
+ (xenidc_gateway * gateway) {
+ trace();
+
+ while (!list_empty(&gateway->message_and_transaction_list)) {
+ xenidc_gateway_message_and_transaction_header *header =
+ list_entry(gateway->message_and_transaction_list.next,
+ xenidc_gateway_message_and_transaction_header,
+ XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK);
+
+ list_del_init
+ (xenidc_gateway_message_and_transaction_header_to_link
+ (header));
+
+ xenidc_callback_complete
+ (xenidc_gateway_message_and_transaction_header_to_callback
+ (header), XENIDC_ERROR_DISCONNECT);
+ }
+}
+
+static void xenidc_gateway_kick_channel_messages(xenidc_gateway * gateway)
+{
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ if (!gateway->kick_channel_messages_out) {
+ gateway->kick_channel_messages_out = 1;
+
+ (void)xenidc_work_schedule(&gateway->
+ kick_channel_messages_1_work);
+ }
+}
+
+static void xenidc_gateway_kick_channel_messages_1(void *data)
+{
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ while ((!list_empty(&gateway->channel_message_list))
+ && (!list_empty(&gateway->target_resource_list))
+ ) {
+ xenidc_channel_message *message = list_entry
+ (gateway->channel_message_list.next,
+ xenidc_channel_message,
+ XENIDC_CHANNEL_MESSAGE_LINK);
+
+ xenidc_gateway_target_resource *resource = list_entry
+ (gateway->target_resource_list.next,
+ xenidc_gateway_target_resource,
+ XENIDC_GATEWAY_TARGET_RESOURCE_LINK);
+
+ list_del_init(xenidc_channel_message_to_link(message));
+
+ {
+ xenidc_gateway_ring_element_header header;
+
+ if (xenidc_local_buffer_reference_copy_out
+ (&message->message_lbr, &header,
+ sizeof(header))
+ != sizeof(header)
+ ) {
+ goto PROTOCOL_ERROR;
+ }
+
+ if (header.type ==
+ XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE) {
+ xenidc_local_buffer_reference
+ message_lbr = message->message_lbr;
+
+ xenidc_local_buffer_reference_advance
+ (&message_lbr,
+ sizeof
+ (xenidc_gateway_message_ring_element)
+ );
+
+ list_del_init
+ (xenidc_gateway_target_resource_to_link
+ (resource));
+
+ gateway->target_resources_out++;
+
+ spin_unlock_irqrestore(&gateway->lock,
+ flags);
+
+ xenidc_gateway_target_resource_start_message
+ (resource, message_lbr);
+
+ spin_lock_irqsave(&gateway->lock,
+ flags);
+
+ xenidc_callback_success
+ (xenidc_channel_message_to_callback
+ (message));
+ } else if (header.type ==
+ XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS)
+ {
+ xenidc_local_buffer_reference
+ parameters_lbr =
+ message->message_lbr;
+
+ xenidc_gateway_parameters_ring_element
+ parameters_element;
+
+ if (xenidc_local_buffer_reference_copy_out(¶meters_lbr, ¶meters_element, sizeof(parameters_element)
+ )
+ != sizeof(parameters_element)
+ ) {
+ goto PROTOCOL_ERROR;
+ }
+
+ xenidc_local_buffer_reference_advance
+ (¶meters_lbr,
+ sizeof(parameters_element));
+
+ list_del_init
+ (xenidc_gateway_target_resource_to_link
+ (resource));
+
+ gateway->target_resources_out++;
+
+ spin_unlock_irqrestore(&gateway->lock,
+ flags);
+
+ xenidc_gateway_target_resource_start_transaction
+ (resource,
+ parameters_element.id,
+ parameters_lbr,
+ parameters_element.
+ status_byte_count);
+
+ spin_lock_irqsave(&gateway->lock,
+ flags);
+
+ xenidc_callback_success
+ (xenidc_channel_message_to_callback
+ (message));
+ } else {
+ PROTOCOL_ERROR:
+
+ xenidc_callback_complete
+ (xenidc_channel_message_to_callback
+ (message),
+ XENIDC_ERROR_INVALID_PROTOCOL);
+ }
+ }
+ }
+
+ gateway->kick_channel_messages_out = 0;
+
+ xenidc_gateway_handle_stimulus(gateway,
+ xenidc_gateway_stimulus_kc);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_kick_channel_messages_2(xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_target_resource *resource =
+ xenidc_gateway_target_resource_callback_to(callback);
+
+ xenidc_gateway *gateway =
+ xenidc_gateway_target_resource_query_gateway(resource);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ list_add_tail
+ (xenidc_gateway_target_resource_to_link(resource),
+ &gateway->target_resource_list);
+
+ if (--gateway->target_resources_out != 0) {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_tc);
+ } else {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ti);
+ }
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_complete_channel_messages(xenidc_gateway * gateway) {
+ trace();
+
+ while (!list_empty(&gateway->channel_message_list)) {
+ xenidc_channel_message *message = list_entry
+ (gateway->channel_message_list.next,
+ xenidc_channel_message,
+ XENIDC_CHANNEL_MESSAGE_LINK);
+
+ list_del_init(xenidc_channel_message_to_link(message));
+
+ xenidc_callback_success
+ (xenidc_channel_message_to_callback(message));
+ }
+}
+
+static void xenidc_gateway_connect_client(xenidc_gateway * gateway)
+{
+ trace();
+
+ (void)xenidc_work_schedule(&gateway->connect_client_1_work);
+}
+
+static void xenidc_gateway_connect_client_1(void *data)
+{
+ trace();
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+ gateway->connect(gateway);
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_lc);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+ }
+}
+
+static void xenidc_gateway_disconnect_client(xenidc_gateway * gateway)
+{
+ trace();
+
+ (void)xenidc_work_schedule(&gateway->disconnect_client_1_work);
+}
+
+static void xenidc_gateway_disconnect_client_1(void *data)
+{
+ trace();
+
+ {
+ xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+ gateway->disconnect(gateway,
+ &gateway->disconnect_client_2_callback);
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_lg);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+ }
+}
+
+static void xenidc_gateway_disconnect_client_2(xenidc_callback * callback)
+{
+ trace();
+
+ {
+ xenidc_gateway *gateway = container_of
+ (callback, xenidc_gateway, disconnect_client_2_callback);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&gateway->lock, flags);
+
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ld);
+
+ spin_unlock_irqrestore(&gateway->lock, flags);
+ }
+}
+
+static void xenidc_gateway_abort_initiator_resources(xenidc_gateway * gateway) {
+ trace();
+
+ {
+ u32 i;
+
+ for (i = 0; i < gateway->initiator_quota; i++) {
+ xenidc_gateway_initiator_resource_abort
+ (&gateway->initiator_resources[i],
+ XENIDC_ERROR_DISCONNECT);
+ }
+ }
+}
+
+static void xenidc_gateway_test_initiator_resources(xenidc_gateway * gateway) {
+ trace();
+
+ if (gateway->initiator_resources_out == 0) {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ii);
+ }
+}
+
+static void xenidc_gateway_test_target_resources(xenidc_gateway * gateway) {
+ trace();
+
+ if (gateway->target_resources_out == 0) {
+ xenidc_gateway_handle_stimulus
+ (gateway, xenidc_gateway_stimulus_ti);
+ }
+}
+
+static void xenidc_gateway_complete_channel_disconnect(xenidc_gateway * gateway) {
+ trace();
+
+ xenidc_callback_success(gateway->channel_disconnect_callback);
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.c
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.c Sun Nov 20 17:45:16 2005
@@ -0,0 +1,382 @@
+/*****************************************************************************/
+/* The xenidc_gateway_initiator_resource object performs the initiator-side */
+/* part of the processing of a client message or transaction sent across the */
+/* gateway. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_vaddress.h>
+#include "xenidc_gateway_initiator_resource.h"
+#include "xenidc_trace.h"
+
+extern void xenidc_gateway_submit_channel_message
+ (xenidc_gateway * gateway, xenidc_channel_message * message);
+
+static void xenidc_gateway_initiator_resource_handle_stimulus
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_initiator_resource_stimulus stimulus);
+
+static void xenidc_gateway_initiator_resource_channel_message_callback
+ (xenidc_callback * callback);
+
+void xenidc_gateway_initiator_resource_init
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway * gateway, xenidc_callback_function callback, int id) {
+ trace();
+
+ xenidc_callback_init(&resource->callback, callback);
+
+ resource->gateway = gateway;
+
+ resource->id = id;
+
+ spin_lock_init(&resource->lock);
+
+ resource->state = xenidc_gateway_initiator_resource_state_i;
+
+ xenidc_callback_init
+ (xenidc_channel_message_to_callback(&resource->channel_message),
+ xenidc_gateway_initiator_resource_channel_message_callback);
+}
+
+void xenidc_gateway_initiator_resource_start
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_message_and_transaction_header * header) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ resource->header = header;
+
+ resource->error = XENIDC_ERROR_SUCCESS;
+
+ {
+ xenidc_gateway_initiator_resource_stimulus stimulus;
+
+ if (header->transaction_not_message) {
+ xenidc_gateway_transaction *transaction =
+ xenidc_gateway_transaction_header_to(header);
+
+ resource->element_lbr = xenidc_vaddress_create_lbr
+ (&resource->parameters_element,
+ sizeof(resource->parameters_element)
+ );
+
+ resource->channel_message.message_lbr =
+ xenidc_concatenate_create_lbr
+ (&resource->base,
+ &resource->element_lbr,
+ &transaction->parameters_lbr);
+
+ memset
+ (&resource->parameters_element,
+ 0, sizeof(resource->parameters_element)
+ );
+
+ resource->parameters_element.header.type =
+ XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS;
+
+ resource->parameters_element.id = resource->id;
+
+ resource->parameters_element.status_byte_count =
+ xenidc_local_buffer_reference_query_byte_count
+ (&transaction->status_lbr);
+
+ stimulus =
+ xenidc_gateway_initiator_resource_stimulus_st;
+ } else {
+ xenidc_gateway_message *message =
+ xenidc_gateway_message_header_to(header);
+
+ resource->element_lbr = xenidc_vaddress_create_lbr
+ (&resource->message_element,
+ sizeof(resource->message_element)
+ );
+
+ resource->channel_message.message_lbr =
+ xenidc_concatenate_create_lbr
+ (&resource->base,
+ &resource->element_lbr, &message->message_lbr);
+
+ memset
+ (&resource->message_element,
+ 0, sizeof(resource->message_element)
+ );
+
+ resource->parameters_element.header.type =
+ XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE;
+
+ stimulus =
+ xenidc_gateway_initiator_resource_stimulus_sm;
+ }
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&resource->lock, flags);
+
+ xenidc_gateway_initiator_resource_handle_stimulus
+ (resource, stimulus);
+
+ spin_unlock_irqrestore(&resource->lock, flags);
+ }
+
+ xenidc_gateway_submit_channel_message
+ (resource->gateway, &resource->channel_message);
+ }
+}
+
+void xenidc_gateway_initiator_resource_abort
+ (xenidc_gateway_initiator_resource * resource, xenidc_error error) {
+ trace();
+
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&resource->lock, flags);
+
+ resource->aborted_error = error;
+
+ xenidc_gateway_initiator_resource_handle_stimulus
+ (resource, xenidc_gateway_initiator_resource_stimulus_ab);
+
+ spin_unlock_irqrestore(&resource->lock, flags);
+ }
+}
+
+static void xenidc_gateway_initiator_resource_channel_message_callback
+ (xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_initiator_resource *resource = container_of
+ (callback,
+ xenidc_gateway_initiator_resource,
+ channel_message.callback);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&resource->lock, flags);
+
+ xenidc_gateway_initiator_resource_handle_stimulus
+ (resource, xenidc_gateway_initiator_resource_stimulus_sc);
+
+ spin_unlock_irqrestore(&resource->lock, flags);
+ }
+}
+
+int xenidc_gateway_initiator_resource_handle_status
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_error error, xenidc_local_buffer_reference status_lbr) {
+ trace();
+
+ {
+ int return_value = -1;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&resource->lock, flags);
+
+ if ((resource->state
+ == xenidc_gateway_initiator_resource_state_i_st)
+ ||
+ (resource->state
+ == xenidc_gateway_initiator_resource_state_i_st_sc)
+ ) {
+ xenidc_gateway_transaction *transaction =
+ xenidc_gateway_transaction_header_to(resource->
+ header);
+
+ if (xenidc_local_buffer_reference_query_byte_count
+ (&status_lbr)
+ ==
+ xenidc_local_buffer_reference_query_byte_count
+ (&transaction->status_lbr)
+ ) {
+ xenidc_local_buffer_reference_copy
+ (&transaction->status_lbr, &status_lbr);
+
+ resource->error = error;
+
+ xenidc_gateway_initiator_resource_handle_stimulus
+ (resource,
+ xenidc_gateway_initiator_resource_stimulus_ts);
+
+ return_value = 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&resource->lock, flags);
+
+ return return_value;
+ }
+}
+
+static void xenidc_gateway_initiator_resource_invalid_stimulus
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_initiator_resource_stimulus stimulus);
+
+static void xenidc_gateway_initiator_resource_set_aborted
+ (xenidc_gateway_initiator_resource * resource);
+
+static void xenidc_gateway_initiator_resource_complete
+ (xenidc_gateway_initiator_resource * resource);
+
+static void xenidc_gateway_initiator_resource_handle_stimulus
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_initiator_resource_stimulus stimulus) {
+ trace3
+ ("gateway initiator resource %p in state %d received stimulus %d",
+ resource, resource->state, stimulus);
+
+ switch (resource->state) {
+ case xenidc_gateway_initiator_resource_state_i:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_sm:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i_sm;
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_st:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i_st;
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_ab:
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_initiator_resource_state_i_sm:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_ab:
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_sc:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i;
+ xenidc_gateway_initiator_resource_complete(resource);
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_initiator_resource_state_i_st:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_ab:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i_st_ab;
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_sc:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i_st_sc;
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_ts:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i_st_ts;
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_initiator_resource_state_i_st_ab:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_sc:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i;
+ xenidc_gateway_initiator_resource_set_aborted(resource);
+ xenidc_gateway_initiator_resource_complete(resource);
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_initiator_resource_state_i_st_sc:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_ab:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i;
+ xenidc_gateway_initiator_resource_set_aborted(resource);
+ xenidc_gateway_initiator_resource_complete(resource);
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_ts:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i;
+ xenidc_gateway_initiator_resource_complete(resource);
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ case xenidc_gateway_initiator_resource_state_i_st_ts:
+ switch (stimulus) {
+ case xenidc_gateway_initiator_resource_stimulus_ab:
+ break;
+ case xenidc_gateway_initiator_resource_stimulus_sc:
+ resource->state =
+ xenidc_gateway_initiator_resource_state_i;
+ xenidc_gateway_initiator_resource_complete(resource);
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+ break;
+ default:
+ xenidc_gateway_initiator_resource_invalid_stimulus
+ (resource, stimulus);
+ break;
+ }
+}
+
+static void xenidc_gateway_initiator_resource_invalid_stimulus
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_initiator_resource_stimulus stimulus) {
+ trace();
+
+ printk
+ (KERN_ERR "xenidc: gateway initiator resource %p in state %d"
+ "received invalid stimulus %d",
+ resource, resource->state, stimulus);
+}
+
+static void xenidc_gateway_initiator_resource_set_aborted
+ (xenidc_gateway_initiator_resource * resource) {
+ trace();
+
+ resource->error = resource->aborted_error;
+}
+
+static void xenidc_gateway_initiator_resource_complete
+ (xenidc_gateway_initiator_resource * resource) {
+ trace();
+
+ xenidc_callback_complete(&resource->header->callback, resource->error);
+
+ xenidc_callback_success(&resource->callback);
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.h
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.h Sun Nov 20 17:45:16 2005
@@ -0,0 +1,78 @@
+#ifndef _XENIDC_GATEWAY_INITIATOR_RESOURCE_H
+#define _XENIDC_GATEWAY_INITIATOR_RESOURCE_H
+
+#include <asm-xen/xenidc_concatenate.h>
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_gateway.h>
+#include "xenidc_gateway_ring.h"
+
+typedef enum {
+ xenidc_gateway_initiator_resource_state_i,
+ xenidc_gateway_initiator_resource_state_i_sm,
+ xenidc_gateway_initiator_resource_state_i_st,
+ xenidc_gateway_initiator_resource_state_i_st_ab,
+ xenidc_gateway_initiator_resource_state_i_st_sc,
+ xenidc_gateway_initiator_resource_state_i_st_ts
+} xenidc_gateway_initiator_resource_state;
+
+typedef enum {
+ xenidc_gateway_initiator_resource_stimulus_sm, /* Start message */
+ xenidc_gateway_initiator_resource_stimulus_st, /* Start transaction */
+ xenidc_gateway_initiator_resource_stimulus_ab, /* Abort */
+ xenidc_gateway_initiator_resource_stimulus_sc, /* Send complete */
+ xenidc_gateway_initiator_resource_stimulus_ts, /* Transaction status */
+} xenidc_gateway_initiator_resource_stimulus;
+
+struct xenidc_gateway_initiator_resource_struct {
+ xenidc_callback callback;
+ xenidc_gateway *gateway;
+ int id;
+ spinlock_t lock;
+ xenidc_gateway_initiator_resource_state state;
+ xenidc_gateway_message_and_transaction_header *header;
+ xenidc_error aborted_error;
+ xenidc_error error;
+ xenidc_channel_message channel_message;
+ xenidc_local_buffer_reference element_lbr;
+ xenidc_concatenate_base base;
+ union {
+ xenidc_gateway_parameters_ring_element parameters_element;
+ xenidc_gateway_message_ring_element message_element;
+ };
+};
+
+#define XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head *xenidc_gateway_initiator_resource_to_link
+ (xenidc_gateway_initiator_resource * resource) {
+ return &resource->XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK;
+}
+
+static inline xenidc_gateway_initiator_resource
+ *xenidc_gateway_initiator_resource_callback_to(xenidc_callback * callback)
+{
+ return container_of
+ (callback, xenidc_gateway_initiator_resource, callback);
+}
+
+static inline xenidc_gateway *xenidc_gateway_initiator_resource_query_gateway
+ (xenidc_gateway_initiator_resource * resource) {
+ return resource->gateway;
+}
+
+void xenidc_gateway_initiator_resource_init
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway * gateway, xenidc_callback_function callback, int id);
+
+void xenidc_gateway_initiator_resource_start
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_gateway_message_and_transaction_header * header);
+
+void xenidc_gateway_initiator_resource_abort
+ (xenidc_gateway_initiator_resource * resource, xenidc_error error);
+
+int xenidc_gateway_initiator_resource_handle_status
+ (xenidc_gateway_initiator_resource * resource,
+ xenidc_error error, xenidc_local_buffer_reference status);
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_ring.h
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_ring.h Sun Nov 20 17:45:16 2005
@@ -0,0 +1,65 @@
+/*****************************************************************************/
+/* Xen inter-domain communication gateway ring structure definitions. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#ifndef _XENIDC_GATEWAY_RING_H
+#define _XENIDC_GATEWAY_RING_H
+
+#include <asm-xen/xenidc_error.h>
+
+typedef struct xenidc_gateway_ring_element_header_struct
+ xenidc_gateway_ring_element_header;
+
+struct xenidc_gateway_ring_element_header_struct {
+ u8 type;
+ u8 reserved[7];
+};
+
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE 0
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS 1
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS 2
+
+typedef struct xenidc_gateway_message_ring_element_struct
+ xenidc_gateway_message_ring_element;
+
+struct xenidc_gateway_message_ring_element_struct {
+ xenidc_gateway_ring_element_header header;
+};
+
+typedef struct xenidc_gateway_parameters_ring_element_struct
+ xenidc_gateway_parameters_ring_element;
+
+struct xenidc_gateway_parameters_ring_element_struct {
+ xenidc_gateway_ring_element_header header;
+ u32 id;
+ u16 status_byte_count;
+ u16 reserved;
+};
+
+typedef struct xenidc_gateway_status_ring_element_struct
+ xenidc_gateway_status_ring_element;
+
+struct xenidc_gateway_status_ring_element_struct {
+ xenidc_gateway_ring_element_header header;
+ u32 id;
+ xenidc_error error;
+};
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.c
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.c Sun Nov 20 17:45:16 2005
@@ -0,0 +1,190 @@
+/*****************************************************************************/
+/* The xenidc_gateway_target_resource object performs the target-side part */
+/* of the processing of a client message or transaction sent across the */
+/* gateway. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_vaddress.h>
+#include "xenidc_gateway_target_resource.h"
+#include "xenidc_trace.h"
+
+extern void xenidc_gateway_submit_channel_message
+ (xenidc_gateway * gateway, xenidc_channel_message * message);
+
+extern void xenidc_gateway_submit_message_to_client
+ (xenidc_gateway * gateway, xenidc_gateway_message * message);
+
+extern void xenidc_gateway_submit_transaction_to_client
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+
+static void xenidc_gateway_target_resource_channel_message_callback
+ (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_init
+ (xenidc_gateway_target_resource * resource,
+ xenidc_gateway * gateway,
+ xenidc_callback_function callback, xenidc_local_buffer_reference buffer) {
+ trace();
+
+ xenidc_callback_init(&resource->callback, callback);
+
+ resource->gateway = gateway;
+
+ resource->buffer = buffer;
+
+ xenidc_callback_init
+ (xenidc_channel_message_to_callback(&resource->channel_message),
+ xenidc_gateway_target_resource_channel_message_callback);
+
+ resource->element_lbr = xenidc_vaddress_create_lbr
+ (&resource->status_element, sizeof(resource->status_element));
+
+ memset(&resource->status_element, 0, sizeof(resource->status_element));
+
+ resource->status_element.header.type =
+ XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS;
+}
+
+static void xenidc_gateway_target_resource_message_callback
+ (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_start_message
+ (xenidc_gateway_target_resource * resource,
+ xenidc_local_buffer_reference message_lbr) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ xenidc_gateway_message_init
+ (&resource->message,
+ xenidc_gateway_target_resource_message_callback);
+
+ {
+ xenidc_local_buffer_reference lbr = resource->buffer;
+
+ xenidc_local_buffer_reference_truncate
+ (&lbr,
+ xenidc_local_buffer_reference_copy(&lbr, &message_lbr)
+ );
+
+ resource->message.message_lbr = lbr;
+ }
+
+ xenidc_gateway_submit_message_to_client
+ (resource->gateway, &resource->message);
+}
+
+static void xenidc_gateway_target_resource_message_callback
+ (xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_target_resource *resource = container_of
+ (xenidc_gateway_message_callback_to(callback),
+ xenidc_gateway_target_resource,
+ message);
+
+ xenidc_callback_success(&resource->callback);
+ }
+}
+
+static void xenidc_gateway_target_resource_transaction_callback
+ (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_start_transaction
+ (xenidc_gateway_target_resource * resource,
+ u32 id,
+ xenidc_local_buffer_reference parameters_lbr,
+ xenidc_buffer_byte_count status_byte_count) {
+ trace();
+
+ /* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+ xenidc_gateway_transaction_init
+ (&resource->transaction,
+ xenidc_gateway_target_resource_transaction_callback);
+
+ {
+ xenidc_local_buffer_reference lbr = resource->buffer;
+
+ xenidc_local_buffer_reference_truncate
+ (&lbr,
+ xenidc_local_buffer_reference_copy(&lbr, ¶meters_lbr)
+ );
+
+ resource->transaction.parameters_lbr = lbr;
+ }
+
+ {
+ xenidc_local_buffer_reference lbr = resource->buffer;
+
+ xenidc_local_buffer_reference_subrange
+ (&lbr,
+ xenidc_local_buffer_reference_query_byte_count
+ (¶meters_lbr), status_byte_count);
+
+ xenidc_local_buffer_reference_zero(&lbr);
+
+ resource->transaction.status_lbr = lbr;
+ }
+
+ resource->status_element.id = id;
+
+ xenidc_gateway_submit_transaction_to_client
+ (resource->gateway, &resource->transaction);
+}
+
+static void xenidc_gateway_target_resource_transaction_callback
+ (xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_target_resource *resource = container_of
+ (xenidc_gateway_transaction_callback_to(callback),
+ xenidc_gateway_target_resource,
+ transaction);
+
+ resource->status_element.error =
+ xenidc_callback_query_error(callback);
+
+ resource->channel_message.message_lbr =
+ xenidc_concatenate_create_lbr(&resource->base,
+ &resource->element_lbr,
+ &resource->transaction.
+ status_lbr);
+
+ xenidc_gateway_submit_channel_message
+ (resource->gateway, &resource->channel_message);
+ }
+}
+
+static void xenidc_gateway_target_resource_channel_message_callback
+ (xenidc_callback * callback) {
+ trace();
+
+ {
+ xenidc_gateway_target_resource *resource = container_of
+ (callback,
+ xenidc_gateway_target_resource,
+ channel_message.callback);
+
+ xenidc_callback_success(&resource->callback);
+ }
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.h
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.h Sun Nov 20 17:45:16 2005
@@ -0,0 +1,79 @@
+/*****************************************************************************/
+/* The xenidc_gateway_target_resource object performs the target-side part */
+/* of the processing of a client message or transaction sent across the */
+/* gateway. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#ifndef _XENIDC_GATEWAY_TARGET_RESOURCE_H
+#define _XENIDC_GATEWAY_TARGET_RESOURCE_H
+
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_concatenate.h>
+#include <asm-xen/xenidc_gateway.h>
+#include "xenidc_gateway_ring.h"
+
+struct xenidc_gateway_target_resource_struct {
+ xenidc_callback callback;
+ xenidc_gateway *gateway;
+ xenidc_local_buffer_reference buffer;
+ union {
+ xenidc_gateway_message message;
+ xenidc_gateway_transaction transaction;
+ };
+ xenidc_channel_message channel_message;
+ xenidc_local_buffer_reference element_lbr;
+ xenidc_concatenate_base base;
+ xenidc_gateway_status_ring_element status_element;
+};
+
+#define XENIDC_GATEWAY_TARGET_RESOURCE_LINK callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head *xenidc_gateway_target_resource_to_link
+ (xenidc_gateway_target_resource * resource) {
+ return &resource->XENIDC_GATEWAY_TARGET_RESOURCE_LINK;
+}
+
+static inline xenidc_gateway_target_resource
+ *xenidc_gateway_target_resource_callback_to(xenidc_callback * callback)
+{
+ return container_of(callback, xenidc_gateway_target_resource, callback);
+}
+
+static inline xenidc_gateway *xenidc_gateway_target_resource_query_gateway
+ (xenidc_gateway_target_resource * resource) {
+ return resource->gateway;
+}
+
+extern void xenidc_gateway_target_resource_init
+ (xenidc_gateway_target_resource * resource,
+ xenidc_gateway * gateway,
+ xenidc_callback_function callback, xenidc_local_buffer_reference buffer);
+
+extern void xenidc_gateway_target_resource_start_message
+ (xenidc_gateway_target_resource * resource,
+ xenidc_local_buffer_reference message_lbr);
+
+extern void xenidc_gateway_target_resource_start_transaction
+ (xenidc_gateway_target_resource * resource,
+ u32 id,
+ xenidc_local_buffer_reference parameters_lbr,
+ xenidc_buffer_byte_count status_byte_count);
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/include/asm-xen/xenidc_gateway.h
--- /dev/null Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_gateway.h Sun Nov 20 17:45:16 2005
@@ -0,0 +1,254 @@
+/*****************************************************************************/
+/* Xen inter-domain communication gateway class. This class uses the message */
+/* channel service provided by a xenidc_channel to implement a gateway */
+/* service which allows the client to send both messages and transactions */
+/* (consisting of parameters and status) between domains. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
+/* Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along */
+/* with this program; if not, write to the Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#ifndef _XENIDC_GATEWAY_H
+#define _XENIDC_GATEWAY_H
+
+#include <asm-xen/xenidc_callback.h>
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_local_buffer_reference.h>
+
+typedef struct xenidc_gateway_initiator_resource_struct
+ xenidc_gateway_initiator_resource;
+
+typedef struct xenidc_gateway_target_resource_struct
+ xenidc_gateway_target_resource;
+
+/* Messages and transactions share a common header because relative order is */
+/* preserved on submission and so they are queued on the same list. */
+
+typedef struct xenidc_gateway_message_and_transaction_header_struct
+ xenidc_gateway_message_and_transaction_header;
+
+struct xenidc_gateway_message_and_transaction_header_struct {
+ xenidc_callback callback;
+ int transaction_not_message;
+};
+
+#define XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK \
+callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head
+ *xenidc_gateway_message_and_transaction_header_to_link
+ (xenidc_gateway_message_and_transaction_header * header) {
+ return xenidc_callback_to_link(&header->callback);
+}
+
+static inline xenidc_callback
+ *xenidc_gateway_message_and_transaction_header_to_callback
+ (xenidc_gateway_message_and_transaction_header * header) {
+ return &header->callback;
+}
+
+/* A xenidc_gateway_message is used to send a message from the local domain */
+/* to the remote domain using the gateway. This is also the structure used */
+/* by the gateway to pass a message to the client. The receiver gets to */
+/* hold onto the message as long as necessary and completes the callback to */
+/* return it when finished with it. */
+
+typedef struct xenidc_gateway_message_struct xenidc_gateway_message;
+
+struct xenidc_gateway_message_struct {
+ xenidc_gateway_message_and_transaction_header header;
+ xenidc_local_buffer_reference message_lbr;
+};
+
+static inline xenidc_callback *xenidc_gateway_message_to_callback
+ (xenidc_gateway_message * message) {
+ return &message->header.callback;
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_callback_to
+ (xenidc_callback * callback) {
+ return container_of(callback, xenidc_gateway_message, header.callback);
+}
+
+static inline struct list_head *xenidc_gateway_message_to_link
+ (xenidc_gateway_message * message) {
+ return xenidc_callback_to_link(&message->header.callback);
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_link_to
+ (struct list_head *link) {
+ return xenidc_gateway_message_callback_to
+ (xenidc_callback_link_to(link));
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_header_to
+ (xenidc_gateway_message_and_transaction_header * header) {
+ return container_of(header, xenidc_gateway_message, header);
+}
+
+static inline void xenidc_gateway_message_init
+ (xenidc_gateway_message * message, xenidc_callback_function * callback) {
+ xenidc_callback_init
+ (xenidc_gateway_message_to_callback(message), callback);
+
+ message->header.transaction_not_message = 0;
+}
+
+/* A xenidc_gateway_transaction is used to send a transaction to the remote */
+/* domain from the local domain. The transaction passes parameters to the */
+/* remote domain and gets status back from the remote domain. */
+/* The structure is used for both sending transactions and when inbound */
+/* transactions are received. The target domain completes the transaction */
+/* with a xenidc_error which is returned to the transaction initiator as the */
+/* error of the callback of the initiators transaction. */
+
+typedef struct xenidc_gateway_transaction_struct xenidc_gateway_transaction;
+
+struct xenidc_gateway_transaction_struct {
+ xenidc_gateway_message_and_transaction_header header;
+ xenidc_local_buffer_reference parameters_lbr;
+ xenidc_local_buffer_reference status_lbr;
+};
+
+#define XENIDC_GATEWAY_TRANSACTION_LINK header.callback.XENIDC_CALLBACK_LINK
+
+static inline xenidc_callback *xenidc_gateway_transaction_to_callback
+ (xenidc_gateway_transaction * transaction) {
+ return &transaction->header.callback;
+}
+
+static inline xenidc_gateway_transaction
+ *xenidc_gateway_transaction_callback_to(xenidc_callback * callback)
+{
+ return container_of
+ (callback, xenidc_gateway_transaction, header.callback);
+}
+
+static inline struct list_head *xenidc_gateway_transaction_to_link
+ (xenidc_gateway_transaction * transaction) {
+ return xenidc_callback_to_link
+ (xenidc_gateway_transaction_to_callback(transaction));
+}
+
+static inline xenidc_gateway_transaction *xenidc_gateway_transaction_link_to
+ (struct list_head *link) {
+ return xenidc_gateway_transaction_callback_to
+ (xenidc_callback_link_to(link));
+}
+
+static inline xenidc_gateway_transaction *xenidc_gateway_transaction_header_to
+ (xenidc_gateway_message_and_transaction_header * header) {
+ return container_of(header, xenidc_gateway_transaction, header);
+}
+
+static inline void xenidc_gateway_transaction_init
+ (xenidc_gateway_transaction * transaction,
+ xenidc_callback_function * callback) {
+ xenidc_callback_init
+ (xenidc_gateway_transaction_to_callback(transaction), callback);
+
+ transaction->header.transaction_not_message = 1;
+}
+
+typedef enum {
+ xenidc_gateway_state_i,
+ xenidc_gateway_state_i_cc,
+ xenidc_gateway_state_i_cc_cd,
+ xenidc_gateway_state_i_cc_lc,
+ xenidc_gateway_state_i_cc_cd_lc,
+ xenidc_gateway_state_i_cc_lc_cd,
+ xenidc_gateway_state_i_cc_lc_cd_km,
+ xenidc_gateway_state_i_cc_cd_lc_lg,
+ xenidc_gateway_state_i_cc_cd_lc_ld,
+ xenidc_gateway_state_i_cc_cd_lc_lg_ld,
+ xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti
+} xenidc_gateway_state;
+
+typedef struct xenidc_gateway_struct xenidc_gateway;
+
+struct xenidc_gateway_struct {
+ xenidc_channel *channel;
+ void (*connect) (xenidc_gateway * gateway);
+ void (*handle_message)
+ (xenidc_gateway * gateway, xenidc_gateway_message * message);
+ void (*handle_transaction)
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+ void (*disconnect)
+ (xenidc_gateway * gateway, xenidc_callback * callback);
+
+ u32 initiator_quota;
+ u32 target_quota;
+ xenidc_buffer_byte_count target_maximum_byte_count;
+
+ struct list_head initiator_resource_list;
+ xenidc_gateway_initiator_resource *initiator_resources;
+
+ struct list_head target_resource_list;
+ xenidc_gateway_target_resource *target_resources;
+
+ spinlock_t lock;
+
+ xenidc_gateway_state state;
+
+ struct list_head message_and_transaction_list;
+ struct list_head channel_message_list;
+
+ xenidc_work kick_messages_and_transactions_1_work;
+ xenidc_work kick_channel_messages_1_work;
+ xenidc_work connect_client_1_work;
+ xenidc_work disconnect_client_1_work;
+ xenidc_callback disconnect_client_2_callback;
+
+ int kick_messages_and_transactions_out:1;
+ int kick_channel_messages_out:1;
+ u32 initiator_resources_out;
+ u32 target_resources_out;
+
+ xenidc_callback *channel_disconnect_callback;
+};
+
+/* Initialised with underlying channel to use to send inter-domain messages */
+/* and client's callbacks and required quotas. */
+
+extern int xenidc_gateway_init
+ (xenidc_gateway * gateway,
+ xenidc_channel * channel,
+ void (*connect) (xenidc_gateway * gateway), void (*handle_message)
+ (xenidc_gateway * gateway, xenidc_gateway_message * message),
+ void (*handle_transaction)
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction),
+ void (*disconnect)
+ (xenidc_gateway * gateway, xenidc_callback * callback),
+ u32 initiator_quota,
+ xenidc_buffer_byte_count initiator_maximum_byte_count,
+ u32 target_quota, xenidc_buffer_byte_count target_maximum_byte_count);
+
+/* Called by client between connect and disconnect callback to submit a */
+/* message. */
+
+extern void xenidc_gateway_submit_message
+ (xenidc_gateway * gateway, xenidc_gateway_message * message);
+
+/* Called by client between connect and disconnect callback to submit a */
+/* transaction. */
+
+extern void xenidc_gateway_submit_transaction
+ (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+
+extern void xenidc_gateway_exit(xenidc_gateway * gateway);
+
+#endif
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
reply other threads:[~2005-11-21 13:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1132579145.31295.120.camel@localhost.localdomain \
--to=harry@hebutterworth.freeserve.co.uk \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.