diff options
Diffstat (limited to 'arch/powerpc/kernel/vio.c')
-rw-r--r-- | arch/powerpc/kernel/vio.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index fa3469ddaef8..1b695fdc362b 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -238,9 +238,7 @@ static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size) | |||
238 | * memory in this pool does not change. | 238 | * memory in this pool does not change. |
239 | */ | 239 | */ |
240 | if (spare_needed && reserve_freed) { | 240 | if (spare_needed && reserve_freed) { |
241 | tmp = min(spare_needed, min(reserve_freed, | 241 | tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT)); |
242 | (viodev->cmo.entitled - | ||
243 | VIO_CMO_MIN_ENT))); | ||
244 | 242 | ||
245 | vio_cmo.spare += tmp; | 243 | vio_cmo.spare += tmp; |
246 | viodev->cmo.entitled -= tmp; | 244 | viodev->cmo.entitled -= tmp; |
@@ -602,6 +600,11 @@ static void vio_dma_iommu_unmap_sg(struct device *dev, | |||
602 | vio_cmo_dealloc(viodev, alloc_size); | 600 | vio_cmo_dealloc(viodev, alloc_size); |
603 | } | 601 | } |
604 | 602 | ||
603 | static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask) | ||
604 | { | ||
605 | return dma_iommu_ops.dma_supported(dev, mask); | ||
606 | } | ||
607 | |||
605 | struct dma_map_ops vio_dma_mapping_ops = { | 608 | struct dma_map_ops vio_dma_mapping_ops = { |
606 | .alloc_coherent = vio_dma_iommu_alloc_coherent, | 609 | .alloc_coherent = vio_dma_iommu_alloc_coherent, |
607 | .free_coherent = vio_dma_iommu_free_coherent, | 610 | .free_coherent = vio_dma_iommu_free_coherent, |
@@ -609,6 +612,7 @@ struct dma_map_ops vio_dma_mapping_ops = { | |||
609 | .unmap_sg = vio_dma_iommu_unmap_sg, | 612 | .unmap_sg = vio_dma_iommu_unmap_sg, |
610 | .map_page = vio_dma_iommu_map_page, | 613 | .map_page = vio_dma_iommu_map_page, |
611 | .unmap_page = vio_dma_iommu_unmap_page, | 614 | .unmap_page = vio_dma_iommu_unmap_page, |
615 | .dma_supported = vio_dma_iommu_dma_supported, | ||
612 | 616 | ||
613 | }; | 617 | }; |
614 | 618 | ||
@@ -860,8 +864,7 @@ static void vio_cmo_bus_remove(struct vio_dev *viodev) | |||
860 | 864 | ||
861 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) | 865 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) |
862 | { | 866 | { |
863 | vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported; | 867 | set_dma_ops(&viodev->dev, &vio_dma_mapping_ops); |
864 | viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops; | ||
865 | } | 868 | } |
866 | 869 | ||
867 | /** | 870 | /** |
@@ -1184,7 +1187,12 @@ EXPORT_SYMBOL(vio_unregister_driver); | |||
1184 | /* vio_dev refcount hit 0 */ | 1187 | /* vio_dev refcount hit 0 */ |
1185 | static void __devinit vio_dev_release(struct device *dev) | 1188 | static void __devinit vio_dev_release(struct device *dev) |
1186 | { | 1189 | { |
1187 | /* XXX should free TCE table */ | 1190 | struct iommu_table *tbl = get_iommu_table_base(dev); |
1191 | |||
1192 | /* iSeries uses a common table for all vio devices */ | ||
1193 | if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl) | ||
1194 | iommu_free_table(tbl, dev->of_node ? | ||
1195 | dev->of_node->full_name : dev_name(dev)); | ||
1188 | of_node_put(dev->of_node); | 1196 | of_node_put(dev->of_node); |
1189 | kfree(to_vio_dev(dev)); | 1197 | kfree(to_vio_dev(dev)); |
1190 | } | 1198 | } |
@@ -1241,7 +1249,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1241 | if (firmware_has_feature(FW_FEATURE_CMO)) | 1249 | if (firmware_has_feature(FW_FEATURE_CMO)) |
1242 | vio_cmo_set_dma_ops(viodev); | 1250 | vio_cmo_set_dma_ops(viodev); |
1243 | else | 1251 | else |
1244 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | 1252 | set_dma_ops(&viodev->dev, &dma_iommu_ops); |
1245 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); | 1253 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); |
1246 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); | 1254 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); |
1247 | 1255 | ||
@@ -1249,13 +1257,16 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1249 | viodev->dev.parent = &vio_bus_device.dev; | 1257 | viodev->dev.parent = &vio_bus_device.dev; |
1250 | viodev->dev.bus = &vio_bus_type; | 1258 | viodev->dev.bus = &vio_bus_type; |
1251 | viodev->dev.release = vio_dev_release; | 1259 | viodev->dev.release = vio_dev_release; |
1260 | /* needed to ensure proper operation of coherent allocations | ||
1261 | * later, in case driver doesn't set it explicitly */ | ||
1262 | dma_set_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1263 | dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1252 | 1264 | ||
1253 | /* register with generic device framework */ | 1265 | /* register with generic device framework */ |
1254 | if (device_register(&viodev->dev)) { | 1266 | if (device_register(&viodev->dev)) { |
1255 | printk(KERN_ERR "%s: failed to register device %s\n", | 1267 | printk(KERN_ERR "%s: failed to register device %s\n", |
1256 | __func__, dev_name(&viodev->dev)); | 1268 | __func__, dev_name(&viodev->dev)); |
1257 | /* XXX free TCE table */ | 1269 | put_device(&viodev->dev); |
1258 | kfree(viodev); | ||
1259 | return NULL; | 1270 | return NULL; |
1260 | } | 1271 | } |
1261 | 1272 | ||