mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.1159.56.1 (412f28f2oorf9i_6akPMKOUodxF7qg)
Towards new device-interface setup code for the frontend drivers. Added a synchronous send-and-get-response call to the control interface API. Modified and extended the domain-controller messaging protocol.
This commit is contained in:
1 parent
004d796c34
commit
dcb731aad7
6 files changed
+143
-36
No files matched your search
@@ -201,7 +201,8 @@ static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id,
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int ctrl_if_send_message_noblock(
|
||||
int
|
||||
ctrl_if_send_message_noblock(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_handler_t hnd,
|
||||
unsigned long id)
|
||||
@@ -245,7 +246,8 @@ int ctrl_if_send_message_noblock(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctrl_if_send_message_block(
|
||||
int
|
||||
ctrl_if_send_message_block(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_handler_t hnd,
|
||||
unsigned long id,
|
||||
@@ -280,7 +282,59 @@ int ctrl_if_send_message_block(
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ctrl_if_enqueue_space_callback(struct tq_struct *task)
|
||||
/* Allow a reponse-callback handler to find context of a blocked requester. */
|
||||
struct rsp_wait {
|
||||
ctrl_msg_t *msg; /* Buffer for the response message. */
|
||||
struct task_struct *task; /* The task that is blocked on the response. */
|
||||
int done; /* Indicate to 'task' that response is rcv'ed. */
|
||||
};
|
||||
|
||||
static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
struct rsp_wait *wait = (struct rsp_wait *)id;
|
||||
struct task_struct *task = wait->task;
|
||||
|
||||
memcpy(wait->msg, msg, sizeof(*msg));
|
||||
wmb();
|
||||
wait->done = 1;
|
||||
|
||||
wake_up_process(task);
|
||||
}
|
||||
|
||||
int
|
||||
ctrl_if_send_message_and_get_response(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_t *rmsg,
|
||||
long wait_state)
|
||||
{
|
||||
struct rsp_wait wait;
|
||||
int rc;
|
||||
|
||||
wait.msg = rmsg;
|
||||
wait.done = 0;
|
||||
wait.task = current;
|
||||
|
||||
if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response,
|
||||
(unsigned long)&wait,
|
||||
wait_state)) != 0 )
|
||||
return rc;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
/* NB. Can't easily support TASK_INTERRUPTIBLE here. */
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
if ( wait.done )
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ctrl_if_enqueue_space_callback(
|
||||
struct tq_struct *task)
|
||||
{
|
||||
control_if_t *ctrl_if = get_ctrl_if();
|
||||
|
||||
@@ -299,7 +353,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task)
|
||||
return TX_FULL(ctrl_if);
|
||||
}
|
||||
|
||||
void ctrl_if_send_response(ctrl_msg_t *msg)
|
||||
void
|
||||
ctrl_if_send_response(
|
||||
ctrl_msg_t *msg)
|
||||
{
|
||||
control_if_t *ctrl_if = get_ctrl_if();
|
||||
unsigned long flags;
|
||||
@@ -327,7 +383,8 @@ void ctrl_if_send_response(ctrl_msg_t *msg)
|
||||
ctrl_if_notify_controller();
|
||||
}
|
||||
|
||||
int ctrl_if_register_receiver(
|
||||
int
|
||||
ctrl_if_register_receiver(
|
||||
u8 type,
|
||||
ctrl_msg_handler_t hnd,
|
||||
unsigned int flags)
|
||||
@@ -361,7 +418,10 @@ int ctrl_if_register_receiver(
|
||||
return !inuse;
|
||||
}
|
||||
|
||||
void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd)
|
||||
void
|
||||
ctrl_if_unregister_receiver(
|
||||
u8 type,
|
||||
ctrl_msg_handler_t hnd)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
@@ -814,9 +814,10 @@ static void netif_driver_status_change(
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
DPRINTK("> nr_interfaces=%d\n", status->nr_interfaces);
|
||||
DPRINTK("> max_handle=%d\n", status->max_handle);
|
||||
|
||||
netctrl.interface_n = status->nr_interfaces;
|
||||
/* XXX FIXME: Abuse of 'max_handle' as interface count. */
|
||||
netctrl.interface_n = status->max_handle;
|
||||
netctrl.connected_n = 0;
|
||||
|
||||
for ( i = 0; i < netctrl.interface_n; i++ )
|
||||
@@ -913,7 +914,7 @@ static int __init netif_init(void)
|
||||
cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
|
||||
cmsg.length = sizeof(netif_fe_driver_status_changed_t);
|
||||
st.status = NETIF_DRIVER_STATUS_UP;
|
||||
st.nr_interfaces = 0;
|
||||
st.max_handle = 0;
|
||||
memcpy(cmsg.msg, &st, sizeof(st));
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
@@ -999,7 +1000,7 @@ void netif_resume(void)
|
||||
cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
|
||||
cmsg.length = sizeof(netif_fe_driver_status_changed_t);
|
||||
st.status = NETIF_DRIVER_STATUS_UP;
|
||||
st.nr_interfaces = 0;
|
||||
st.max_handle = 0;
|
||||
memcpy(cmsg.msg, &st, sizeof(st));
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,8 @@ typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long);
|
||||
* function returns.
|
||||
* 2. If @hnd is NULL then no callback is executed.
|
||||
*/
|
||||
int ctrl_if_send_message_noblock(
|
||||
int
|
||||
ctrl_if_send_message_noblock(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_handler_t hnd,
|
||||
unsigned long id);
|
||||
@@ -52,12 +53,23 @@ int ctrl_if_send_message_noblock(
|
||||
* function returns.
|
||||
* 2. If @hnd is NULL then no callback is executed.
|
||||
*/
|
||||
int ctrl_if_send_message_block(
|
||||
int
|
||||
ctrl_if_send_message_block(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_handler_t hnd,
|
||||
unsigned long id,
|
||||
long wait_state);
|
||||
|
||||
/*
|
||||
* Send @msg to the domain controller. Block until the response is received,
|
||||
* and then copy it into the provided buffer, @rmsg.
|
||||
*/
|
||||
int
|
||||
ctrl_if_send_message_and_get_response(
|
||||
ctrl_msg_t *msg,
|
||||
ctrl_msg_t *rmsg,
|
||||
long wait_state);
|
||||
|
||||
/*
|
||||
* Request a callback when there is /possibly/ space to immediately send a
|
||||
* message to the domain controller. This function returns 0 if there is
|
||||
@@ -65,7 +77,9 @@ int ctrl_if_send_message_block(
|
||||
* still be executed. If this function returns 1 then the callback /will/ be
|
||||
* executed when space becomes available.
|
||||
*/
|
||||
int ctrl_if_enqueue_space_callback(struct tq_struct *task);
|
||||
int
|
||||
ctrl_if_enqueue_space_callback(
|
||||
struct tq_struct *task);
|
||||
|
||||
/*
|
||||
* Send a response (@msg) to a message from the domain controller. This will
|
||||
@@ -74,7 +88,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task);
|
||||
* 1. The @msg is copied and so can be freed after this function returns.
|
||||
* 2. The @msg may be the original request message, modified in-place.
|
||||
*/
|
||||
void ctrl_if_send_response(ctrl_msg_t *msg);
|
||||
void
|
||||
ctrl_if_send_response(
|
||||
ctrl_msg_t *msg);
|
||||
|
||||
/*
|
||||
* Register a receiver for typed messages from the domain controller. The
|
||||
@@ -93,7 +109,9 @@ int ctrl_if_register_receiver(
|
||||
* Unregister a receiver for typed messages from the domain controller. The
|
||||
* handler (@hnd) will not be executed after this function returns.
|
||||
*/
|
||||
void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd);
|
||||
void
|
||||
ctrl_if_unregister_receiver(
|
||||
u8 type, ctrl_msg_handler_t hnd);
|
||||
|
||||
/* Suspend/resume notifications. */
|
||||
void ctrl_if_suspend(void);
|
||||
|
||||
@@ -325,10 +325,10 @@ static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
|
||||
switch ( TYPE(xum->msg.type, xum->msg.subtype) )
|
||||
{
|
||||
case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
|
||||
P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
|
||||
P2C(blkif_fe_driver_status_changed_t, max_handle, u32);
|
||||
break;
|
||||
case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
|
||||
P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
|
||||
P2C(netif_fe_driver_status_changed_t, max_handle, u32);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
|
||||
return dict;
|
||||
case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
|
||||
C2P(netif_fe_driver_status_changed_t, status, Int, Long);
|
||||
C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
|
||||
C2P(netif_fe_driver_status_changed_t, max_handle, Int, Long);
|
||||
return dict;
|
||||
case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
|
||||
C2P(netif_fe_interface_connect_t, handle, Int, Long);
|
||||
@@ -630,7 +630,7 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
|
||||
break;
|
||||
case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
|
||||
P2C(netif_fe_driver_status_changed_t, status, u32);
|
||||
P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
|
||||
P2C(netif_fe_driver_status_changed_t, max_handle, u32);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -333,8 +333,9 @@ class NetifController(controller.SplitController):
|
||||
def recv_fe_driver_status_changed(self, msg, req):
|
||||
if not req: return
|
||||
msg = packMsg('netif_fe_driver_status_changed_t',
|
||||
{ 'status' : NETIF_DRIVER_STATUS_UP,
|
||||
'nr_interfaces' : len(self.devices) })
|
||||
{ 'status' : NETIF_DRIVER_STATUS_UP,
|
||||
## FIXME: max_handle should be max active interface id
|
||||
'max_handle' : len(self.devices) })
|
||||
self.writeRequest(msg)
|
||||
for dev in self.devices.values():
|
||||
dev.attach_fe_device()
|
||||
|
||||
@@ -76,6 +76,7 @@ typedef struct {
|
||||
#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED 32
|
||||
#define CMSG_BLKIF_FE_INTERFACE_CONNECT 33
|
||||
#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT 34
|
||||
#define CMSG_BLKIF_FE_INTERFACE_QUERY 35
|
||||
|
||||
/* These are used by both front-end and back-end drivers. */
|
||||
#define blkif_vdev_t u16
|
||||
@@ -87,7 +88,7 @@ typedef struct {
|
||||
* Notify a guest about a status change on one of its block interfaces.
|
||||
* If the interface is DESTROYED or DOWN then the interface is disconnected:
|
||||
* 1. The shared-memory frame is available for reuse.
|
||||
* 2. Any unacknowledged messgaes pending on the interface were dropped.
|
||||
* 2. Any unacknowledged messages pending on the interface were dropped.
|
||||
*/
|
||||
#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
|
||||
#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
|
||||
@@ -103,10 +104,13 @@ typedef struct {
|
||||
* CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
|
||||
* Notify the domain controller that the front-end driver is DOWN or UP.
|
||||
* When the driver goes DOWN then the controller will send no more
|
||||
* status-change notifications. When the driver comes UP then the controller
|
||||
* will send a notification for each interface that currently exists.
|
||||
* status-change notifications.
|
||||
* If the driver goes DOWN while interfaces are still UP, the domain
|
||||
* will automatically take the interfaces DOWN.
|
||||
*
|
||||
* NB. The controller should not send an INTERFACE_STATUS_CHANGED message
|
||||
* for interfaces that are active when it receives an UP notification. We
|
||||
* expect that the frontend driver will query those interfaces itself.
|
||||
*/
|
||||
#define BLKIF_DRIVER_STATUS_DOWN 0
|
||||
#define BLKIF_DRIVER_STATUS_UP 1
|
||||
@@ -114,11 +118,8 @@ typedef struct {
|
||||
/* IN */
|
||||
u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */
|
||||
/* OUT */
|
||||
/*
|
||||
* Tells driver how many interfaces it should expect to immediately
|
||||
* receive notifications about.
|
||||
*/
|
||||
u32 nr_interfaces; /* 4 */
|
||||
/* Driver should query interfaces [0..max_handle]. */
|
||||
u32 max_handle; /* 4 */
|
||||
} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
|
||||
|
||||
/*
|
||||
@@ -142,6 +143,18 @@ typedef struct {
|
||||
u32 handle; /* 0 */
|
||||
} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
|
||||
|
||||
/*
|
||||
* CMSG_BLKIF_FE_INTERFACE_QUERY:
|
||||
*/
|
||||
typedef struct {
|
||||
/* IN */
|
||||
u32 handle; /* 0 */
|
||||
/* OUT */
|
||||
u32 status; /* 4 */
|
||||
u16 evtchn; /* 8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
|
||||
domid_t domid; /* 10: status != BLKIF_INTERFACE_STATUS_DESTROYED */
|
||||
} PACKED blkif_fe_interface_query_t; /* 12 bytes */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* BLOCK-INTERFACE BACKEND DEFINITIONS
|
||||
@@ -332,6 +345,7 @@ typedef struct {
|
||||
#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED 32
|
||||
#define CMSG_NETIF_FE_INTERFACE_CONNECT 33
|
||||
#define CMSG_NETIF_FE_INTERFACE_DISCONNECT 34
|
||||
#define CMSG_NETIF_FE_INTERFACE_QUERY 35
|
||||
|
||||
/*
|
||||
* CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
|
||||
@@ -355,10 +369,13 @@ typedef struct {
|
||||
* CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
|
||||
* Notify the domain controller that the front-end driver is DOWN or UP.
|
||||
* When the driver goes DOWN then the controller will send no more
|
||||
* status-change notifications. When the driver comes UP then the controller
|
||||
* will send a notification for each interface that currently exists.
|
||||
* status-change notifications.
|
||||
* If the driver goes DOWN while interfaces are still UP, the domain
|
||||
* will automatically take the interfaces DOWN.
|
||||
*
|
||||
* NB. The controller should not send an INTERFACE_STATUS_CHANGED message
|
||||
* for interfaces that are active when it receives an UP notification. We
|
||||
* expect that the frontend driver will query those interfaces itself.
|
||||
*/
|
||||
#define NETIF_DRIVER_STATUS_DOWN 0
|
||||
#define NETIF_DRIVER_STATUS_UP 1
|
||||
@@ -366,11 +383,8 @@ typedef struct {
|
||||
/* IN */
|
||||
u32 status; /* 0: NETIF_DRIVER_STATUS_??? */
|
||||
/* OUT */
|
||||
/*
|
||||
* Tells driver how many interfaces it should expect to immediately
|
||||
* receive notifications about.
|
||||
*/
|
||||
u32 nr_interfaces; /* 4 */
|
||||
/* Driver should query interfaces [0..max_handle]. */
|
||||
u32 max_handle; /* 4 */
|
||||
} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
|
||||
|
||||
/*
|
||||
@@ -396,6 +410,19 @@ typedef struct {
|
||||
u32 handle; /* 0 */
|
||||
} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
|
||||
|
||||
/*
|
||||
* CMSG_NETIF_FE_INTERFACE_QUERY:
|
||||
*/
|
||||
typedef struct {
|
||||
/* IN */
|
||||
u32 handle; /* 0 */
|
||||
/* OUT */
|
||||
u32 status; /* 4 */
|
||||
u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */
|
||||
u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
|
||||
domid_t domid; /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */
|
||||
} PACKED netif_fe_interface_query_t; /* 18 bytes */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NETWORK-INTERFACE BACKEND DEFINITIONS
|
||||
|
||||