diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-18 10:23:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-18 10:23:37 -0700 |
commit | 31bdc5dc7666aa2fe04c626cea30fe3c20cf481c (patch) | |
tree | a1a78a39379e081e9982c3273a71b4e93e8c1fd0 | |
parent | 5cc97bf2d8eaa6cab60727c3eba3e85e29062669 (diff) | |
parent | a5f8967e171a6fa27da8e6d06d3ef85f7fed43c1 (diff) | |
download | op-kernel-dev-31bdc5dc7666aa2fe04c626cea30fe3c20cf481c.zip op-kernel-dev-31bdc5dc7666aa2fe04c626cea30fe3c20cf481c.tar.gz |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
[SPARC64]: Set vio->desc_buf to NULL after freeing.
[SPARC]: Mark sparc and sparc64 as not having virt_to_bus
[SPARC64]: Fix reset handling in VNET driver.
[SPARC64]: Handle reset events in vio_link_state_change().
[SPARC64]: Handle LDC resets properly in domain-services driver.
[SPARC64]: Massively simplify VIO device layer and support hot add/remove.
[SPARC64]: Simplify VNET probing.
[SPARC64]: Simplify VDC device probing.
[SPARC64]: Add basic infrastructure for MD add/remove notification.
-rw-r--r-- | arch/sparc/Kconfig | 3 | ||||
-rw-r--r-- | arch/sparc64/Kconfig | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/ds.c | 19 | ||||
-rw-r--r-- | arch/sparc64/kernel/mdesc.c | 78 | ||||
-rw-r--r-- | arch/sparc64/kernel/vio.c | 94 | ||||
-rw-r--r-- | arch/sparc64/kernel/viohs.c | 30 | ||||
-rw-r--r-- | drivers/block/sunvdc.c | 97 | ||||
-rw-r--r-- | drivers/net/sunvnet.c | 260 | ||||
-rw-r--r-- | drivers/net/sunvnet.h | 4 | ||||
-rw-r--r-- | include/asm-sparc64/io.h | 5 | ||||
-rw-r--r-- | include/asm-sparc64/mdesc.h | 10 | ||||
-rw-r--r-- | include/asm-sparc64/vio.h | 2 |
12 files changed, 344 insertions, 261 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 73df711..603d83a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -21,6 +21,9 @@ config GENERIC_ISA_DMA bool default y +config ARCH_NO_VIRT_TO_BUS + def_bool y + source "init/Kconfig" menu "General machine setup" diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index b84b6af..df6ee71 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -62,6 +62,9 @@ config AUDIT_ARCH bool default y +config ARCH_NO_VIRT_TO_BUS + def_bool y + choice prompt "Kernel page size" default SPARC64_PAGE_SIZE_8KB diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index ba01533..fa1f04d 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c @@ -1013,6 +1013,19 @@ static void ds_up(struct ds_info *dp) dp->hs_state = DS_HS_START; } +static void ds_reset(struct ds_info *dp) +{ + int i; + + dp->hs_state = 0; + + for (i = 0; i < ARRAY_SIZE(ds_states); i++) { + struct ds_cap_state *cp = &ds_states[i]; + + cp->state = CAP_STATE_UNKNOWN; + } +} + static void ds_event(void *arg, int event) { struct ds_info *dp = arg; @@ -1028,6 +1041,12 @@ static void ds_event(void *arg, int event) return; } + if (event == LDC_EVENT_RESET) { + ds_reset(dp); + spin_unlock_irqrestore(&ds_lock, flags); + return; + } + if (event != LDC_EVENT_DATA_READY) { printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); spin_unlock_irqrestore(&ds_lock, flags); diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index de5310f..302ba5e 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c @@ -137,7 +137,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size) sizeof(struct mdesc_hdr) + mdesc_size); - base = kmalloc(handle_size + 15, GFP_KERNEL); + base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL); if (base) { struct mdesc_handle *hp; unsigned long addr; @@ -214,18 +214,83 @@ void mdesc_release(struct mdesc_handle *hp) } EXPORT_SYMBOL(mdesc_release); +static DEFINE_MUTEX(mdesc_mutex); +static struct mdesc_notifier_client *client_list; + +void mdesc_register_notifier(struct mdesc_notifier_client *client) +{ + u64 node; + + mutex_lock(&mdesc_mutex); + client->next = client_list; + client_list = client; + + mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name) + client->add(cur_mdesc, node); + + mutex_unlock(&mdesc_mutex); +} + +/* Run 'func' on nodes which are in A but not in B. */ +static void invoke_on_missing(const char *name, + struct mdesc_handle *a, + struct mdesc_handle *b, + void (*func)(struct mdesc_handle *, u64)) +{ + u64 node; + + mdesc_for_each_node_by_name(a, node, name) { + const u64 *id = mdesc_get_property(a, node, "id", NULL); + int found = 0; + u64 fnode; + + mdesc_for_each_node_by_name(b, fnode, name) { + const u64 *fid = mdesc_get_property(b, fnode, + "id", NULL); + + if (*id == *fid) { + found = 1; + break; + } + } + if (!found) + func(a, node); + } +} + +static void notify_one(struct mdesc_notifier_client *p, + struct mdesc_handle *old_hp, + struct mdesc_handle *new_hp) +{ + invoke_on_missing(p->node_name, old_hp, new_hp, p->remove); + invoke_on_missing(p->node_name, new_hp, old_hp, p->add); +} + +static void mdesc_notify_clients(struct mdesc_handle *old_hp, + struct mdesc_handle *new_hp) +{ + struct mdesc_notifier_client *p = client_list; + + while (p) { + notify_one(p, old_hp, new_hp); + p = p->next; + } +} + void mdesc_update(void) { unsigned long len, real_len, status; struct mdesc_handle *hp, *orig_hp; unsigned long flags; + mutex_lock(&mdesc_mutex); + (void) sun4v_mach_desc(0UL, 0UL, &len); hp = mdesc_alloc(len, &kmalloc_mdesc_memops); if (!hp) { printk(KERN_ERR "MD: mdesc alloc fails\n"); - return; + goto out; } status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); @@ -234,18 +299,25 @@ void mdesc_update(void) status); atomic_dec(&hp->refcnt); mdesc_free(hp); - return; + goto out; } spin_lock_irqsave(&mdesc_lock, flags); orig_hp = cur_mdesc; cur_mdesc = hp; + spin_unlock_irqrestore(&mdesc_lock, flags); + mdesc_notify_clients(orig_hp, hp); + + spin_lock_irqsave(&mdesc_lock, flags); if (atomic_dec_and_test(&orig_hp->refcnt)) mdesc_free(orig_hp); else list_add(&orig_hp->list, &mdesc_zombie_list); spin_unlock_irqrestore(&mdesc_lock, flags); + +out: + mutex_unlock(&mdesc_mutex); } static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 49569b4..8d3cc4f 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -201,10 +201,11 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, struct device *parent) { - const char *type, *compat; + const char *type, *compat, *bus_id_name; struct device_node *dp; struct vio_dev *vdev; int err, tlen, clen; + const u64 *id; type = mdesc_get_property(hp, mp, "device-type", &tlen); if (!type) { @@ -220,6 +221,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, return NULL; } + bus_id_name = type; + if (!strcmp(type, "domain-services-port")) + bus_id_name = "ds"; + + if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) { + printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n", + bus_id_name); + return NULL; + } + compat = mdesc_get_property(hp, mp, "device-type", &clen); if (!compat) { clen = 0; @@ -249,7 +260,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, vio_fill_channel_info(hp, mp, vdev); - snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp); + id = mdesc_get_property(hp, mp, "id", NULL); + if (!id) + snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", + bus_id_name); + else + snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", + bus_id_name, *id); + vdev->dev.parent = parent; vdev->dev.bus = &vio_bus_type; vdev->dev.release = vio_dev_release; @@ -269,6 +287,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, } vdev->dp = dp; + printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id); + err = device_register(&vdev->dev); if (err) { printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", @@ -283,46 +303,46 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, return vdev; } -static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent) +static void vio_add(struct mdesc_handle *hp, u64 node) { - u64 a; - - mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) { - struct vio_dev *vdev; - u64 target; - - target = mdesc_arc_target(hp, a); - vdev = vio_create_one(hp, target, &parent->dev); - if (vdev) - walk_tree(hp, target, vdev); - } + (void) vio_create_one(hp, node, &root_vdev->dev); } -static void create_devices(struct mdesc_handle *hp, u64 root) +static int vio_md_node_match(struct device *dev, void *arg) { - u64 mp; + struct vio_dev *vdev = to_vio_dev(dev); - root_vdev = vio_create_one(hp, root, NULL); - if (!root_vdev) { - printk(KERN_ERR "VIO: Coult not create root device.\n"); - return; - } + if (vdev->mp == (u64) arg) + return 1; - walk_tree(hp, root, root_vdev); + return 0; +} + +static void vio_remove(struct mdesc_handle *hp, u64 node) +{ + struct device *dev; - /* Domain services is odd as it doesn't sit underneath the - * channel-devices node, so we plug it in manually. - */ - mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services"); - if (mp != MDESC_NODE_NULL) { - struct vio_dev *parent = vio_create_one(hp, mp, - &root_vdev->dev); + dev = device_find_child(&root_vdev->dev, (void *) node, + vio_md_node_match); + if (dev) { + printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id); - if (parent) - walk_tree(hp, mp, parent); + device_unregister(dev); } } +static struct mdesc_notifier_client vio_device_notifier = { + .add = vio_add, + .remove = vio_remove, + .node_name = "virtual-device-port", +}; + +static struct mdesc_notifier_client vio_ds_notifier = { + .add = vio_add, + .remove = vio_remove, + .node_name = "domain-services-port", +}; + const char *channel_devices_node = "channel-devices"; const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; const char *cfg_handle_prop = "cfg-handle"; @@ -381,11 +401,19 @@ static int __init vio_init(void) cdev_cfg_handle = *cfg_handle; - create_devices(hp, root); + root_vdev = vio_create_one(hp, root, NULL); + err = -ENODEV; + if (!root_vdev) { + printk(KERN_ERR "VIO: Coult not create root device.\n"); + goto out_release; + } + + mdesc_register_notifier(&vio_device_notifier); + mdesc_register_notifier(&vio_ds_notifier); mdesc_release(hp); - return 0; + return err; out_release: mdesc_release(hp); diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c index 15613ad..09126fc 100644 --- a/arch/sparc64/kernel/viohs.c +++ b/arch/sparc64/kernel/viohs.c @@ -78,6 +78,24 @@ static int start_handshake(struct vio_driver_state *vio) return 0; } +static void flush_rx_dring(struct vio_driver_state *vio) +{ + struct vio_dring_state *dr; + u64 ident; + + BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG)); + + dr = &vio->drings[VIO_DRIVER_RX_RING]; + ident = dr->ident; + + BUG_ON(!vio->desc_buf); + kfree(vio->desc_buf); + vio->desc_buf = NULL; + + memset(dr, 0, sizeof(*dr)); + dr->ident = ident; +} + void vio_link_state_change(struct vio_driver_state *vio, int event) { if (event == LDC_EVENT_UP) { @@ -98,6 +116,16 @@ void vio_link_state_change(struct vio_driver_state *vio, int event) break; } start_handshake(vio); + } else if (event == LDC_EVENT_RESET) { + vio->hs_state = VIO_HS_INVALID; + + if (vio->dr_state & VIO_DR_STATE_RXREG) + flush_rx_dring(vio); + + vio->dr_state = 0x00; + memset(&vio->ver, 0, sizeof(vio->ver)); + + ldc_disconnect(vio->lp); } } EXPORT_SYMBOL(vio_link_state_change); @@ -396,6 +424,8 @@ static int process_dreg_info(struct vio_driver_state *vio, if (vio->dr_state & VIO_DR_STATE_RXREG) goto send_nack; + BUG_ON(vio->desc_buf); + vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC); if (!vio->desc_buf) goto send_nack; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 0f5e3ca..2288b55 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -45,8 +45,6 @@ struct vdc_req_entry { struct vdc_port { struct vio_driver_state vio; - struct vdc *vp; - struct gendisk *disk; struct vdc_completion *cmp; @@ -72,8 +70,6 @@ struct vdc_port { struct vio_disk_geom geom; struct vio_disk_vtoc label; - - struct list_head list; }; static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) @@ -81,15 +77,6 @@ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) return container_of(vio, struct vdc_port, vio); } -struct vdc { - /* Protects prot_list. */ - spinlock_t lock; - - struct vio_dev *dev; - - struct list_head port_list; -}; - /* Ordered from largest major to lowest */ static struct vio_version vdc_versions[] = { { .major = 1, .minor = 0 }, @@ -747,21 +734,23 @@ static struct vio_driver_ops vdc_vio_ops = { .handshake_complete = vdc_handshake_complete, }; +static void print_version(void) +{ + static int version_printed; + + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); +} + static int __devinit vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) { struct mdesc_handle *hp; struct vdc_port *port; - unsigned long flags; - struct vdc *vp; const u64 *port_id; int err; - vp = dev_get_drvdata(vdev->dev.parent); - if (!vp) { - printk(KERN_ERR PFX "Cannot find port parent vdc.\n"); - return -ENODEV; - } + print_version(); hp = mdesc_grab(); @@ -783,7 +772,6 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev, goto err_out_release_mdesc; } - port->vp = vp; port->dev_no = *port_id; if (port->dev_no >= 26) @@ -818,12 +806,6 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev, if (err) goto err_out_free_tx_ring; - INIT_LIST_HEAD(&port->list); - - spin_lock_irqsave(&vp->lock, flags); - list_add(&port->list, &vp->port_list); - spin_unlock_irqrestore(&vp->lock, flags); - dev_set_drvdata(&vdev->dev, port); mdesc_release(hp); @@ -879,58 +861,6 @@ static struct vio_driver vdc_port_driver = { } }; -static int __devinit vdc_probe(struct vio_dev *vdev, - const struct vio_device_id *id) -{ - static int vdc_version_printed; - struct vdc *vp; - - if (vdc_version_printed++ == 0) - printk(KERN_INFO "%s", version); - - vp = kzalloc(sizeof(struct vdc), GFP_KERNEL); - if (!vp) - return -ENOMEM; - - spin_lock_init(&vp->lock); - vp->dev = vdev; - INIT_LIST_HEAD(&vp->port_list); - - dev_set_drvdata(&vdev->dev, vp); - - return 0; -} - -static int vdc_remove(struct vio_dev *vdev) -{ - - struct vdc *vp = dev_get_drvdata(&vdev->dev); - - if (vp) { - kfree(vp); - dev_set_drvdata(&vdev->dev, NULL); - } - return 0; -} - -static struct vio_device_id vdc_match[] = { - { - .type = "block", - }, - {}, -}; -MODULE_DEVICE_TABLE(vio, vdc_match); - -static struct vio_driver vdc_driver = { - .id_table = vdc_match, - .probe = vdc_probe, - .remove = vdc_remove, - .driver = { - .name = "vdc", - .owner = THIS_MODULE, - } -}; - static int __init vdc_init(void) { int err; @@ -940,19 +870,13 @@ static int __init vdc_init(void) goto out_err; vdc_major = err; - err = vio_register_driver(&vdc_driver); - if (err) - goto out_unregister_blkdev; err = vio_register_driver(&vdc_port_driver); if (err) - goto out_unregister_vdc; + goto out_unregister_blkdev; return 0; -out_unregister_vdc: - vio_unregister_driver(&vdc_driver); - out_unregister_blkdev: unregister_blkdev(vdc_major, VDCBLK_NAME); vdc_major = 0; @@ -964,7 +888,6 @@ out_err: static void __exit vdc_exit(void) { vio_unregister_driver(&vdc_port_driver); - vio_unregister_driver(&vdc_driver); unregister_blkdev(vdc_major, VDCBLK_NAME); } diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 8a667c1..b801e3b 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -12,6 +12,7 @@ #include <linux/netdevice.h> #include <linux/ethtool.h> #include <linux/etherdevice.h> +#include <linux/mutex.h> #include <asm/vio.h> #include <asm/ldc.h> @@ -497,6 +498,8 @@ static void vnet_event(void *arg, int event) vio_link_state_change(vio, event); spin_unlock_irqrestore(&vio->lock, flags); + if (event == LDC_EVENT_RESET) + vio_port_up(vio); return; } @@ -875,6 +878,115 @@ err_out: return err; } +static LIST_HEAD(vnet_list); +static DEFINE_MUTEX(vnet_list_mutex); + +static struct vnet * __devinit vnet_new(const u64 *local_mac) +{ + struct net_device *dev; + struct vnet *vp; + int err, i; + + dev = alloc_etherdev(sizeof(*vp)); + if (!dev) { + printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + return ERR_PTR(-ENOMEM); + } + + for (i = 0; i < ETH_ALEN; i++) + dev->dev_addr[i] = (*local_mac >> (5 - i) * 8) & 0xff; + + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + vp = netdev_priv(dev); + + spin_lock_init(&vp->lock); + vp->dev = dev; + + INIT_LIST_HEAD(&vp->port_list); + for (i = 0; i < VNET_PORT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&vp->port_hash[i]); + INIT_LIST_HEAD(&vp->list); + vp->local_mac = *local_mac; + + dev->open = vnet_open; + dev->stop = vnet_close; + dev->set_multicast_list = vnet_set_rx_mode; + dev->set_mac_address = vnet_set_mac_addr; + dev->tx_timeout = vnet_tx_timeout; + dev->ethtool_ops = &vnet_ethtool_ops; + dev->watchdog_timeo = VNET_TX_TIMEOUT; + dev->change_mtu = vnet_change_mtu; + dev->hard_start_xmit = vnet_start_xmit; + + err = register_netdev(dev); + if (err) { + printk(KERN_ERR PFX "Cannot register net device, " + "aborting.\n"); + goto err_out_free_dev; + } + + printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name); + + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); + + list_add(&vp->list, &vnet_list); + + return vp; + +err_out_free_dev: + free_netdev(dev); + + return ERR_PTR(err); +} + +static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac) +{ + struct vnet *iter, *vp; + + mutex_lock(&vnet_list_mutex); + vp = NULL; + list_for_each_entry(iter, &vnet_list, list) { + if (iter->local_mac == *local_mac) { + vp = iter; + break; + } + } + if (!vp) + vp = vnet_new(local_mac); + mutex_unlock(&vnet_list_mutex); + + return vp; +} + +static const char *local_mac_prop = "local-mac-address"; + +static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp, + u64 port_node) +{ + const u64 *local_mac = NULL; + u64 a; + + mdesc_for_each_arc(a, hp, port_node, MDESC_ARC_TYPE_BACK) { + u64 target = mdesc_arc_target(hp, a); + const char *name; + + name = mdesc_get_property(hp, target, "name", NULL); + if (!name || strcmp(name, "network")) + continue; + + local_mac = mdesc_get_property(hp, target, + local_mac_prop, NULL); + if (local_mac) + break; + } + if (!local_mac) + return ERR_PTR(-ENODEV); + + return vnet_find_or_create(local_mac); +} + static struct ldc_channel_config vnet_ldc_cfg = { .event = vnet_event, .mtu = 64, @@ -887,6 +999,14 @@ static struct vio_driver_ops vnet_vio_ops = { .handshake_complete = vnet_handshake_complete, }; +static void print_version(void) +{ + static int version_printed; + + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); +} + const char *remote_macaddr_prop = "remote-mac-address"; static int __devinit vnet_port_probe(struct vio_dev *vdev, @@ -899,14 +1019,17 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, const u64 *rmac; int len, i, err, switch_port; - vp = dev_get_drvdata(vdev->dev.parent); - if (!vp) { - printk(KERN_ERR PFX "Cannot find port parent vnet.\n"); - return -ENODEV; - } + print_version(); hp = mdesc_grab(); + vp = vnet_find_parent(hp, vdev->mp); + if (IS_ERR(vp)) { + printk(KERN_ERR PFX "Cannot find port parent vnet.\n"); + err = PTR_ERR(vp); + goto err_out_put_mdesc; + } + rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); err = -ENODEV; if (!rmac) { @@ -1025,139 +1148,14 @@ static struct vio_driver vnet_port_driver = { } }; -const char *local_mac_prop = "local-mac-address"; - -static int __devinit vnet_probe(struct vio_dev *vdev, - const struct vio_device_id *id) -{ - static int vnet_version_printed; - struct mdesc_handle *hp; - struct net_device *dev; - struct vnet *vp; - const u64 *mac; - int err, i, len; - - if (vnet_version_printed++ == 0) - printk(KERN_INFO "%s", version); - - hp = mdesc_grab(); - - mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len); - if (!mac) { - printk(KERN_ERR PFX "vnet lacks %s property.\n", - local_mac_prop); - err = -ENODEV; - goto err_out; - } - - dev = alloc_etherdev(sizeof(*vp)); - if (!dev) { - printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); - err = -ENOMEM; - goto err_out; - } - - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff; - - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_NETDEV_DEV(dev, &vdev->dev); - - vp = netdev_priv(dev); - - spin_lock_init(&vp->lock); - vp->dev = dev; - vp->vdev = vdev; - - INIT_LIST_HEAD(&vp->port_list); - for (i = 0; i < VNET_PORT_HASH_SIZE; i++) - INIT_HLIST_HEAD(&vp->port_hash[i]); - - dev->open = vnet_open; - dev->stop = vnet_close; - dev->set_multicast_list = vnet_set_rx_mode; - dev->set_mac_address = vnet_set_mac_addr; - dev->tx_timeout = vnet_tx_timeout; - dev->ethtool_ops = &vnet_ethtool_ops; - dev->watchdog_timeo = VNET_TX_TIMEOUT; - dev->change_mtu = vnet_change_mtu; - dev->hard_start_xmit = vnet_start_xmit; - - err = register_netdev(dev); - if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); - goto err_out_free_dev; - } - - printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - - dev_set_drvdata(&vdev->dev, vp); - - mdesc_release(hp); - - return 0; - -err_out_free_dev: - free_netdev(dev); - -err_out: - mdesc_release(hp); - return err; -} - -static int vnet_remove(struct vio_dev *vdev) -{ - - struct vnet *vp = dev_get_drvdata(&vdev->dev); - - if (vp) { - /* XXX unregister port, or at least check XXX */ - unregister_netdevice(vp->dev); - dev_set_drvdata(&vdev->dev, NULL); - } - return 0; -} - -static struct vio_device_id vnet_match[] = { - { - .type = "network", - }, - {}, -}; -MODULE_DEVICE_TABLE(vio, vnet_match); - -static struct vio_driver vnet_driver = { - .id_table = vnet_match, - .probe = vnet_probe, - .remove = vnet_remove, - .driver = { - .name = "vnet", - .owner = THIS_MODULE, - } -}; - static int __init vnet_init(void) { - int err = vio_register_driver(&vnet_driver); - - if (!err) { - err = vio_register_driver(&vnet_port_driver); - if (err) - vio_unregister_driver(&vnet_driver); - } - - return err; + return vio_register_driver(&vnet_port_driver); } static void __exit vnet_exit(void) { vio_unregister_driver(&vnet_port_driver); - vio_unregister_driver(&vnet_driver); } module_init(vnet_init); diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h index 1c88730..7d3a0ca 100644 --- a/drivers/net/sunvnet.h +++ b/drivers/net/sunvnet.h @@ -60,11 +60,13 @@ struct vnet { struct net_device *dev; u32 msg_enable; - struct vio_dev *vdev; struct list_head port_list; struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; + + struct list_head list; + u64 local_mac; }; #endif /* _SUNVNET_H */ diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h index ad595b6..9565a89 100644 --- a/include/asm-sparc64/io.h +++ b/include/asm-sparc64/io.h @@ -14,11 +14,6 @@ #define __SLOW_DOWN_IO do { } while (0) #define SLOW_DOWN_IO do { } while (0) -extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr); -#define virt_to_bus virt_to_bus_not_defined_use_pci_map -extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr); -#define bus_to_virt bus_to_virt_not_defined_use_pci_map - /* BIO layer definitions. */ extern unsigned long kern_base, kern_size; #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h index e97c431..1acc727 100644 --- a/include/asm-sparc64/mdesc.h +++ b/include/asm-sparc64/mdesc.h @@ -61,6 +61,16 @@ extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc); extern void mdesc_update(void); +struct mdesc_notifier_client { + void (*add)(struct mdesc_handle *handle, u64 node); + void (*remove)(struct mdesc_handle *handle, u64 node); + + const char *node_name; + struct mdesc_notifier_client *next; +}; + +extern void mdesc_register_notifier(struct mdesc_notifier_client *client); + extern void mdesc_fill_in_cpu_data(cpumask_t mask); extern void sun4v_mdesc_init(void); diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h index 83c9642..c0a8d4e 100644 --- a/include/asm-sparc64/vio.h +++ b/include/asm-sparc64/vio.h @@ -264,7 +264,7 @@ static inline u32 vio_dring_avail(struct vio_dring_state *dr, ((dr->prod - dr->cons) & (ring_size - 1))); } -#define VIO_MAX_TYPE_LEN 64 +#define VIO_MAX_TYPE_LEN 32 #define VIO_MAX_COMPAT_LEN 64 struct vio_dev { |