aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc64/Kconfig3
-rw-r--r--arch/sparc64/kernel/ds.c19
-rw-r--r--arch/sparc64/kernel/mdesc.c78
-rw-r--r--arch/sparc64/kernel/vio.c94
-rw-r--r--arch/sparc64/kernel/viohs.c30
-rw-r--r--drivers/block/sunvdc.c97
-rw-r--r--drivers/net/sunvnet.c260
-rw-r--r--drivers/net/sunvnet.h4
-rw-r--r--include/asm-sparc64/io.h5
-rw-r--r--include/asm-sparc64/mdesc.h10
-rw-r--r--include/asm-sparc64/vio.h2
12 files changed, 344 insertions, 261 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 73df7115325b..603d83ad65c8 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -21,6 +21,9 @@ config GENERIC_ISA_DMA
21 bool 21 bool
22 default y 22 default y
23 23
24config ARCH_NO_VIRT_TO_BUS
25 def_bool y
26
24source "init/Kconfig" 27source "init/Kconfig"
25 28
26menu "General machine setup" 29menu "General machine setup"
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index b84b6af1241e..df6ee71894d1 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -62,6 +62,9 @@ config AUDIT_ARCH
62 bool 62 bool
63 default y 63 default y
64 64
65config ARCH_NO_VIRT_TO_BUS
66 def_bool y
67
65choice 68choice
66 prompt "Kernel page size" 69 prompt "Kernel page size"
67 default SPARC64_PAGE_SIZE_8KB 70 default SPARC64_PAGE_SIZE_8KB
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
index ba01533f4e03..fa1f04d756a2 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)
1013 dp->hs_state = DS_HS_START; 1013 dp->hs_state = DS_HS_START;
1014} 1014}
1015 1015
1016static void ds_reset(struct ds_info *dp)
1017{
1018 int i;
1019
1020 dp->hs_state = 0;
1021
1022 for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
1023 struct ds_cap_state *cp = &ds_states[i];
1024
1025 cp->state = CAP_STATE_UNKNOWN;
1026 }
1027}
1028
1016static void ds_event(void *arg, int event) 1029static void ds_event(void *arg, int event)
1017{ 1030{
1018 struct ds_info *dp = arg; 1031 struct ds_info *dp = arg;
@@ -1028,6 +1041,12 @@ static void ds_event(void *arg, int event)
1028 return; 1041 return;
1029 } 1042 }
1030 1043
1044 if (event == LDC_EVENT_RESET) {
1045 ds_reset(dp);
1046 spin_unlock_irqrestore(&ds_lock, flags);
1047 return;
1048 }
1049
1031 if (event != LDC_EVENT_DATA_READY) { 1050 if (event != LDC_EVENT_DATA_READY) {
1032 printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); 1051 printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
1033 spin_unlock_irqrestore(&ds_lock, flags); 1052 spin_unlock_irqrestore(&ds_lock, flags);
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index de5310ffdb48..302ba5e5a0bb 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)
137 sizeof(struct mdesc_hdr) + 137 sizeof(struct mdesc_hdr) +
138 mdesc_size); 138 mdesc_size);
139 139
140 base = kmalloc(handle_size + 15, GFP_KERNEL); 140 base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
141 if (base) { 141 if (base) {
142 struct mdesc_handle *hp; 142 struct mdesc_handle *hp;
143 unsigned long addr; 143 unsigned long addr;
@@ -214,18 +214,83 @@ void mdesc_release(struct mdesc_handle *hp)
214} 214}
215EXPORT_SYMBOL(mdesc_release); 215EXPORT_SYMBOL(mdesc_release);
216 216
217static DEFINE_MUTEX(mdesc_mutex);
218static struct mdesc_notifier_client *client_list;
219
220void mdesc_register_notifier(struct mdesc_notifier_client *client)
221{
222 u64 node;
223
224 mutex_lock(&mdesc_mutex);
225 client->next = client_list;
226 client_list = client;
227
228 mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
229 client->add(cur_mdesc, node);
230
231 mutex_unlock(&mdesc_mutex);
232}
233
234/* Run 'func' on nodes which are in A but not in B. */
235static void invoke_on_missing(const char *name,
236 struct mdesc_handle *a,
237 struct mdesc_handle *b,
238 void (*func)(struct mdesc_handle *, u64))
239{
240 u64 node;
241
242 mdesc_for_each_node_by_name(a, node, name) {
243 const u64 *id = mdesc_get_property(a, node, "id", NULL);
244 int found = 0;
245 u64 fnode;
246
247 mdesc_for_each_node_by_name(b, fnode, name) {
248 const u64 *fid = mdesc_get_property(b, fnode,
249 "id", NULL);
250
251 if (*id == *fid) {
252 found = 1;
253 break;
254 }
255 }
256 if (!found)
257 func(a, node);
258 }
259}
260
261static void notify_one(struct mdesc_notifier_client *p,
262 struct mdesc_handle *old_hp,
263 struct mdesc_handle *new_hp)
264{
265 invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
266 invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
267}
268
269static void mdesc_notify_clients(struct mdesc_handle *old_hp,
270 struct mdesc_handle *new_hp)
271{
272 struct mdesc_notifier_client *p = client_list;
273
274 while (p) {
275 notify_one(p, old_hp, new_hp);
276 p = p->next;
277 }
278}
279
217void mdesc_update(void) 280void mdesc_update(void)
218{ 281{
219 unsigned long len, real_len, status; 282 unsigned long len, real_len, status;
220 struct mdesc_handle *hp, *orig_hp; 283 struct mdesc_handle *hp, *orig_hp;
221 unsigned long flags; 284 unsigned long flags;
222 285
286 mutex_lock(&mdesc_mutex);
287
223 (void) sun4v_mach_desc(0UL, 0UL, &len); 288 (void) sun4v_mach_desc(0UL, 0UL, &len);
224 289
225 hp = mdesc_alloc(len, &kmalloc_mdesc_memops); 290 hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
226 if (!hp) { 291 if (!hp) {
227 printk(KERN_ERR "MD: mdesc alloc fails\n"); 292 printk(KERN_ERR "MD: mdesc alloc fails\n");
228 return; 293 goto out;
229 } 294 }
230 295
231 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); 296 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
@@ -234,18 +299,25 @@ void mdesc_update(void)
234 status); 299 status);
235 atomic_dec(&hp->refcnt); 300 atomic_dec(&hp->refcnt);
236 mdesc_free(hp); 301 mdesc_free(hp);
237 return; 302 goto out;
238 } 303 }
239 304
240 spin_lock_irqsave(&mdesc_lock, flags); 305 spin_lock_irqsave(&mdesc_lock, flags);
241 orig_hp = cur_mdesc; 306 orig_hp = cur_mdesc;
242 cur_mdesc = hp; 307 cur_mdesc = hp;
308 spin_unlock_irqrestore(&mdesc_lock, flags);
243 309
310 mdesc_notify_clients(orig_hp, hp);
311
312 spin_lock_irqsave(&mdesc_lock, flags);
244 if (atomic_dec_and_test(&orig_hp->refcnt)) 313 if (atomic_dec_and_test(&orig_hp->refcnt))
245 mdesc_free(orig_hp); 314 mdesc_free(orig_hp);
246 else 315 else
247 list_add(&orig_hp->list, &mdesc_zombie_list); 316 list_add(&orig_hp->list, &mdesc_zombie_list);
248 spin_unlock_irqrestore(&mdesc_lock, flags); 317 spin_unlock_irqrestore(&mdesc_lock, flags);
318
319out:
320 mutex_unlock(&mdesc_mutex);
249} 321}
250 322
251static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) 323static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 49569b44ea1f..8d3cc4fdb557 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,
201static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, 201static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
202 struct device *parent) 202 struct device *parent)
203{ 203{
204 const char *type, *compat; 204 const char *type, *compat, *bus_id_name;
205 struct device_node *dp; 205 struct device_node *dp;
206 struct vio_dev *vdev; 206 struct vio_dev *vdev;
207 int err, tlen, clen; 207 int err, tlen, clen;
208 const u64 *id;
208 209
209 type = mdesc_get_property(hp, mp, "device-type", &tlen); 210 type = mdesc_get_property(hp, mp, "device-type", &tlen);
210 if (!type) { 211 if (!type) {
@@ -220,6 +221,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
220 return NULL; 221 return NULL;
221 } 222 }
222 223
224 bus_id_name = type;
225 if (!strcmp(type, "domain-services-port"))
226 bus_id_name = "ds";
227
228 if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) {
229 printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
230 bus_id_name);
231 return NULL;
232 }
233
223 compat = mdesc_get_property(hp, mp, "device-type", &clen); 234 compat = mdesc_get_property(hp, mp, "device-type", &clen);
224 if (!compat) { 235 if (!compat) {
225 clen = 0; 236 clen = 0;
@@ -249,7 +260,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
249 260
250 vio_fill_channel_info(hp, mp, vdev); 261 vio_fill_channel_info(hp, mp, vdev);
251 262
252 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp); 263 id = mdesc_get_property(hp, mp, "id", NULL);
264 if (!id)
265 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
266 bus_id_name);
267 else
268 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
269 bus_id_name, *id);
270
253 vdev->dev.parent = parent; 271 vdev->dev.parent = parent;
254 vdev->dev.bus = &vio_bus_type; 272 vdev->dev.bus = &vio_bus_type;
255 vdev->dev.release = vio_dev_release; 273 vdev->dev.release = vio_dev_release;
@@ -269,6 +287,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
269 } 287 }
270 vdev->dp = dp; 288 vdev->dp = dp;
271 289
290 printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id);
291
272 err = device_register(&vdev->dev); 292 err = device_register(&vdev->dev);
273 if (err) { 293 if (err) {
274 printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", 294 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,
283 return vdev; 303 return vdev;
284} 304}
285 305
286static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent) 306static void vio_add(struct mdesc_handle *hp, u64 node)
287{ 307{
288 u64 a; 308 (void) vio_create_one(hp, node, &root_vdev->dev);
289
290 mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
291 struct vio_dev *vdev;
292 u64 target;
293
294 target = mdesc_arc_target(hp, a);
295 vdev = vio_create_one(hp, target, &parent->dev);
296 if (vdev)
297 walk_tree(hp, target, vdev);
298 }
299} 309}
300 310
301static void create_devices(struct mdesc_handle *hp, u64 root) 311static int vio_md_node_match(struct device *dev, void *arg)
302{ 312{
303 u64 mp; 313 struct vio_dev *vdev = to_vio_dev(dev);
304 314
305 root_vdev = vio_create_one(hp, root, NULL); 315 if (vdev->mp == (u64) arg)
306 if (!root_vdev) { 316 return 1;
307 printk(KERN_ERR "VIO: Coult not create root device.\n");
308 return;
309 }
310 317
311 walk_tree(hp, root, root_vdev); 318 return 0;
319}
320
321static void vio_remove(struct mdesc_handle *hp, u64 node)
322{
323 struct device *dev;
312 324
313 /* Domain services is odd as it doesn't sit underneath the 325 dev = device_find_child(&root_vdev->dev, (void *) node,
314 * channel-devices node, so we plug it in manually. 326 vio_md_node_match);
315 */ 327 if (dev) {
316 mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services"); 328 printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id);
317 if (mp != MDESC_NODE_NULL) {
318 struct vio_dev *parent = vio_create_one(hp, mp,
319 &root_vdev->dev);
320 329
321 if (parent) 330 device_unregister(dev);
322 walk_tree(hp, mp, parent);
323 } 331 }
324} 332}
325 333
334static struct mdesc_notifier_client vio_device_notifier = {
335 .add = vio_add,
336 .remove = vio_remove,
337 .node_name = "virtual-device-port",
338};
339
340static struct mdesc_notifier_client vio_ds_notifier = {
341 .add = vio_add,
342 .remove = vio_remove,
343 .node_name = "domain-services-port",
344};
345
326const char *channel_devices_node = "channel-devices"; 346const char *channel_devices_node = "channel-devices";
327const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; 347const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
328const char *cfg_handle_prop = "cfg-handle"; 348const char *cfg_handle_prop = "cfg-handle";
@@ -381,11 +401,19 @@ static int __init vio_init(void)
381 401
382 cdev_cfg_handle = *cfg_handle; 402 cdev_cfg_handle = *cfg_handle;
383 403
384 create_devices(hp, root); 404 root_vdev = vio_create_one(hp, root, NULL);
405 err = -ENODEV;
406 if (!root_vdev) {
407 printk(KERN_ERR "VIO: Coult not create root device.\n");
408 goto out_release;
409 }
410
411 mdesc_register_notifier(&vio_device_notifier);
412 mdesc_register_notifier(&vio_ds_notifier);
385 413
386 mdesc_release(hp); 414 mdesc_release(hp);
387 415
388 return 0; 416 return err;
389 417
390out_release: 418out_release:
391 mdesc_release(hp); 419 mdesc_release(hp);
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
index 15613add45d1..09126fc338ba 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)
78 return 0; 78 return 0;
79} 79}
80 80
81static void flush_rx_dring(struct vio_driver_state *vio)
82{
83 struct vio_dring_state *dr;
84 u64 ident;
85
86 BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG));
87
88 dr = &vio->drings[VIO_DRIVER_RX_RING];
89 ident = dr->ident;
90
91 BUG_ON(!vio->desc_buf);
92 kfree(vio->desc_buf);
93 vio->desc_buf = NULL;
94
95 memset(dr, 0, sizeof(*dr));
96 dr->ident = ident;
97}
98
81void vio_link_state_change(struct vio_driver_state *vio, int event) 99void vio_link_state_change(struct vio_driver_state *vio, int event)
82{ 100{
83 if (event == LDC_EVENT_UP) { 101 if (event == LDC_EVENT_UP) {
@@ -98,6 +116,16 @@ void vio_link_state_change(struct vio_driver_state *vio, int event)
98 break; 116 break;
99 } 117 }
100 start_handshake(vio); 118 start_handshake(vio);
119 } else if (event == LDC_EVENT_RESET) {
120 vio->hs_state = VIO_HS_INVALID;
121
122 if (vio->dr_state & VIO_DR_STATE_RXREG)
123 flush_rx_dring(vio);
124
125 vio->dr_state = 0x00;
126 memset(&vio->ver, 0, sizeof(vio->ver));
127
128 ldc_disconnect(vio->lp);
101 } 129 }
102} 130}
103EXPORT_SYMBOL(vio_link_state_change); 131EXPORT_SYMBOL(vio_link_state_change);
@@ -396,6 +424,8 @@ static int process_dreg_info(struct vio_driver_state *vio,
396 if (vio->dr_state & VIO_DR_STATE_RXREG) 424 if (vio->dr_state & VIO_DR_STATE_RXREG)
397 goto send_nack; 425 goto send_nack;
398 426
427 BUG_ON(vio->desc_buf);
428
399 vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC); 429 vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
400 if (!vio->desc_buf) 430 if (!vio->desc_buf)
401 goto send_nack; 431 goto send_nack;
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 0f5e3caf85d7..2288b55d916f 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -45,8 +45,6 @@ struct vdc_req_entry {
45struct vdc_port { 45struct vdc_port {
46 struct vio_driver_state vio; 46 struct vio_driver_state vio;
47 47
48 struct vdc *vp;
49
50 struct gendisk *disk; 48 struct gendisk *disk;
51 49
52 struct vdc_completion *cmp; 50 struct vdc_completion *cmp;
@@ -72,8 +70,6 @@ struct vdc_port {
72 70
73 struct vio_disk_geom geom; 71 struct vio_disk_geom geom;
74 struct vio_disk_vtoc label; 72 struct vio_disk_vtoc label;
75
76 struct list_head list;
77}; 73};
78 74
79static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) 75static 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)
81 return container_of(vio, struct vdc_port, vio); 77 return container_of(vio, struct vdc_port, vio);
82} 78}
83 79
84struct vdc {
85 /* Protects prot_list. */
86 spinlock_t lock;
87
88 struct vio_dev *dev;
89
90 struct list_head port_list;
91};
92
93/* Ordered from largest major to lowest */ 80/* Ordered from largest major to lowest */
94static struct vio_version vdc_versions[] = { 81static struct vio_version vdc_versions[] = {
95 { .major = 1, .minor = 0 }, 82 { .major = 1, .minor = 0 },
@@ -747,21 +734,23 @@ static struct vio_driver_ops vdc_vio_ops = {
747 .handshake_complete = vdc_handshake_complete, 734 .handshake_complete = vdc_handshake_complete,
748}; 735};
749 736
737static void print_version(void)
738{
739 static int version_printed;
740
741 if (version_printed++ == 0)
742 printk(KERN_INFO "%s", version);
743}
744
750static int __devinit vdc_port_probe(struct vio_dev *vdev, 745static int __devinit vdc_port_probe(struct vio_dev *vdev,
751 const struct vio_device_id *id) 746 const struct vio_device_id *id)
752{ 747{
753 struct mdesc_handle *hp; 748 struct mdesc_handle *hp;
754 struct vdc_port *port; 749 struct vdc_port *port;
755 unsigned long flags;
756 struct vdc *vp;
757 const u64 *port_id; 750 const u64 *port_id;
758 int err; 751 int err;
759 752
760 vp = dev_get_drvdata(vdev->dev.parent); 753 print_version();
761 if (!vp) {
762 printk(KERN_ERR PFX "Cannot find port parent vdc.\n");
763 return -ENODEV;
764 }
765 754
766 hp = mdesc_grab(); 755 hp = mdesc_grab();
767 756
@@ -783,7 +772,6 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
783 goto err_out_release_mdesc; 772 goto err_out_release_mdesc;
784 } 773 }
785 774
786 port->vp = vp;
787 port->dev_no = *port_id; 775 port->dev_no = *port_id;
788 776
789 if (port->dev_no >= 26) 777 if (port->dev_no >= 26)
@@ -818,12 +806,6 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
818 if (err) 806 if (err)
819 goto err_out_free_tx_ring; 807 goto err_out_free_tx_ring;
820 808
821 INIT_LIST_HEAD(&port->list);
822
823 spin_lock_irqsave(&vp->lock, flags);
824 list_add(&port->list, &vp->port_list);
825 spin_unlock_irqrestore(&vp->lock, flags);
826
827 dev_set_drvdata(&vdev->dev, port); 809 dev_set_drvdata(&vdev->dev, port);
828 810
829 mdesc_release(hp); 811 mdesc_release(hp);
@@ -879,58 +861,6 @@ static struct vio_driver vdc_port_driver = {
879 } 861 }
880}; 862};
881 863
882static int __devinit vdc_probe(struct vio_dev *vdev,
883 const struct vio_device_id *id)
884{
885 static int vdc_version_printed;
886 struct vdc *vp;
887
888 if (vdc_version_printed++ == 0)
889 printk(KERN_INFO "%s", version);
890
891 vp = kzalloc(sizeof(struct vdc), GFP_KERNEL);
892 if (!vp)
893 return -ENOMEM;
894
895 spin_lock_init(&vp->lock);
896 vp->dev = vdev;
897 INIT_LIST_HEAD(&vp->port_list);
898
899 dev_set_drvdata(&vdev->dev, vp);
900
901 return 0;
902}
903
904static int vdc_remove(struct vio_dev *vdev)
905{
906
907 struct vdc *vp = dev_get_drvdata(&vdev->dev);
908
909 if (vp) {
910 kfree(vp);
911 dev_set_drvdata(&vdev->dev, NULL);
912 }
913 return 0;
914}
915
916static struct vio_device_id vdc_match[] = {
917 {
918 .type = "block",
919 },
920 {},
921};
922MODULE_DEVICE_TABLE(vio, vdc_match);
923
924static struct vio_driver vdc_driver = {
925 .id_table = vdc_match,
926 .probe = vdc_probe,
927 .remove = vdc_remove,
928 .driver = {
929 .name = "vdc",
930 .owner = THIS_MODULE,
931 }
932};
933
934static int __init vdc_init(void) 864static int __init vdc_init(void)
935{ 865{
936 int err; 866 int err;
@@ -940,19 +870,13 @@ static int __init vdc_init(void)
940 goto out_err; 870 goto out_err;
941 871
942 vdc_major = err; 872 vdc_major = err;
943 err = vio_register_driver(&vdc_driver);
944 if (err)
945 goto out_unregister_blkdev;
946 873
947 err = vio_register_driver(&vdc_port_driver); 874 err = vio_register_driver(&vdc_port_driver);
948 if (err) 875 if (err)
949 goto out_unregister_vdc; 876 goto out_unregister_blkdev;
950 877
951 return 0; 878 return 0;
952 879
953out_unregister_vdc:
954 vio_unregister_driver(&vdc_driver);
955
956out_unregister_blkdev: 880out_unregister_blkdev:
957 unregister_blkdev(vdc_major, VDCBLK_NAME); 881 unregister_blkdev(vdc_major, VDCBLK_NAME);
958 vdc_major = 0; 882 vdc_major = 0;
@@ -964,7 +888,6 @@ out_err:
964static void __exit vdc_exit(void) 888static void __exit vdc_exit(void)
965{ 889{
966 vio_unregister_driver(&vdc_port_driver); 890 vio_unregister_driver(&vdc_port_driver);
967 vio_unregister_driver(&vdc_driver);
968 unregister_blkdev(vdc_major, VDCBLK_NAME); 891 unregister_blkdev(vdc_major, VDCBLK_NAME);
969} 892}
970 893
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index 8a667c13faef..b801e3b3a11a 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -12,6 +12,7 @@
12#include <linux/netdevice.h> 12#include <linux/netdevice.h>
13#include <linux/ethtool.h> 13#include <linux/ethtool.h>
14#include <linux/etherdevice.h> 14#include <linux/etherdevice.h>
15#include <linux/mutex.h>
15 16
16#include <asm/vio.h> 17#include <asm/vio.h>
17#include <asm/ldc.h> 18#include <asm/ldc.h>
@@ -497,6 +498,8 @@ static void vnet_event(void *arg, int event)
497 vio_link_state_change(vio, event); 498 vio_link_state_change(vio, event);
498 spin_unlock_irqrestore(&vio->lock, flags); 499 spin_unlock_irqrestore(&vio->lock, flags);
499 500
501 if (event == LDC_EVENT_RESET)
502 vio_port_up(vio);
500 return; 503 return;
501 } 504 }
502 505
@@ -875,6 +878,115 @@ err_out:
875 return err; 878 return err;
876} 879}
877 880
881static LIST_HEAD(vnet_list);
882static DEFINE_MUTEX(vnet_list_mutex);
883
884static struct vnet * __devinit vnet_new(const u64 *local_mac)
885{
886 struct net_device *dev;
887 struct vnet *vp;
888 int err, i;
889
890 dev = alloc_etherdev(sizeof(*vp));
891 if (!dev) {
892 printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
893 return ERR_PTR(-ENOMEM);
894 }
895
896 for (i = 0; i < ETH_ALEN; i++)
897 dev->dev_addr[i] = (*local_mac >> (5 - i) * 8) & 0xff;
898
899 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
900
901 vp = netdev_priv(dev);
902
903 spin_lock_init(&vp->lock);
904 vp->dev = dev;
905
906 INIT_LIST_HEAD(&vp->port_list);
907 for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
908 INIT_HLIST_HEAD(&vp->port_hash[i]);
909 INIT_LIST_HEAD(&vp->list);
910 vp->local_mac = *local_mac;
911
912 dev->open = vnet_open;
913 dev->stop = vnet_close;
914 dev->set_multicast_list = vnet_set_rx_mode;
915 dev->set_mac_address = vnet_set_mac_addr;
916 dev->tx_timeout = vnet_tx_timeout;
917 dev->ethtool_ops = &vnet_ethtool_ops;
918 dev->watchdog_timeo = VNET_TX_TIMEOUT;
919 dev->change_mtu = vnet_change_mtu;
920 dev->hard_start_xmit = vnet_start_xmit;
921
922 err = register_netdev(dev);
923 if (err) {
924 printk(KERN_ERR PFX "Cannot register net device, "
925 "aborting.\n");
926 goto err_out_free_dev;
927 }
928
929 printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
930
931 for (i = 0; i < 6; i++)
932 printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
933
934 list_add(&vp->list, &vnet_list);
935
936 return vp;
937
938err_out_free_dev:
939 free_netdev(dev);
940
941 return ERR_PTR(err);
942}
943
944static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
945{
946 struct vnet *iter, *vp;
947
948 mutex_lock(&vnet_list_mutex);
949 vp = NULL;
950 list_for_each_entry(iter, &vnet_list, list) {
951 if (iter->local_mac == *local_mac) {
952 vp = iter;
953 break;
954 }
955 }
956 if (!vp)
957 vp = vnet_new(local_mac);
958 mutex_unlock(&vnet_list_mutex);
959
960 return vp;
961}
962
963static const char *local_mac_prop = "local-mac-address";
964
965static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp,
966 u64 port_node)
967{
968 const u64 *local_mac = NULL;
969 u64 a;
970
971 mdesc_for_each_arc(a, hp, port_node, MDESC_ARC_TYPE_BACK) {
972 u64 target = mdesc_arc_target(hp, a);
973 const char *name;
974
975 name = mdesc_get_property(hp, target, "name", NULL);
976 if (!name || strcmp(name, "network"))
977 continue;
978
979 local_mac = mdesc_get_property(hp, target,
980 local_mac_prop, NULL);
981 if (local_mac)
982 break;
983 }
984 if (!local_mac)
985 return ERR_PTR(-ENODEV);
986
987 return vnet_find_or_create(local_mac);
988}
989
878static struct ldc_channel_config vnet_ldc_cfg = { 990static struct ldc_channel_config vnet_ldc_cfg = {
879 .event = vnet_event, 991 .event = vnet_event,
880 .mtu = 64, 992 .mtu = 64,
@@ -887,6 +999,14 @@ static struct vio_driver_ops vnet_vio_ops = {
887 .handshake_complete = vnet_handshake_complete, 999 .handshake_complete = vnet_handshake_complete,
888}; 1000};
889 1001
1002static void print_version(void)
1003{
1004 static int version_printed;
1005
1006 if (version_printed++ == 0)
1007 printk(KERN_INFO "%s", version);
1008}
1009
890const char *remote_macaddr_prop = "remote-mac-address"; 1010const char *remote_macaddr_prop = "remote-mac-address";
891 1011
892static int __devinit vnet_port_probe(struct vio_dev *vdev, 1012static int __devinit vnet_port_probe(struct vio_dev *vdev,
@@ -899,14 +1019,17 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
899 const u64 *rmac; 1019 const u64 *rmac;
900 int len, i, err, switch_port; 1020 int len, i, err, switch_port;
901 1021
902 vp = dev_get_drvdata(vdev->dev.parent); 1022 print_version();
903 if (!vp) {
904 printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
905 return -ENODEV;
906 }
907 1023
908 hp = mdesc_grab(); 1024 hp = mdesc_grab();
909 1025
1026 vp = vnet_find_parent(hp, vdev->mp);
1027 if (IS_ERR(vp)) {
1028 printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
1029 err = PTR_ERR(vp);
1030 goto err_out_put_mdesc;
1031 }
1032
910 rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); 1033 rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
911 err = -ENODEV; 1034 err = -ENODEV;
912 if (!rmac) { 1035 if (!rmac) {
@@ -1025,139 +1148,14 @@ static struct vio_driver vnet_port_driver = {
1025 } 1148 }
1026}; 1149};
1027 1150
1028const char *local_mac_prop = "local-mac-address";
1029
1030static int __devinit vnet_probe(struct vio_dev *vdev,
1031 const struct vio_device_id *id)
1032{
1033 static int vnet_version_printed;
1034 struct mdesc_handle *hp;
1035 struct net_device *dev;
1036 struct vnet *vp;
1037 const u64 *mac;
1038 int err, i, len;
1039
1040 if (vnet_version_printed++ == 0)
1041 printk(KERN_INFO "%s", version);
1042
1043 hp = mdesc_grab();
1044
1045 mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len);
1046 if (!mac) {
1047 printk(KERN_ERR PFX "vnet lacks %s property.\n",
1048 local_mac_prop);
1049 err = -ENODEV;
1050 goto err_out;
1051 }
1052
1053 dev = alloc_etherdev(sizeof(*vp));
1054 if (!dev) {
1055 printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
1056 err = -ENOMEM;
1057 goto err_out;
1058 }
1059
1060 for (i = 0; i < ETH_ALEN; i++)
1061 dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff;
1062
1063 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
1064
1065 SET_NETDEV_DEV(dev, &vdev->dev);
1066
1067 vp = netdev_priv(dev);
1068
1069 spin_lock_init(&vp->lock);
1070 vp->dev = dev;
1071 vp->vdev = vdev;
1072
1073 INIT_LIST_HEAD(&vp->port_list);
1074 for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
1075 INIT_HLIST_HEAD(&vp->port_hash[i]);
1076
1077 dev->open = vnet_open;
1078 dev->stop = vnet_close;
1079 dev->set_multicast_list = vnet_set_rx_mode;
1080 dev->set_mac_address = vnet_set_mac_addr;
1081 dev->tx_timeout = vnet_tx_timeout;
1082 dev->ethtool_ops = &vnet_ethtool_ops;
1083 dev->watchdog_timeo = VNET_TX_TIMEOUT;
1084 dev->change_mtu = vnet_change_mtu;
1085 dev->hard_start_xmit = vnet_start_xmit;
1086
1087 err = register_netdev(dev);
1088 if (err) {
1089 printk(KERN_ERR PFX "Cannot register net device, "
1090 "aborting.\n");
1091 goto err_out_free_dev;
1092 }
1093
1094 printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
1095
1096 for (i = 0; i < 6; i++)
1097 printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
1098
1099 dev_set_drvdata(&vdev->dev, vp);
1100
1101 mdesc_release(hp);
1102
1103 return 0;
1104
1105err_out_free_dev:
1106 free_netdev(dev);
1107
1108err_out:
1109 mdesc_release(hp);
1110 return err;
1111}
1112
1113static int vnet_remove(struct vio_dev *vdev)
1114{
1115
1116 struct vnet *vp = dev_get_drvdata(&vdev->dev);
1117
1118 if (vp) {
1119 /* XXX unregister port, or at least check XXX */
1120 unregister_netdevice(vp->dev);
1121 dev_set_drvdata(&vdev->dev, NULL);
1122 }
1123 return 0;
1124}
1125
1126static struct vio_device_id vnet_match[] = {
1127 {
1128 .type = "network",
1129 },
1130 {},
1131};
1132MODULE_DEVICE_TABLE(vio, vnet_match);
1133
1134static struct vio_driver vnet_driver = {
1135 .id_table = vnet_match,
1136 .probe = vnet_probe,
1137 .remove = vnet_remove,
1138 .driver = {
1139 .name = "vnet",
1140 .owner = THIS_MODULE,
1141 }
1142};
1143
1144static int __init vnet_init(void) 1151static int __init vnet_init(void)
1145{ 1152{
1146 int err = vio_register_driver(&vnet_driver); 1153 return vio_register_driver(&vnet_port_driver);
1147
1148 if (!err) {
1149 err = vio_register_driver(&vnet_port_driver);
1150 if (err)
1151 vio_unregister_driver(&vnet_driver);
1152 }
1153
1154 return err;
1155} 1154}
1156 1155
1157static void __exit vnet_exit(void) 1156static void __exit vnet_exit(void)
1158{ 1157{
1159 vio_unregister_driver(&vnet_port_driver); 1158 vio_unregister_driver(&vnet_port_driver);
1160 vio_unregister_driver(&vnet_driver);
1161} 1159}
1162 1160
1163module_init(vnet_init); 1161module_init(vnet_init);
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h
index 1c887302d46d..7d3a0cac727b 100644
--- a/drivers/net/sunvnet.h
+++ b/drivers/net/sunvnet.h
@@ -60,11 +60,13 @@ struct vnet {
60 struct net_device *dev; 60 struct net_device *dev;
61 61
62 u32 msg_enable; 62 u32 msg_enable;
63 struct vio_dev *vdev;
64 63
65 struct list_head port_list; 64 struct list_head port_list;
66 65
67 struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; 66 struct hlist_head port_hash[VNET_PORT_HASH_SIZE];
67
68 struct list_head list;
69 u64 local_mac;
68}; 70};
69 71
70#endif /* _SUNVNET_H */ 72#endif /* _SUNVNET_H */
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index ad595b679842..9565a892801e 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -14,11 +14,6 @@
14#define __SLOW_DOWN_IO do { } while (0) 14#define __SLOW_DOWN_IO do { } while (0)
15#define SLOW_DOWN_IO do { } while (0) 15#define SLOW_DOWN_IO do { } while (0)
16 16
17extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
18#define virt_to_bus virt_to_bus_not_defined_use_pci_map
19extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
20#define bus_to_virt bus_to_virt_not_defined_use_pci_map
21
22/* BIO layer definitions. */ 17/* BIO layer definitions. */
23extern unsigned long kern_base, kern_size; 18extern unsigned long kern_base, kern_size;
24#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) 19#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 e97c43133752..1acc7272e537 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);
61 61
62extern void mdesc_update(void); 62extern void mdesc_update(void);
63 63
64struct mdesc_notifier_client {
65 void (*add)(struct mdesc_handle *handle, u64 node);
66 void (*remove)(struct mdesc_handle *handle, u64 node);
67
68 const char *node_name;
69 struct mdesc_notifier_client *next;
70};
71
72extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
73
64extern void mdesc_fill_in_cpu_data(cpumask_t mask); 74extern void mdesc_fill_in_cpu_data(cpumask_t mask);
65 75
66extern void sun4v_mdesc_init(void); 76extern void sun4v_mdesc_init(void);
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
index 83c96422e9d6..c0a8d4ed5bcb 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,
264 ((dr->prod - dr->cons) & (ring_size - 1))); 264 ((dr->prod - dr->cons) & (ring_size - 1)));
265} 265}
266 266
267#define VIO_MAX_TYPE_LEN 64 267#define VIO_MAX_TYPE_LEN 32
268#define VIO_MAX_COMPAT_LEN 64 268#define VIO_MAX_COMPAT_LEN 64
269 269
270struct vio_dev { 270struct vio_dev {