diff
+static void cleanup_io_tlb_mem(struct io_tlb_mem *mem)
+{
+	if (mem) {
+		kfree(mem->defpool.areas);
+		kfree(mem->defpool.slots);
+		kfree(mem);
+	}
+}
+
 static int rmem_swiotlb_device_init(struct reserved_mem *rmem,
 				    struct device *dev)
 {
 	struct io_tlb_mem *mem = rmem->priv;
 	unsigned long nslabs = rmem->size >> IO_TLB_SHIFT;
+	int ret = 0;
 	/* ... */
 	if (!mem) {
 		struct io_tlb_pool *pool;
 
 		mem = kzalloc(sizeof(*mem), GFP_KERNEL);
-		if (!mem)
-			return -ENOMEM;
+		if (!mem) {
+			ret = -ENOMEM;
+			goto out;
+		}
 		pool = &mem->defpool;
 
 		pool->slots = kcalloc(nslabs, sizeof(*pool->slots), GFP_KERNEL);
 		if (!pool->slots) {
-			kfree(mem);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto out;
 		}
 		pool->areas = kcalloc(nareas, sizeof(*pool->areas),
 				GFP_KERNEL);
 		if (!pool->areas) {
-			kfree(pool->slots);
-			kfree(mem);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto out;
 		}
 	}
 	/* ... rest of the function ... */
+out:
+	if (ret)
+		cleanup_io_tlb_mem(mem);
+	return ret;
 }
