diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2006-04-27 17:18:21 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-04-29 18:02:00 +1000 |
commit | e10fa77368dff31140451fac04d78d9f51f0f3ac (patch) | |
tree | 20f3645859dbd995ded831f5a40b78e823e4fc6e /arch/powerpc/platforms | |
parent | 95a1ca6cd8e702a19ee56efae522a5816a56a205 (diff) |
[PATCH] powerpc: use the device tree for the iSeries vio bus probe
As an added bonus, since every vio_dev now has a device_node
associated with it, hotplug now works.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/iseries/setup.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/vio.c | 70 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/vio.c | 147 |
3 files changed, 22 insertions, 199 deletions
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 4862b8e7c78..901acbcc088 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -951,6 +951,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "vlan"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); mac_addr[0] = 0x02; mac_addr[1] = 0x01; @@ -971,6 +972,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viodasd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALDISKS; @@ -980,6 +982,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viocd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALCDROMS; @@ -989,6 +992,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viotape"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 22045a2829a..a689da6f2b0 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -43,58 +43,11 @@ static void __init iommu_vio_init(void) printk("Virtual Bus VIO TCE table failed.\n"); } -/** - * vio_register_device_iseries: - Register a new iSeries vio device. - * @voidev: The device to register. - */ -static struct vio_dev *__init vio_register_device_iseries(char *type, - uint32_t unit_num) +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) { - struct vio_dev *viodev; - - /* allocate a vio_dev for this device */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) - return NULL; - memset(viodev, 0, sizeof(struct vio_dev)); - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); - - viodev->name = viodev->dev.bus_id; - viodev->type = type; - viodev->unit_address = unit_num; - viodev->iommu_table = &vio_iommu_table; - if (vio_register_device(viodev) == NULL) { - kfree(viodev); - return NULL; - } - return viodev; -} - -static void __init probe_bus_iseries(void) -{ - HvLpIndexMap vlan_map; - struct vio_dev *viodev; - int i; - - /* there is only one of each of these */ - vio_register_device_iseries("viocons", 0); - vio_register_device_iseries("vscsi", 0); - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - viodev = vio_register_device_iseries("vlan", i); - /* veth is special and has it own iommu_table */ - viodev->iommu_table = &veth_iommu_table; - } - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - vio_register_device_iseries("viodasd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - vio_register_device_iseries("viocd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - vio_register_device_iseries("viotape", i); + if (strcmp(dev->type, "vlan") == 0) + return &veth_iommu_table; + return &vio_iommu_table; } /** @@ -109,6 +62,7 @@ static int vio_match_device_iseries(const struct vio_device_id *id, static struct vio_bus_ops vio_bus_ops_iseries = { .match = vio_match_device_iseries, + .build_iommu_table = vio_build_iommu_table, }; /** @@ -116,16 +70,10 @@ static struct vio_bus_ops vio_bus_ops_iseries = { */ static int __init vio_bus_init_iseries(void) { - int err; - - err = vio_bus_init(&vio_bus_ops_iseries); - if (err == 0) { - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - probe_bus_iseries(); - } - return err; + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + return vio_bus_init(&vio_bus_ops_iseries); } __initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 8e53e04ada8..b3925aefdac 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -26,26 +26,6 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -static void probe_bus_pseries(void) -{ - struct device_node *node_vroot, *of_node; - - node_vroot = find_devices("vdevice"); - if ((node_vroot == NULL) || (node_vroot->child == NULL)) - /* this machine doesn't do virtual IO, and that's ok */ - return; - - /* - * Create struct vio_devices for each virtual device in the device tree. - * Drivers will associate with them later. - */ - for (of_node = node_vroot->child; of_node != NULL; - of_node = of_node->sibling) { - printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node); - vio_register_device_node(of_node); - } -} - /** * vio_match_device_pseries: - Tell if a pSeries VIO device matches a * vio_device_id @@ -57,47 +37,6 @@ static int vio_match_device_pseries(const struct vio_device_id *id, device_is_compatible(dev->dev.platform_data, id->compat); } -static void vio_release_device_pseries(struct device *dev) -{ - /* XXX free TCE table */ - of_node_put(dev->platform_data); -} - -static ssize_t viodev_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct device_node *of_node = dev->platform_data; - - return sprintf(buf, "%s\n", of_node->full_name); -} -DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); - -static void vio_unregister_device_pseries(struct vio_dev *viodev) -{ - device_remove_file(&viodev->dev, &dev_attr_devspec); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, - .unregister_device = vio_unregister_device_pseries, - .release_device = vio_release_device_pseries, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_pseries); - if (err == 0) - probe_bus_pseries(); - return err; -} - -__initcall(vio_bus_init_pseries); - /** * vio_build_iommu_table: - gets the dma information from OF and * builds the TCE tree. @@ -136,88 +75,20 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) return iommu_init_table(newTceTable); } +static struct vio_bus_ops vio_bus_ops_pseries = { + .match = vio_match_device_pseries, + .build_iommu_table = vio_build_iommu_table, +}; + /** - * vio_register_device_node: - Register a new vio device. - * @of_node: The OF node for this device. - * - * Creates and initializes a vio_dev structure from the data in - * of_node (dev.platform_data) and adds it to the list of virtual devices. - * Returns a pointer to the created vio_dev or NULL if node has - * NULL device_type or compatible fields. + * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus */ -struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) +static int __init vio_bus_init_pseries(void) { - struct vio_dev *viodev; - unsigned int *unit_address; - unsigned int *irq_p; - - /* we need the 'device_type' property, in order to match with drivers */ - if ((NULL == of_node->type)) { - printk(KERN_WARNING - "%s: node %s missing 'device_type'\n", __FUNCTION__, - of_node->name ? of_node->name : "<unknown>"); - return NULL; - } - - unit_address = (unsigned int *)get_property(of_node, "reg", NULL); - if (!unit_address) { - printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, - of_node->name ? of_node->name : "<unknown>"); - return NULL; - } - - /* allocate a vio_dev for this node */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) { - return NULL; - } - memset(viodev, 0, sizeof(struct vio_dev)); - - viodev->dev.platform_data = of_node_get(of_node); - - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); - viodev->name = of_node->name; - viodev->type = of_node->type; - viodev->unit_address = *unit_address; - viodev->iommu_table = vio_build_iommu_table(viodev); - - /* register with generic device framework */ - if (vio_register_device(viodev) == NULL) { - /* XXX free TCE table */ - kfree(viodev); - return NULL; - } - device_create_file(&viodev->dev, &dev_attr_devspec); - - return viodev; + return vio_bus_init(&vio_bus_ops_pseries); } -EXPORT_SYMBOL(vio_register_device_node); -/** - * vio_get_attribute: - get attribute for virtual device - * @vdev: The vio device to get property. - * @which: The property/attribute to be extracted. - * @length: Pointer to length of returned data size (unused if NULL). - * - * Calls prom.c's get_property() to return the value of the - * attribute specified by the preprocessor constant @which -*/ -const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) -{ - return get_property(vdev->dev.platform_data, (char*)which, length); -} -EXPORT_SYMBOL(vio_get_attribute); +__initcall(vio_bus_init_pseries); /* vio_find_name() - internal because only vio.c knows how we formatted the * kobject name |