diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-18 18:15:45 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-20 00:27:18 -0400 |
commit | 91ba3c2128e9ee490a9f04bcd5b54749b18e4410 (patch) | |
tree | c90f5711b990468dc684a8859cc9c498b8d4163d | |
parent | 48db7b7c50cdb06c85f0ff01b5c19ac34903048b (diff) |
[SPARC64]: Fix handling of multiple vdc-port nodes.
The "id" property in vdc-port nodes are not unique, they
are all zero. Therefore assign ID's using the parent's
"cfg-handle" property which will be unique.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc64/kernel/mdesc.c | 56 | ||||
-rw-r--r-- | arch/sparc64/kernel/vio.c | 29 | ||||
-rw-r--r-- | drivers/block/sunvdc.c | 24 | ||||
-rw-r--r-- | include/asm-sparc64/vio.h | 2 |
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 | ||
234 | static 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. */ |
235 | static void invoke_on_missing(const char *name, | 254 | static 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; |