* [PATCH][9/17] USB virt 2.6 split driver---gateway
@ 2005-11-21 13:19 harry
0 siblings, 0 replies; only message in thread
From: harry @ 2005-11-21 13:19 UTC (permalink / raw)
To: xen-devel
[-- 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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-11-21 13:19 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-21 13:19 [PATCH][9/17] USB virt 2.6 split driver---gateway harry
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.