summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/vio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/vio.c')
-rw-r--r--arch/powerpc/kernel/vio.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index fa3469ddaef8..441d2a722f06 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)
* memory in this pool does not change.
*/
if (spare_needed && reserve_freed) {
- tmp = min(spare_needed, min(reserve_freed,
- (viodev->cmo.entitled -
- VIO_CMO_MIN_ENT)));
+ tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT));
vio_cmo.spare += tmp;
viodev->cmo.entitled -= tmp;
@@ -1184,7 +1182,12 @@ EXPORT_SYMBOL(vio_unregister_driver);
/* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev)
{
- /* XXX should free TCE table */
+ struct iommu_table *tbl = get_iommu_table_base(dev);
+
+ /* iSeries uses a common table for all vio devices */
+ if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl)
+ iommu_free_table(tbl, dev->of_node ?
+ dev->of_node->full_name : dev_name(dev));
of_node_put(dev->of_node);
kfree(to_vio_dev(dev));
}
@@ -1254,8 +1257,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
if (device_register(&viodev->dev)) {
printk(KERN_ERR "%s: failed to register device %s\n",
__func__, dev_name(&viodev->dev));
- /* XXX free TCE table */
- kfree(viodev);
+ put_device(&viodev->dev);
return NULL;
}