Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp744827pxa; Fri, 21 Aug 2020 21:29:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzlZi0Dm9EMJQLZpO8Q5moDFE1lv/if1JNSLJ/cAXiydgOD10MlQggBeTmGZNqYdDRqjI/j X-Received: by 2002:a17:907:1050:: with SMTP id oy16mr5965943ejb.28.1598070596098; Fri, 21 Aug 2020 21:29:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1598070596; cv=none; d=google.com; s=arc-20160816; b=YAa4nRapWZrJHPzr/ggXXqAR74MxOroPY4JziI8ckWtXjIDjiifQ1vQ1nRF7wKnkDu wv9zfNlTUr5WCWs6nBmPIo6hkaZNK9ngotmDIDZywHrnx84W6Okcd4/mwONWOKfJO2jq AP3Rj7+rL1b9ZLz6c1o9ZUBVom6KoevphOB0FFxZRoJeTZTA/nRdoRNMIIhNqGwHSYdF IoO3VXz/YPzvK0hfaBrv5QryoLdTYYeOw2PhIPLgrB6dr9DlovZuwKD4dysHnDz80v0y kV1yUc5E3hfNtzLuWxQvksSvyuPFcIZK4RW+eeus9IgEvqeM+96GE+1zA0BW+8A7psNk sbbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=w7TbhItqwKixGiLvRC8dSaYe7kOA0K/CzHhPkWQGXvU=; b=NK/suYJ4RGayPVA5TzDA8ghT+jB3gbUR/c0CRwGZTkY8XxPxhR8XTSkTl2s6AjSXgA 56pC2xeAjz+ir+GiDJHpy6tAH4yk6iMh/P7cL3ap7k7w4M3LOhduED7oucl7STA0QWr5 zVYjFa3oZRHjBraxi2OsMT6CGuNzR8Az3fObaSOlsZuwF/8J8M/4LnyAkCjCKPCQ2z9A v6ySEcGqFHM6lxNv293ABzsT3V/RxOp7veZwFRBNykC0AuBHVT1v2302dpi30jjsDPh9 b5wFnj8ogPYbB8u6TXtr/GEJ5cNPaR5lplR7PWRdDEwwaE9gz/jEv4yT+PNXy3N7FxZQ DdFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=RV1DpLQk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bq18si2582310ejb.460.2020.08.21.21.29.33; Fri, 21 Aug 2020 21:29:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=RV1DpLQk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726830AbgHVE2w (ORCPT + 99 others); Sat, 22 Aug 2020 00:28:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725932AbgHVE2a (ORCPT ); Sat, 22 Aug 2020 00:28:30 -0400 Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D4FE2C061755 for ; Fri, 21 Aug 2020 21:28:29 -0700 (PDT) Received: by mail-pg1-x544.google.com with SMTP id j21so1932165pgi.9 for ; Fri, 21 Aug 2020 21:28:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=w7TbhItqwKixGiLvRC8dSaYe7kOA0K/CzHhPkWQGXvU=; b=RV1DpLQkpXzX35TlE91Ha03BuzgdBScDmkACaJqRjpLSeoB0IM1HGpcTnZwEArhZnL Pn4VrlsO/3QxDUCkMwgTkNqOC338rfS6UUbu145dBhoufkjzuZnNbW3DoWCb+1UuYIJ/ 1NOtV5B4rEO0UE+ndv2JctfFNW+SSHNMLpKd02hodc+BkBOS5cZMMbjoawe+xQMN8rMo YjTtzLdYN/KmqzQbpEStt32JsMJs0YS0woeR2+yoC1BDq6ruAakB0V6omRDgONiesk9U IElpJPeaVS9SHa7VhxLJ34rMWIdocxLVl3CScs9t/ruOPqX6FaMzbEmnNLLDDt4DeQ0Q 1zBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=w7TbhItqwKixGiLvRC8dSaYe7kOA0K/CzHhPkWQGXvU=; b=orFESZkUQJv+woXpIn/Idddbi932P0jYaAeJlfLwr9gt247DqJpY47qc6ucNH1tOhL M/WQCOxSx+8gmhXTnGXxrX09WSs2mdSItrtP9LhO0a/Kd0ZtkJRWcExOJ457Yuv7Qpsn IlFuKFt6XHW+IKqTIbwwkHhbpWVumI4Y5SGkidNjuaCw+9kmTnDYkYM7P9RcqfNrD+2X URrBVQnYixVshQB/5L/P29d2QMHK8pb7jj/AfW1/b7Jt/y6c6pd8VJ5LCCTWhBA9peo5 kGmH0IYo53fyC9EAXiRfsfhxb0JACTdVI6ovrSfkLsGHrPrWWZEshYm9vXhAtR2P0OYZ h77w== X-Gm-Message-State: AOAM530RmC3s3ht56xnmIKH35Ma4+tbUKdeTVUtuHkQKLwckqmMnToJe 1h5Z8Ukx4OmE3ywQ6Pet/PM= X-Received: by 2002:aa7:8608:: with SMTP id p8mr4912348pfn.62.1598070508123; Fri, 21 Aug 2020 21:28:28 -0700 (PDT) Received: from jacob-builder.jf.intel.com ([192.55.55.43]) by smtp.gmail.com with ESMTPSA id q5sm3341582pgi.31.2020.08.21.21.28.26 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 21 Aug 2020 21:28:27 -0700 (PDT) From: Jacob Pan X-Google-Original-From: Jacob Pan To: iommu@lists.linux-foundation.org, LKML , Jean-Philippe Brucker , "Lu Baolu" , Joerg Roedel , David Woodhouse Cc: Yi Liu , "Tian, Kevin" , Raj Ashok , Eric Auger , Wu Hao Subject: [PATCH v2 4/9] iommu/ioasid: Add reference couting functions Date: Fri, 21 Aug 2020 21:35:13 -0700 Message-Id: <1598070918-21321-5-git-send-email-jacob.jun.pan@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1598070918-21321-1-git-send-email-jacob.jun.pan@linux.intel.com> References: <1598070918-21321-1-git-send-email-jacob.jun.pan@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There can be multiple users of an IOASID, each user could have hardware contexts associated with the IOASID. In order to align lifecycles, reference counting is introduced in this patch. It is expected that when an IOASID is being freed, each user will drop a reference only after its context is cleared. Signed-off-by: Jacob Pan --- drivers/iommu/ioasid.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/ioasid.h | 4 ++ 2 files changed, 117 insertions(+) diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c index f73b3dbfc37a..5f31d63c75b1 100644 --- a/drivers/iommu/ioasid.c +++ b/drivers/iommu/ioasid.c @@ -717,6 +717,119 @@ int ioasid_set_for_each_ioasid(struct ioasid_set *set, EXPORT_SYMBOL_GPL(ioasid_set_for_each_ioasid); /** + * IOASID refcounting rules + * - ioasid_alloc() set initial refcount to 1 + * + * - ioasid_free() decrement and test refcount. + * If refcount is 0, ioasid will be freed. Deleted from the system-wide + * xarray as well as per set xarray. The IOASID will be returned to the + * pool and available for new allocations. + * + * If recount is non-zero, mark IOASID as IOASID_STATE_FREE_PENDING. + * No new reference can be added. The IOASID is not returned to the pool + * for reuse. + * After free, ioasid_get() will return error but ioasid_find() and other + * non refcount adding APIs will continue to work until the last reference + * is dropped + * + * - ioasid_get() get a reference on an active IOASID + * + * - ioasid_put() decrement and test refcount of the IOASID. + * If refcount is 0, ioasid will be freed. Deleted from the system-wide + * xarray as well as per set xarray. The IOASID will be returned to the + * pool and available for new allocations. + * Do nothing if refcount is non-zero. + * + * - ioasid_find() does not take reference, caller must hold reference + * + * ioasid_free() can be called multiple times without error until all refs are + * dropped. + */ + +int ioasid_get_locked(struct ioasid_set *set, ioasid_t ioasid) +{ + struct ioasid_data *data; + + data = xa_load(&active_allocator->xa, ioasid); + if (!data) { + pr_err("Trying to get unknown IOASID %u\n", ioasid); + return -EINVAL; + } + if (data->state == IOASID_STATE_FREE_PENDING) { + pr_err("Trying to get IOASID being freed%u\n", ioasid); + return -EBUSY; + } + + if (set && data->set != set) { + pr_err("Trying to get IOASID not in set%u\n", ioasid); + /* data found but does not belong to the set */ + return -EACCES; + } + refcount_inc(&data->users); + + return 0; +} +EXPORT_SYMBOL_GPL(ioasid_get_locked); + +/** + * ioasid_get - Obtain a reference of an ioasid + * @set + * @ioasid + * + * Check set ownership if @set is non-null. + */ +int ioasid_get(struct ioasid_set *set, ioasid_t ioasid) +{ + int ret = 0; + + spin_lock(&ioasid_allocator_lock); + ret = ioasid_get_locked(set, ioasid); + spin_unlock(&ioasid_allocator_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(ioasid_get); + +void ioasid_put_locked(struct ioasid_set *set, ioasid_t ioasid) +{ + struct ioasid_data *data; + + data = xa_load(&active_allocator->xa, ioasid); + if (!data) { + pr_err("Trying to put unknown IOASID %u\n", ioasid); + return; + } + + if (set && data->set != set) { + pr_err("Trying to drop IOASID not in the set %u\n", ioasid); + return; + } + + if (!refcount_dec_and_test(&data->users)) { + pr_debug("%s: IOASID %d has %d remainning users\n", + __func__, ioasid, refcount_read(&data->users)); + return; + } + ioasid_do_free(data); +} +EXPORT_SYMBOL_GPL(ioasid_put_locked); + +/** + * ioasid_put - Drop a reference of an ioasid + * @set + * @ioasid + * + * Check set ownership if @set is non-null. + */ +void ioasid_put(struct ioasid_set *set, ioasid_t ioasid) +{ + spin_lock(&ioasid_allocator_lock); + ioasid_put_locked(set, ioasid); + spin_unlock(&ioasid_allocator_lock); +} +EXPORT_SYMBOL_GPL(ioasid_put); + +/** * ioasid_find - Find IOASID data * @set: the IOASID set * @ioasid: the IOASID to find diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h index 412d025d440e..310abe4187a3 100644 --- a/include/linux/ioasid.h +++ b/include/linux/ioasid.h @@ -76,6 +76,10 @@ int ioasid_attach_data(ioasid_t ioasid, void *data); int ioasid_register_allocator(struct ioasid_allocator_ops *allocator); void ioasid_unregister_allocator(struct ioasid_allocator_ops *allocator); void ioasid_is_in_set(struct ioasid_set *set, ioasid_t ioasid); +int ioasid_get(struct ioasid_set *set, ioasid_t ioasid); +int ioasid_get_locked(struct ioasid_set *set, ioasid_t ioasid); +void ioasid_put(struct ioasid_set *set, ioasid_t ioasid); +void ioasid_put_locked(struct ioasid_set *set, ioasid_t ioasid); int ioasid_set_for_each_ioasid(struct ioasid_set *sdata, void (*fn)(ioasid_t id, void *data), void *data); -- 2.7.4