diff
+static int allocate_io_tlb_mem(struct io_tlb_mem **mem_ptr, unsigned long nslabs, unsigned int nareas)
+{
+	struct io_tlb_mem *mem;
+	struct io_tlb_pool *pool;
+
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+	pool = &mem->defpool;
+
+	pool->slots = kcalloc(nslabs, sizeof(*pool->slots), GFP_KERNEL);
+	if (!pool->slots) {
+		kfree(mem);
+		return -ENOMEM;
+	}
+	pool->areas = kcalloc(nareas, sizeof(*pool->areas), GFP_KERNEL);
+	if (!pool->areas) {
+		kfree(pool->slots);
+		kfree(mem);
+		return -ENOMEM;
+	}
+
+	*mem_ptr = mem;
+	return 0;
+}
+
 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;
 	/* ... */
 	if (!mem) {
-		struct io_tlb_pool *pool;
-		/* ... allocation code ... */
+		ret = allocate_io_tlb_mem(&mem, nslabs, nareas);
+		if (ret)
+			return ret;
 	}
 	/* ... rest of the function ... */
 }
