diff options
Diffstat (limited to 'arch/powerpc/kernel/vio.c')
-rw-r--r-- | arch/powerpc/kernel/vio.c | 104 |
1 files changed, 28 insertions, 76 deletions
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 62c1bc12ea39..cb22a3557c4e 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | extern struct kset devices_subsys; /* needed for vio_find_name() */ | 40 | extern struct kset devices_subsys; /* needed for vio_find_name() */ |
41 | 41 | ||
42 | static struct bus_type vio_bus_type; | ||
43 | |||
42 | static struct vio_dev vio_bus_device = { /* fake "parent" device */ | 44 | static struct vio_dev vio_bus_device = { /* fake "parent" device */ |
43 | .name = vio_bus_device.dev.bus_id, | 45 | .name = vio_bus_device.dev.bus_id, |
44 | .type = "", | 46 | .type = "", |
@@ -46,60 +48,33 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */ | |||
46 | .dev.bus = &vio_bus_type, | 48 | .dev.bus = &vio_bus_type, |
47 | }; | 49 | }; |
48 | 50 | ||
49 | #ifdef CONFIG_PPC_ISERIES | 51 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) |
50 | struct device *iSeries_vio_dev = &vio_bus_device.dev; | 52 | { |
51 | EXPORT_SYMBOL(iSeries_vio_dev); | 53 | const unsigned char *dma_window; |
54 | struct iommu_table *tbl; | ||
55 | unsigned long offset, size; | ||
52 | 56 | ||
53 | static struct iommu_table veth_iommu_table; | 57 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
54 | static struct iommu_table vio_iommu_table; | 58 | return vio_build_iommu_table_iseries(dev); |
55 | 59 | ||
56 | static void __init iommu_vio_init(void) | 60 | dma_window = of_get_property(dev->dev.archdata.of_node, |
57 | { | 61 | "ibm,my-dma-window", NULL); |
58 | iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); | 62 | if (!dma_window) |
59 | veth_iommu_table.it_size /= 2; | 63 | return NULL; |
60 | vio_iommu_table = veth_iommu_table; | ||
61 | vio_iommu_table.it_offset += veth_iommu_table.it_size; | ||
62 | |||
63 | if (!iommu_init_table(&veth_iommu_table, -1)) | ||
64 | printk("Virtual Bus VETH TCE table failed.\n"); | ||
65 | if (!iommu_init_table(&vio_iommu_table, -1)) | ||
66 | printk("Virtual Bus VIO TCE table failed.\n"); | ||
67 | } | ||
68 | #endif | ||
69 | 64 | ||
70 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | 65 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); |
71 | { | 66 | |
72 | #ifdef CONFIG_PPC_ISERIES | 67 | of_parse_dma_window(dev->dev.archdata.of_node, dma_window, |
73 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 68 | &tbl->it_index, &offset, &size); |
74 | if (strcmp(dev->type, "network") == 0) | 69 | |
75 | return &veth_iommu_table; | 70 | /* TCE table size - measured in tce entries */ |
76 | return &vio_iommu_table; | 71 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
77 | } else | 72 | /* offset for VIO should always be 0 */ |
78 | #endif | 73 | tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; |
79 | { | 74 | tbl->it_busno = 0; |
80 | const unsigned char *dma_window; | 75 | tbl->it_type = TCE_VB; |
81 | struct iommu_table *tbl; | 76 | |
82 | unsigned long offset, size; | 77 | return iommu_init_table(tbl, -1); |
83 | |||
84 | dma_window = of_get_property(dev->dev.archdata.of_node, | ||
85 | "ibm,my-dma-window", NULL); | ||
86 | if (!dma_window) | ||
87 | return NULL; | ||
88 | |||
89 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); | ||
90 | |||
91 | of_parse_dma_window(dev->dev.archdata.of_node, dma_window, | ||
92 | &tbl->it_index, &offset, &size); | ||
93 | |||
94 | /* TCE table size - measured in tce entries */ | ||
95 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | ||
96 | /* offset for VIO should always be 0 */ | ||
97 | tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; | ||
98 | tbl->it_busno = 0; | ||
99 | tbl->it_type = TCE_VB; | ||
100 | |||
101 | return iommu_init_table(tbl, -1); | ||
102 | } | ||
103 | } | 78 | } |
104 | 79 | ||
105 | /** | 80 | /** |
@@ -160,16 +135,6 @@ static int vio_bus_remove(struct device *dev) | |||
160 | return 1; | 135 | return 1; |
161 | } | 136 | } |
162 | 137 | ||
163 | /* convert from struct device to struct vio_dev and pass to driver. */ | ||
164 | static void vio_bus_shutdown(struct device *dev) | ||
165 | { | ||
166 | struct vio_dev *viodev = to_vio_dev(dev); | ||
167 | struct vio_driver *viodrv = to_vio_driver(dev->driver); | ||
168 | |||
169 | if (dev->driver && viodrv->shutdown) | ||
170 | viodrv->shutdown(viodev); | ||
171 | } | ||
172 | |||
173 | /** | 138 | /** |
174 | * vio_register_driver: - Register a new vio driver | 139 | * vio_register_driver: - Register a new vio driver |
175 | * @drv: The vio_driver structure to be registered. | 140 | * @drv: The vio_driver structure to be registered. |
@@ -282,15 +247,6 @@ static int __init vio_bus_init(void) | |||
282 | int err; | 247 | int err; |
283 | struct device_node *node_vroot; | 248 | struct device_node *node_vroot; |
284 | 249 | ||
285 | #ifdef CONFIG_PPC_ISERIES | ||
286 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
287 | iommu_vio_init(); | ||
288 | vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops; | ||
289 | vio_bus_device.dev.archdata.dma_data = &vio_iommu_table; | ||
290 | iSeries_vio_dev = &vio_bus_device.dev; | ||
291 | } | ||
292 | #endif /* CONFIG_PPC_ISERIES */ | ||
293 | |||
294 | err = bus_register(&vio_bus_type); | 250 | err = bus_register(&vio_bus_type); |
295 | if (err) { | 251 | if (err) { |
296 | printk(KERN_ERR "failed to register VIO bus\n"); | 252 | printk(KERN_ERR "failed to register VIO bus\n"); |
@@ -317,11 +273,8 @@ static int __init vio_bus_init(void) | |||
317 | * the device tree. Drivers will associate with them later. | 273 | * the device tree. Drivers will associate with them later. |
318 | */ | 274 | */ |
319 | for (of_node = node_vroot->child; of_node != NULL; | 275 | for (of_node = node_vroot->child; of_node != NULL; |
320 | of_node = of_node->sibling) { | 276 | of_node = of_node->sibling) |
321 | printk(KERN_DEBUG "%s: processing %p\n", | ||
322 | __FUNCTION__, of_node); | ||
323 | vio_register_device_node(of_node); | 277 | vio_register_device_node(of_node); |
324 | } | ||
325 | of_node_put(node_vroot); | 278 | of_node_put(node_vroot); |
326 | } | 279 | } |
327 | 280 | ||
@@ -391,14 +344,13 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, | |||
391 | return 0; | 344 | return 0; |
392 | } | 345 | } |
393 | 346 | ||
394 | struct bus_type vio_bus_type = { | 347 | static struct bus_type vio_bus_type = { |
395 | .name = "vio", | 348 | .name = "vio", |
396 | .dev_attrs = vio_dev_attrs, | 349 | .dev_attrs = vio_dev_attrs, |
397 | .uevent = vio_hotplug, | 350 | .uevent = vio_hotplug, |
398 | .match = vio_bus_match, | 351 | .match = vio_bus_match, |
399 | .probe = vio_bus_probe, | 352 | .probe = vio_bus_probe, |
400 | .remove = vio_bus_remove, | 353 | .remove = vio_bus_remove, |
401 | .shutdown = vio_bus_shutdown, | ||
402 | }; | 354 | }; |
403 | 355 | ||
404 | /** | 356 | /** |