All of lore.kernel.org
 help / color / mirror / Atom feed
* RFC: Creation of virtual bus, hook-up of Xen devices
@ 2005-02-01 20:30 Jeremy Katz
  2005-02-01 22:49 ` Christian Limpach
  0 siblings, 1 reply; 11+ messages in thread
From: Jeremy Katz @ 2005-02-01 20:30 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]

For many purposes on a Linux system, it is required to have devices
export themselves via the device infrastructure (exposed via sysfs) to
allow for reasonable user-space probing and discovery of available
devices.  This is especially useful/necessary for things like installing
to guest systems.

The attached patch is a first pass at starting to get something along
these lines for Xen devices to hook into.  Provided sysfs bits
are /sys/bus/x/devices/netN for each xen_net device
and /sys/bus/x/drivers/xen_{net,blk} as points for the xen_net and
xen_blk drivers.  I haven't actually really hooked up the xen_blk
devices yet as I think that getting some of the base infrastructure
committed first will make that a little better.  Also, there's
definitely more that can be done in terms of cleaning up netfront to
better take advantage of the fact that there's a struct device
associated with each net_device instead of keeping track of all of the
generic bits in the net_private struct.

Comments? 

Jeremy

[-- Attachment #2: xen-xbus.patch --]
[-- Type: text/x-patch, Size: 14994 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/02/01 13:57:41-05:00 katzj@redhat.com 
#   Hook up netfront devices to x bus.
# 
# linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c
#   2005/02/01 13:57:39-05:00 katzj@redhat.com +41 -27
#   Register netfront device with virtual bus.  Hook everything up so that
#   network devices show up under /sys/bus/x/devices with driver links, etc
# 
# ChangeSet
#   2005/02/01 13:56:13-05:00 katzj@redhat.com 
#   Register block frontend with xbus
# 
# linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c
#   2005/02/01 13:56:12-05:00 katzj@redhat.com +10 -1
#   Basic registration with xbus
# 
# ChangeSet
#   2005/02/01 13:53:31-05:00 katzj@redhat.com 
#   First pass at creating xbus virtual bus for Xen devices to sit 
#   on.  Heavily inspired by the vio code for ppc64. 
#   
#   Lets devices appear under /sys/bus/x 
# 
# linux-2.6.10-xen-sparse/include/asm-xen/xbus.h
#   2005/02/01 13:53:22-05:00 katzj@redhat.com +45 -0
# 
# linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c
#   2005/02/01 13:53:22-05:00 katzj@redhat.com +201 -0
# 
# linux-2.6.10-xen-sparse/include/asm-xen/xbus.h
#   2005/02/01 13:53:22-05:00 katzj@redhat.com +0 -0
#   BitKeeper file /home/katzj/cvs/xen/xen-katzj/linux-2.6.10-xen-sparse/include/asm-xen/xbus.h
# 
# linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c
#   2005/02/01 13:53:22-05:00 katzj@redhat.com +0 -0
#   BitKeeper file /home/katzj/cvs/xen/xen-katzj/linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c
# 
# linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile
#   2005/02/01 13:53:22-05:00 katzj@redhat.com +1 -1
#   Add build of xbus
# 
diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile b/linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile
--- a/linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile	2005-02-01 14:50:53 -05:00
+++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile	2005-02-01 14:50:53 -05:00
@@ -12,4 +12,4 @@
 extra-y += vmlinux.lds
 
 obj-y	:= ctrl_if.o evtchn.o fixup.o reboot.o xen_proc.o \
-           gnttab.o skbuff.o devmem.o smp.o
+           gnttab.o skbuff.o devmem.o smp.o xbus.o
diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c b/linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/xbus.c	2005-02-01 14:50:53 -05:00
@@ -0,0 +1,201 @@
+/*
+ * X IO Bus for Xen
+ *
+ *  Heavily based on arch/ppc64/kernel/vio.c
+ *
+ *    Copyright (c) 2005 Red Hat, Inc.
+ *     Jeremy Katz <katzj@redhat.com>
+ *
+ *      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.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <asm-xen/xbus.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+
+static struct xdev *xbus_dev;
+
+static int xbus_probe(struct device *dev)
+{
+    struct xdev *xdev = to_xdev(dev);
+    struct xdriver *xdrv = to_xdriver(dev->driver);
+
+    if (!xdrv->probe)
+        return -ENODEV;
+
+    /* match the device */
+    return xdrv->probe(xdev, xdev->type);
+}
+
+static int xbus_match(struct device *dev, struct device_driver *drv)
+{
+    const struct xdev *xdev = to_xdev(dev);
+    struct xdriver *xdrv = to_xdriver(drv);
+
+    return !strcmp(xdrv->type, xdev->type);
+}
+
+/**
+ * x_register_driver: - Register a new driver
+ * @drv:	The xdriver structure to be registered.
+ */
+int x_register_driver(struct xdriver *xdrv)
+{
+    printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
+           xdrv->name);
+
+    /* fill in 'struct driver' fields */
+    xdrv->driver.name = xdrv->name;
+    xdrv->driver.bus = &xbus_type;
+    xdrv->driver.probe = &xbus_probe;
+    xdrv->driver.remove = NULL;
+    
+    return driver_register(&xdrv->driver);
+}
+EXPORT_SYMBOL(x_register_driver);
+
+static void __devinit xdev_release(struct device *dev)
+{
+    kfree(to_xdev(dev));
+}
+
+void __devinit x_unregister_device(struct xdev *dev)
+{
+    device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(x_unregister_device);
+
+static struct xdev *__init x_register_device (char *type, unsigned int handle) {
+    struct xdev *dev;
+    int err;
+
+    dev = kmalloc(sizeof(struct xdev), GFP_KERNEL);
+    if (!dev)
+        return NULL;
+    memset(dev, 0, sizeof(struct xdev));
+
+    snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, handle);
+    dev->name = dev->dev.bus_id;
+    dev->type = type;
+    dev->handle = handle;
+
+    /* init generic struct fields */
+    dev->dev.parent = &xbus_dev->dev;
+    dev->dev.bus = &xbus_type;
+    dev->dev.release = xdev_release;
+
+    /* register with device framework */
+    if ((err = device_register(&dev->dev))) {
+        printk(KERN_ERR "%s: failed to register device %s: %d\n",
+               __FUNCTION__, dev->dev.bus_id, err);
+        return NULL;
+    }
+    
+    return dev;
+}
+
+static int num_intfs = 0;
+
+static void count_netif_rxmsg_handler(ctrl_msg_t *msg, unsigned long id)
+{
+    if (msg->subtype == CMSG_NETIF_FE_INTERFACE_STATUS) {
+        netif_fe_interface_status_t *n;
+
+        n = (netif_fe_interface_status_t *) &msg->msg[0];
+        x_register_device("net", n->handle);
+        num_intfs++;
+    } 
+    msg->length = 0;
+    ctrl_if_send_response(msg);
+}
+
+/**
+ * xunregister_driver - Remove registration of driver.
+ * @driver:	The xdriver struct to be removed form registration
+ */
+void x_unregister_driver(struct xdriver *xdrv)
+{
+	driver_unregister(&xdrv->driver);
+}
+EXPORT_SYMBOL(x_unregister_driver);
+
+/* FIXME: this is ugly in that we have to do the netif specific bits
+ * in what should be generic code.  
+ */
+static void register_net_devs(void)
+{
+    int err;
+    ctrl_msg_t cmsg = {
+        .type = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
+        .length = sizeof(netif_fe_driver_status_t)
+    };
+    int i;
+    netif_fe_driver_status_t *msg = (void*)cmsg.msg;
+    msg->status = (NETIF_DRIVER_STATUS_UP);
+    
+    (void)ctrl_if_register_receiver(CMSG_NETIF_FE, count_netif_rxmsg_handler,
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+    
+    
+    err = ctrl_if_send_message_block(&cmsg, NULL, 0, 
+                                     TASK_UNINTERRUPTIBLE);
+    if (!err) {
+        for (i=0; i < 5; i++) {
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(10);
+        }
+    }
+                
+    ctrl_if_unregister_receiver(CMSG_NETIF_FE, count_netif_rxmsg_handler);
+    msg->status = (NETIF_DRIVER_STATUS_DOWN);
+    err = ctrl_if_send_message_block(&cmsg, NULL, 0, 
+                                     TASK_UNINTERRUPTIBLE);
+
+}
+
+static int __init xbus_init(void)
+{
+    int err = 0;
+
+    err = bus_register(&xbus_type);
+    if (err) {
+        printk(KERN_ERR "failed to register x bus\n");
+        return err;
+    }
+
+    xbus_dev = kmalloc(sizeof(struct xdev), GFP_KERNEL);
+    if (!xbus_dev)
+        return 1;
+    memset(xbus_dev, 0, sizeof(struct xdev));
+    strcpy(xbus_dev->dev.bus_id, "x");
+    
+    err = device_register(&xbus_dev->dev);
+    if (err) {
+        printk(KERN_WARNING "%s: device_register returned %i\n", 
+               __FUNCTION__, err);
+        kfree(xbus_dev);
+        return err;
+    }
+    
+    register_net_devs();
+    
+    return 0;
+}
+
+__initcall(xbus_init);
+
+struct bus_type xbus_type = {
+    .name = "x",
+    .match = &xbus_match,
+};
+
+EXPORT_SYMBOL(xbus_type);
diff -Nru a/linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c	2005-02-01 14:50:53 -05:00
+++ b/linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c	2005-02-01 14:50:53 -05:00
@@ -46,6 +46,7 @@
 #include <scsi/scsi.h>
 #include <asm-xen/ctrl_if.h>
 #include <asm-xen/evtchn.h>
+#include <asm-xen/xbus.h>
 
 typedef unsigned char byte; /* from linux/ide.h */
 
@@ -1350,6 +1351,14 @@
     return err;
 }
 
+static char blkfront_driver_name[] = "xen_blk";
+static char blkfront_driver_type[] = "blk";
+
+static struct xdriver xen_blkfront_driver = {
+    .name        = (char *)blkfront_driver_name,
+    .type = blkfront_driver_type,
+};
+
 int __init xlblk_init(void)
 {
     int i;
@@ -1370,7 +1379,7 @@
 
     wait_for_blkif();
 
-    return 0;
+    return x_register_driver(&xen_blkfront_driver);    
 }
 
 void blkdev_suspend(void)
diff -Nru a/linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c	2005-02-01 14:50:53 -05:00
+++ b/linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c	2005-02-01 14:50:53 -05:00
@@ -46,6 +46,7 @@
 #include <asm-xen/ctrl_if.h>
 #include <asm-xen/xen-public/io/netif.h>
 #include <asm-xen/balloon.h>
+#include <asm-xen/xbus.h>
 #include <asm/page.h>
 
 #include <net/arp.h>
@@ -93,7 +94,8 @@
 struct net_private
 {
     struct list_head list;
-    struct net_device *dev;
+    struct net_device *netdev;
+    struct device *dev;
 
     struct net_device_stats stats;
     NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
@@ -175,7 +177,7 @@
     {
         np = list_entry(ent, struct net_private, list);
         if ( np->handle == handle )
-            return np->dev;
+            return np->netdev;
     }
     return NULL;
 }
@@ -710,7 +712,7 @@
 {
     struct net_private *np = netdev_priv(dev);
     np->user_state = UST_CLOSED;
-    netif_stop_queue(np->dev);
+    netif_stop_queue(dev);
     return 0;
 }
 
@@ -856,14 +858,14 @@
     /* Stop old i/f to prevent errors whilst we rebuild the state. */
     spin_lock_irq(&np->tx_lock);
     spin_lock(&np->rx_lock);
-    netif_stop_queue(np->dev);
+    netif_stop_queue(np->netdev);
     /* np->backend_state = BEST_DISCONNECTED; */
     spin_unlock(&np->rx_lock);
     spin_unlock_irq(&np->tx_lock);
     
     /* Free resources. */
     if(np->tx != NULL){
-        free_irq(np->irq, np->dev);
+        free_irq(np->irq, np->netdev);
         unbind_evtchn_from_irq(np->evtchn);
         free_page((unsigned long)np->tx);
         free_page((unsigned long)np->rx);
@@ -936,7 +938,7 @@
 vif_connect(
     struct net_private *np, netif_fe_interface_status_t *status)
 {
-    struct net_device *dev = np->dev;
+    struct net_device *dev = np->netdev;
     memcpy(dev->dev_addr, status->mac, ETH_ALEN);
     network_connect(dev, status);
     np->evtchn = status->evtchn;
@@ -953,7 +955,7 @@
  * @param val return parameter for created device
  * @return 0 on success, error code otherwise
  */
-static int create_netdev(int handle, struct net_device **val)
+static struct net_device * __init create_netdev(int handle, struct device *xdev)
 {
     int i, err = 0;
     struct net_device *dev = NULL;
@@ -995,15 +997,16 @@
         printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
         goto exit;
     }
-    np->dev = dev;
+    np->dev = xdev;
+    np->netdev = dev;
+    SET_MODULE_OWNER(dev);
+    SET_NETDEV_DEV(dev, xdev);
     list_add(&np->list, &dev_list);
 
   exit:
     if ( (err != 0) && (dev != NULL ) )
         kfree(dev);
-    else if ( val != NULL )
-        *val = dev;
-    return err;
+    return dev;
 }
 
 /* Get the target interface for a status message.
@@ -1036,13 +1039,6 @@
     if ( status->status == NETIF_INTERFACE_STATUS_CHANGED )
         goto exit;
 
-    /* It's a new interface in a good state - create it. */
-    DPRINTK("> create device...\n");
-    if ( (err = create_netdev(status->handle, &dev)) != 0 )
-        goto exit;
-
-    netctrl.interface_n++;
-
   exit:
     if ( np != NULL )
         *np = ((dev && !err) ? netdev_priv(dev) : NULL);
@@ -1056,8 +1052,8 @@
     int err = 0;
     struct net_private *np = NULL;
     
-    DPRINTK("> status=%s handle=%d\n",
-            status_name[status->status], status->handle);
+    DPRINTK("> status=%s handle=%d evtchn=%d\n",
+            status_name[status->status], status->handle, status->evtchn);
 
     if ( (err = target_vif(status, &np)) != 0 )
     {
@@ -1277,7 +1273,7 @@
     list_for_each ( ent, &dev_list )
     {
         np = list_entry(ent, struct net_private, list);
-        if ( np->dev == dev )
+        if ( np->netdev == dev )
             (void)send_fake_arp(dev);
     }
         
@@ -1291,6 +1287,28 @@
     .priority       = 0
 };
 
+static int xen_net_probe(struct xdev *xdev, const char * id) {
+    struct net_device *dev;
+    dev = create_netdev(xdev->handle, &xdev->dev);
+    if (dev == NULL) {
+        /* should remove the device here */
+        return 1;
+    } 
+
+    netctrl.interface_n++;
+    return 0;
+}
+
+static char netfront_driver_name[] = "xen_net";
+static char netfront_driver_type[] = "net";
+
+static struct xdriver xen_netfront_driver = {
+    .name        = (char *)netfront_driver_name,
+    .type = netfront_driver_type,
+    .probe = xen_net_probe,
+};
+
+
 static int __init netif_init(void)
 {
     int err = 0;
@@ -1306,18 +1324,14 @@
     (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
                                     CALLBACK_IN_BLOCKING_CONTEXT);
     send_driver_status(1);
-    err = probe_interfaces();
-    if ( err )
-        ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
 
-    DPRINTK("< err=%d\n", err);
-    return err;
+    return x_register_driver(&xen_netfront_driver);
 }
 
 static void vif_suspend(struct net_private *np)
 {
     /* Avoid having tx/rx stuff happen until we're ready. */
-    free_irq(np->irq, np->dev);
+    free_irq(np->irq, np->netdev);
     unbind_evtchn_from_irq(np->evtchn);
 }
 
diff -Nru a/linux-2.6.10-xen-sparse/include/asm-xen/xbus.h b/linux-2.6.10-xen-sparse/include/asm-xen/xbus.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.10-xen-sparse/include/asm-xen/xbus.h	2005-02-01 14:50:53 -05:00
@@ -0,0 +1,45 @@
+#ifndef _ASM_XBUS_H
+#define _ASM_XBUS_H
+
+#include <linux/config.h>
+#include <linux/device.h>
+
+struct xdev {
+    char * name;
+    char * type;
+
+    unsigned int irq;
+    unsigned int evtchn;
+    unsigned int handle;
+
+    struct device dev;
+};
+
+struct xdriver {
+    char * name;
+    char * type;
+    int (*probe) (struct xdev *dev, const char * id);
+    int (*remove) (struct xdev *dev);
+    unsigned long driver_data;
+
+    struct device_driver driver;
+};
+
+
+extern struct bus_type xbus_type;
+
+int xregister_driver(struct xdriver *xdrv);
+
+static inline struct xdev *to_xdev(struct device *dev)
+{
+	return container_of(dev, struct xdev, dev);
+}
+
+static inline struct xdriver *to_xdriver(struct device_driver *drv)
+{
+	return container_of(drv, struct xdriver, driver);
+}
+
+
+
+#endif

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2005-02-12 15:24 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-01 20:30 RFC: Creation of virtual bus, hook-up of Xen devices Jeremy Katz
2005-02-01 22:49 ` Christian Limpach
2005-02-01 23:09   ` Jeremy Katz
2005-02-01 23:53     ` Ian Pratt
2005-02-02  1:13       ` Jeremy Katz
2005-02-02  1:06     ` Christian Limpach
2005-02-02  2:20       ` Jeremy Katz
2005-02-10  0:17         ` Christian Limpach
2005-02-10 20:52           ` Jeremy Katz
2005-02-12  9:10             ` Andrew Warfield
2005-02-12 15:24               ` Mark Williamson

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.