Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp4209322ybi; Tue, 11 Jun 2019 02:50:31 -0700 (PDT) X-Google-Smtp-Source: APXvYqxu5f/dPBKmbpw0b7OZg+GDeKGSfk1W3EPbXK/nlIkWotKOk36M90JYsv31AjaLk9rUYlLK X-Received: by 2002:a65:62c4:: with SMTP id m4mr20228036pgv.308.1560246630984; Tue, 11 Jun 2019 02:50:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560246630; cv=none; d=google.com; s=arc-20160816; b=SHDHE6mBEdwSj8yZR63rKzui5Qgvd8CgWg/wTRmWTT1Urqck1I1CnU3d0+BMgxr/K3 l5cGEal/sAf85EhrhzhhiDtSRgtcNT89clQPD3TFCoWO3Jr6JFEJHcNmU/ubR37pwB9S 4RCLKYmZpbv6xbEa5AUPGBPRmc+zgwSo9guIqtSZcYQESP/6WpQNUxZ/R8IIIzhOmMd0 P3IqQlT2qraYC5vy2m4lHwUbG8Ncgrts8GjWsL8jOfxNYtEAkBkjCNUuAEucE+TWA1RY 8W/pFsPuciVI/XMT9VFyYfBOFaZrP0UwzvIDG0NSBVYfQlHnF0cKFFg4CpLX1qYM09dY Pctw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :organization:references:in-reply-to:message-id:subject:cc:to:from :date; bh=t/U48xdE8RP+vItikTAfkzQ2JbJ43HmjSyOoIYCPvL0=; b=Y80nB/GrUjQ6e8NAapMoRkiK/ClPc7Fxx7TQZLEkkPTPTVl0+rE6nes7aO6554g+mh mC4oLn1LxNmAx/t/wZ/TYuYoIWlKD0s7KF2ypnBqLShCN9IpuSbI9qFC1o2i98C9X1oj 9Lyp5H+BRE0UlDA+jq7KXT9YE9bPk1qIasoSXQi2ON/dvfvanAa6aqEu3qMYhfLHNHNi fxsvOpV5ZZNq3OWWGXHwJN6IuqkXSThqyKHrE1mLMPP1UWZMEgBDA4yrmtBPYGyN10cT z1Ld7xv5KG5gCBo41KUUEV5A4LiyKgPfPup6BJEIE6jayA8FP3MMeSY0Kf2XYnQB31ys aSew== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d8si2039114pjw.3.2019.06.11.02.50.14; Tue, 11 Jun 2019 02:50:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404605AbfFKJgn (ORCPT + 99 others); Tue, 11 Jun 2019 05:36:43 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:18546 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2404137AbfFKJgm (ORCPT ); Tue, 11 Jun 2019 05:36:42 -0400 Received: from DGGEMS412-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id 7E1052B1E12D93060B1E; Tue, 11 Jun 2019 17:36:40 +0800 (CST) Received: from localhost (10.202.226.61) by DGGEMS412-HUB.china.huawei.com (10.3.19.212) with Microsoft SMTP Server id 14.3.439.0; Tue, 11 Jun 2019 17:36:35 +0800 Date: Tue, 11 Jun 2019 10:36:25 +0100 From: Jonathan Cameron To: Jean-Philippe Brucker CC: , , , , , , , Subject: Re: [PATCH 1/8] iommu: Add I/O ASID allocator Message-ID: <20190611103625.00001399@huawei.com> In-Reply-To: <20190610184714.6786-2-jean-philippe.brucker@arm.com> References: <20190610184714.6786-1-jean-philippe.brucker@arm.com> <20190610184714.6786-2-jean-philippe.brucker@arm.com> Organization: Huawei X-Mailer: Claws Mail 3.17.3 (GTK+ 2.24.32; i686-w64-mingw32) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.202.226.61] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 10 Jun 2019 19:47:07 +0100 Jean-Philippe Brucker wrote: > Some devices might support multiple DMA address spaces, in particular > those that have the PCI PASID feature. PASID (Process Address Space ID) > allows to share process address spaces with devices (SVA), partition a > device into VM-assignable entities (VFIO mdev) or simply provide > multiple DMA address space to kernel drivers. Add a global PASID > allocator usable by different drivers at the same time. Name it I/O ASID > to avoid confusion with ASIDs allocated by arch code, which are usually > a separate ID space. > > The IOASID space is global. Each device can have its own PASID space, > but by convention the IOMMU ended up having a global PASID space, so > that with SVA, each mm_struct is associated to a single PASID. > > The allocator is primarily used by IOMMU subsystem but in rare occasions > drivers would like to allocate PASIDs for devices that aren't managed by > an IOMMU, using the same ID space as IOMMU. > > Signed-off-by: Jean-Philippe Brucker > Signed-off-by: Jacob Pan Hi, A few trivial comments inline. May be more because I'm not that familiar with xa_array than anything else. Jonathan > --- > The most recent discussion on this patch was at: > https://lkml.kernel.org/lkml/1556922737-76313-4-git-send-email-jacob.jun.pan@linux.intel.com/ > I fixed it up a bit following comments in that series, and removed the > definitions for the custom allocator for now. > > There also is a new version that includes the custom allocator into this > patch, but is currently missing the RCU fixes, at: > https://lore.kernel.org/lkml/1560087862-57608-13-git-send-email-jacob.jun.pan@linux.intel.com/ > --- ... > + > +/** > + * ioasid_alloc - Allocate an IOASID > + * @set: the IOASID set > + * @min: the minimum ID (inclusive) > + * @max: the maximum ID (inclusive) > + * @private: data private to the caller > + * > + * Allocate an ID between @min and @max. The @private pointer is stored > + * internally and can be retrieved with ioasid_find(). > + * > + * Return: the allocated ID on success, or %INVALID_IOASID on failure. > + */ > +ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, > + void *private) > +{ > + u32 id = INVALID_IOASID; > + struct ioasid_data *data; > + > + data = kzalloc(sizeof(*data), GFP_KERNEL); > + 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); > + goto exit_free; > + } > + data->id = id; > + > +exit_free: This error flow is perhaps a little more confusing than it needs to be? My assumption (perhaps wrong) is that we only have an id == INVALID_IOASID if the xa_alloc fails, and that we will always have such an id value if it does (I'm not totally sure this second element is true in __xa_alloc). If I'm missing something perhaps a comment on how else we'd get here. > + if (id == INVALID_IOASID) { > + kfree(data); > + return INVALID_IOASID; > + } > + return id; > +} > +EXPORT_SYMBOL_GPL(ioasid_alloc); > + > +/** > + * ioasid_free - Free an IOASID > + * @ioasid: the ID to remove > + */ > +void ioasid_free(ioasid_t ioasid) > +{ > + struct ioasid_data *ioasid_data; > + > + ioasid_data = xa_erase(&ioasid_xa, ioasid); > + > + kfree_rcu(ioasid_data, rcu); > +} > +EXPORT_SYMBOL_GPL(ioasid_free); > + > +/** > + * ioasid_find - Find IOASID data > + * @set: the IOASID set > + * @ioasid: the IOASID to find > + * @getter: function to call on the found object > + * > + * The optional getter function allows to take a reference to the found object > + * under the rcu lock. The function can also check if the object is still valid: > + * if @getter returns false, then the object is invalid and NULL is returned. > + * > + * If the IOASID has been allocated for this set, return the private pointer > + * passed to ioasid_alloc. Private data can be NULL if not set. Return an error > + * if the IOASID is not found or does not belong to the set. Perhaps should make it clear that @set can be null. > + */ > +void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, > + bool (*getter)(void *)) > +{ > + void *priv = NULL; Set in all paths, so does need to be set here. > + struct ioasid_data *ioasid_data; > + > + rcu_read_lock(); > + ioasid_data = xa_load(&ioasid_xa, ioasid); > + if (!ioasid_data) { > + priv = ERR_PTR(-ENOENT); > + goto unlock; > + } > + if (set && ioasid_data->set != set) { > + /* data found but does not belong to the set */ > + priv = ERR_PTR(-EACCES); > + goto unlock; > + } > + /* Now IOASID and its set is verified, we can return the private data */ > + priv = rcu_dereference(ioasid_data->private); > + if (getter && !getter(priv)) > + priv = NULL; > +unlock: > + rcu_read_unlock(); > + > + return priv; > +} > +EXPORT_SYMBOL_GPL(ioasid_find); > + > +MODULE_LICENSE("GPL"); ...