diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index f48e6f84eefeb..f47d16b5810b9 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -22,6 +22,7 @@ #include "vfio_ccw_private.h" struct workqueue_struct *vfio_ccw_work_q; +struct kmem_cache *vfio_ccw_io_region; /* * Helpers @@ -115,8 +116,8 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) if (!private) return -ENOMEM; - private->io_region = kzalloc(sizeof(*private->io_region), - GFP_KERNEL | GFP_DMA); + private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, + GFP_KERNEL | GFP_DMA); if (!private->io_region) { kfree(private); return -ENOMEM; @@ -147,7 +148,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) cio_disable_subchannel(sch); out_free: dev_set_drvdata(&sch->dev, NULL); - kfree(private->io_region); + kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private); return ret; } @@ -162,7 +163,7 @@ static int vfio_ccw_sch_remove(struct subchannel *sch) dev_set_drvdata(&sch->dev, NULL); - kfree(private->io_region); + kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private); return 0; @@ -242,10 +243,20 @@ static int __init vfio_ccw_sch_init(void) if (!vfio_ccw_work_q) return -ENOMEM; + vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region", + sizeof(struct ccw_io_region), 0, + SLAB_ACCOUNT, 0, + sizeof(struct ccw_io_region), NULL); + if (!vfio_ccw_io_region) { + destroy_workqueue(vfio_ccw_work_q); + return -ENOMEM; + } + isc_register(VFIO_CCW_ISC); ret = css_driver_register(&vfio_ccw_sch_driver); if (ret) { isc_unregister(VFIO_CCW_ISC); + kmem_cache_destroy(vfio_ccw_io_region); destroy_workqueue(vfio_ccw_work_q); } @@ -256,6 +267,7 @@ static void __exit vfio_ccw_sch_exit(void) { css_driver_unregister(&vfio_ccw_sch_driver); isc_unregister(VFIO_CCW_ISC); + kmem_cache_destroy(vfio_ccw_io_region); destroy_workqueue(vfio_ccw_work_q); } module_init(vfio_ccw_sch_init);