aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/mdesc.c56
-rw-r--r--arch/sparc64/kernel/vio.c29
-rw-r--r--drivers/block/sunvdc.c24
-rw-r--r--include/asm-sparc64/vio.h2
4 files changed, 88 insertions, 23 deletions
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index 302ba5e5a0bb..13a79fe5115b 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -231,6 +231,25 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client)
231 mutex_unlock(&mdesc_mutex); 231 mutex_unlock(&mdesc_mutex);
232} 232}
233 233
234static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
235{
236 const u64 *id;
237 u64 a;
238
239 id = NULL;
240 mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
241 u64 target;
242
243 target = mdesc_arc_target(hp, a);
244 id = mdesc_get_property(hp, target,
245 "cfg-handle", NULL);
246 if (id)
247 break;
248 }
249
250 return id;
251}
252
234/* Run 'func' on nodes which are in A but not in B. */ 253/* Run 'func' on nodes which are in A but not in B. */
235static void invoke_on_missing(const char *name, 254static void invoke_on_missing(const char *name,
236 struct mdesc_handle *a, 255 struct mdesc_handle *a,
@@ -240,13 +259,42 @@ static void invoke_on_missing(const char *name,
240 u64 node; 259 u64 node;
241 260
242 mdesc_for_each_node_by_name(a, node, name) { 261 mdesc_for_each_node_by_name(a, node, name) {
243 const u64 *id = mdesc_get_property(a, node, "id", NULL); 262 int found = 0, is_vdc_port = 0;
244 int found = 0; 263 const char *name_prop;
264 const u64 *id;
245 u64 fnode; 265 u64 fnode;
246 266
267 name_prop = mdesc_get_property(a, node, "name", NULL);
268 if (name_prop && !strcmp(name_prop, "vdc-port")) {
269 is_vdc_port = 1;
270 id = parent_cfg_handle(a, node);
271 } else
272 id = mdesc_get_property(a, node, "id", NULL);
273
274 if (!id) {
275 printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
276 (name_prop ? name_prop : name));
277 continue;
278 }
279
247 mdesc_for_each_node_by_name(b, fnode, name) { 280 mdesc_for_each_node_by_name(b, fnode, name) {
248 const u64 *fid = mdesc_get_property(b, fnode, 281 const u64 *fid;
249 "id", NULL); 282
283 if (is_vdc_port) {
284 name_prop = mdesc_get_property(b, fnode,
285 "name", NULL);
286 if (!name_prop ||
287 strcmp(name_prop, "vdc-port"))
288 continue;
289 fid = parent_cfg_handle(b, fnode);
290 if (!fid) {
291 printk(KERN_ERR "MD: Cannot find ID "
292 "for vdc-port node.\n");
293 continue;
294 }
295 } else
296 fid = mdesc_get_property(b, fnode,
297 "id", NULL);
250 298
251 if (*id == *fid) { 299 if (*id == *fid) {
252 found = 1; 300 found = 1;
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 7e65b5a28bff..9ae1f61d4db9 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -221,6 +221,27 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
221 return NULL; 221 return NULL;
222 } 222 }
223 223
224 if (!strcmp(type, "vdc-port")) {
225 u64 a;
226
227 id = NULL;
228 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
229 u64 target;
230
231 target = mdesc_arc_target(hp, a);
232 id = mdesc_get_property(hp, target,
233 "cfg-handle", NULL);
234 if (id)
235 break;
236 }
237 if (!id) {
238 printk(KERN_ERR "VIO: vdc-prot lacks parent "
239 "cfg-handle.\n");
240 return NULL;
241 }
242 } else
243 id = mdesc_get_property(hp, mp, "id", NULL);
244
224 bus_id_name = type; 245 bus_id_name = type;
225 if (!strcmp(type, "domain-services-port")) 246 if (!strcmp(type, "domain-services-port"))
226 bus_id_name = "ds"; 247 bus_id_name = "ds";
@@ -260,13 +281,15 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
260 281
261 vio_fill_channel_info(hp, mp, vdev); 282 vio_fill_channel_info(hp, mp, vdev);
262 283
263 id = mdesc_get_property(hp, mp, "id", NULL); 284 if (!id) {
264 if (!id)
265 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", 285 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
266 bus_id_name); 286 bus_id_name);
267 else 287 vdev->dev_no = ~(u64)0;
288 } else {
268 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", 289 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
269 bus_id_name, *id); 290 bus_id_name, *id);
291 vdev->dev_no = *id;
292 }
270 293
271 vdev->dev.parent = parent; 294 vdev->dev.parent = parent;
272 vdev->dev.bus = &vio_bus_type; 295 vdev->dev.bus = &vio_bus_type;
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 4ee3920b05cc..d50b82381155 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -64,7 +64,6 @@ struct vdc_port {
64 u64 operations; 64 u64 operations;
65 u32 vdisk_size; 65 u32 vdisk_size;
66 u8 vdisk_type; 66 u8 vdisk_type;
67 u8 dev_no;
68 67
69 char disk_name[32]; 68 char disk_name[32];
70 69
@@ -703,7 +702,7 @@ static int probe_disk(struct vdc_port *port)
703 blk_queue_max_phys_segments(q, port->ring_cookies); 702 blk_queue_max_phys_segments(q, port->ring_cookies);
704 blk_queue_max_sectors(q, port->max_xfer_size); 703 blk_queue_max_sectors(q, port->max_xfer_size);
705 g->major = vdc_major; 704 g->major = vdc_major;
706 g->first_minor = port->dev_no << PARTITION_SHIFT; 705 g->first_minor = port->vio.vdev->dev_no << PARTITION_SHIFT;
707 strcpy(g->disk_name, port->disk_name); 706 strcpy(g->disk_name, port->disk_name);
708 707
709 g->fops = &vdc_fops; 708 g->fops = &vdc_fops;
@@ -747,21 +746,16 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
747{ 746{
748 struct mdesc_handle *hp; 747 struct mdesc_handle *hp;
749 struct vdc_port *port; 748 struct vdc_port *port;
750 const u64 *port_id;
751 int err; 749 int err;
752 750
753 print_version(); 751 print_version();
754 752
755 hp = mdesc_grab(); 753 hp = mdesc_grab();
756 754
757 port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
758 err = -ENODEV; 755 err = -ENODEV;
759 if (!port_id) { 756 if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
760 printk(KERN_ERR PFX "Port lacks id property.\n"); 757 printk(KERN_ERR PFX "Port id [%lu] too large.\n",
761 goto err_out_release_mdesc; 758 vdev->dev_no);
762 }
763 if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
764 printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
765 goto err_out_release_mdesc; 759 goto err_out_release_mdesc;
766 } 760 }
767 761
@@ -772,16 +766,14 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
772 goto err_out_release_mdesc; 766 goto err_out_release_mdesc;
773 } 767 }
774 768
775 port->dev_no = *port_id; 769 if (vdev->dev_no >= 26)
776
777 if (port->dev_no >= 26)
778 snprintf(port->disk_name, sizeof(port->disk_name), 770 snprintf(port->disk_name, sizeof(port->disk_name),
779 VDCBLK_NAME "%c%c", 771 VDCBLK_NAME "%c%c",
780 'a' + (port->dev_no / 26) - 1, 772 'a' + ((int)vdev->dev_no / 26) - 1,
781 'a' + (port->dev_no % 26)); 773 'a' + ((int)vdev->dev_no % 26));
782 else 774 else
783 snprintf(port->disk_name, sizeof(port->disk_name), 775 snprintf(port->disk_name, sizeof(port->disk_name),
784 VDCBLK_NAME "%c", 'a' + (port->dev_no % 26)); 776 VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26));
785 777
786 err = vio_driver_init(&port->vio, vdev, VDEV_DISK, 778 err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
787 vdc_versions, ARRAY_SIZE(vdc_versions), 779 vdc_versions, ARRAY_SIZE(vdc_versions),
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
index c0a8d4ed5bcb..f7417e91b170 100644
--- a/include/asm-sparc64/vio.h
+++ b/include/asm-sparc64/vio.h
@@ -275,6 +275,8 @@ struct vio_dev {
275 char compat[VIO_MAX_COMPAT_LEN]; 275 char compat[VIO_MAX_COMPAT_LEN];
276 int compat_len; 276 int compat_len;
277 277
278 u64 dev_no;
279
278 unsigned long channel_id; 280 unsigned long channel_id;
279 281
280 unsigned int tx_irq; 282 unsigned int tx_irq;