Hi Jacob, I have four tiny comments below but the patch looks great otherwise, no major concern from me.
On Sat, Sep 21, 2019 at 05:07:49PM -0700, Jacob Pan wrote: > +/* > + * struct ioasid_allocator_data - Internal data structure to hold information > + * about an allocator. There are two types of allocators: > + * > + * - Default allocator always has its own XArray to track the IOASIDs > allocated. > + * - Custom allocators may share allocation helpers with different private > data. > + * Custom allocators that share the same helper functions also share the > same > + * XArray. > + * Rules: > + * 1. Default allocator is always available, not dynamically registered. > This is > + * to prevent race conditions with early boot code that want to register > + * custom allocators or allocate IOASIDs. > + * 2. Custom allocators take precedence over the default allocator. > + * 3. When all custom allocators sharing the same helper functions are > + * unregistered (e.g. due to hotplug), all outstanding IOASIDs must be > + * freed. Otherwise, outstand IOASIDs will be lost and orphaned. outstanding [...] > ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, > void *private) > { > - ioasid_t id; > struct ioasid_data *data; > + void *adata; > + ioasid_t id; nit: changing the location of id could be in patch 2/4. > - data = kzalloc(sizeof(*data), GFP_KERNEL); > + data = kzalloc(sizeof(*data), GFP_ATOMIC); I don't think that one needs to be GFP_ATOMIC. Otherwise it should probably be done from the start, by patch 2/4. > if (!data) > return INVALID_IOASID; > > data->set = set; > data->private = private; > > - if (xa_alloc(&ioasid_xa, &id, data, XA_LIMIT(min, max), GFP_KERNEL)) { > - pr_err("Failed to alloc ioasid from %d to %d\n", min, max); > + /* > + * Custom allocator needs allocator data to perform platform specific > + * operations. > + */ > + spin_lock(&ioasid_allocator_lock); > + adata = active_allocator->flags & IOASID_ALLOCATOR_CUSTOM ? > active_allocator->ops->pdata : data; > + id = active_allocator->ops->alloc(min, max, adata); > + if (id == INVALID_IOASID) { > + pr_err("Failed ASID allocation %lu\n", active_allocator->flags); > + goto exit_free; > + } > + > + if ((active_allocator->flags & IOASID_ALLOCATOR_CUSTOM) && > + xa_alloc(&active_allocator->xa, &id, data, XA_LIMIT(id, id), > GFP_ATOMIC)) { nit: aligning at the "if (" would make this block more readable. > + /* Custom allocator needs framework to store and track > allocation results */ > + pr_err("Failed to alloc ioasid from %d\n", id); > + active_allocator->ops->free(id, active_allocator->ops->pdata); > goto exit_free; > } Thanks, Jean