Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp280294pxb; Thu, 7 Apr 2022 05:36:11 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzOEjHGXmtE1xP5FTIVH1S3oyhNwk5Uq6xAasYy/IPEEM2DYUpCLql6Pb10xwjXUwOTpekP X-Received: by 2002:a50:9f68:0:b0:41d:7de:f00 with SMTP id b95-20020a509f68000000b0041d07de0f00mr2843319edf.381.1649334971008; Thu, 07 Apr 2022 05:36:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649334971; cv=none; d=google.com; s=arc-20160816; b=h/AIbowIFwpTOb1+13oXQ/2lgZRxWmBanttkCmWPwgdnkNkzxht7/vhH9oHgsKPG+o HSMrfNDADazbB9iL2G7jxHTLWEP/dSZ+m3OsD225q/cDw5UXmRMDZhF9lOWnb6fovLCl 27t9DQxqAnNMgerxZ2FB/jIN0U1ptZ0gMxfDe74bA2ORXjuSItYFj5cX58Y57qaVfzqH G3kLa9hHNxFYe7Iy8CnaPoni+2yRRjnUnFCQAbQgnAtryokihbeqrEct1asg3TBltGgQ U+oeF7Oymn6AqFYoZD7qyFsVTT45yuopJMUwq4sPyuh+FyutnTtTkVUt3u+Bg9UrUTVK Aq4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:content-language :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject; bh=aPy/IOn5I56AN2AWTs71Iet2+pzXsqxganjN58ZTbgo=; b=csm8bcsRfiik6XfJ7j7+V6KjF7IGVcwLgrYwzV76apegUCr0S8p21Ofo5IT5NPmKUK g3Qd0EvLSVZPwcIsDV+Pi/PsxhrvSBPw+6Q3V2Y8eqHmVTVZRrFYdL3mcIFPaBmsUp+B hbH6lhxFKpV3zX0vfrxApzCiLqcqsUhEjBPIxzTGqqD787RwEmaMce6eYMdQ/bnRCSfs jFbk24WGipoI9VwdZWRvwRtcxuv1GSkKToeuLq9zSutj1xUgOGzpcbIAsNdKUbvvwC0j 8vMrzAqiTVATslDzB8aMey6cevFM6JuWI7GyVFCrMUE6s5dn1Q4m2dmDpDcYyZ9f9LEa J5Kg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o23-20020a170906289700b006dfe2af50fcsi14028515ejd.893.2022.04.07.05.35.19; Thu, 07 Apr 2022 05:36:10 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241989AbiDGHmT (ORCPT + 99 others); Thu, 7 Apr 2022 03:42:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43310 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231745AbiDGHmS (ORCPT ); Thu, 7 Apr 2022 03:42:18 -0400 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3036437A10 for ; Thu, 7 Apr 2022 00:40:17 -0700 (PDT) Received: from dggpemm500024.china.huawei.com (unknown [172.30.72.55]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4KYtXk6BHGzgYVj; Thu, 7 Apr 2022 15:38:30 +0800 (CST) Received: from dggpemm500006.china.huawei.com (7.185.36.236) by dggpemm500024.china.huawei.com (7.185.36.203) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Thu, 7 Apr 2022 15:40:15 +0800 Received: from [10.174.178.55] (10.174.178.55) by dggpemm500006.china.huawei.com (7.185.36.236) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Thu, 7 Apr 2022 15:40:14 +0800 Subject: Re: [PATCH RESEND v5 1/5] iommu: Refactor iommu_group_store_type() To: John Garry , , , CC: , , , , , , , References: <1649071634-188535-1-git-send-email-john.garry@huawei.com> <1649071634-188535-2-git-send-email-john.garry@huawei.com> From: "Leizhen (ThunderTown)" Message-ID: Date: Thu, 7 Apr 2022 15:40:14 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 MIME-Version: 1.0 In-Reply-To: <1649071634-188535-2-git-send-email-john.garry@huawei.com> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [10.174.178.55] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To dggpemm500006.china.huawei.com (7.185.36.236) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,NICE_REPLY_A, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Reviewed-by: Zhen Lei On 2022/4/4 19:27, John Garry wrote: > Function iommu_group_store_type() supports changing the default domain > of an IOMMU group. > > Many conditions need to be satisfied and steps taken for this action to be > successful. > > Satisfying these conditions and steps will be required for setting other > IOMMU group attributes, so factor into a common part and a part specific > to update the IOMMU group attribute. > > No functional change intended. > > Some code comments are tidied up also. > > Signed-off-by: John Garry > --- > drivers/iommu/iommu.c | 96 ++++++++++++++++++++++++++++--------------- > 1 file changed, 62 insertions(+), 34 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index f2c45b85b9fc..0dd766030baf 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -3000,21 +3000,57 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, > return ret; > } > > +enum iommu_group_op { > + CHANGE_GROUP_TYPE, > +}; > + > +static int __iommu_group_store_type(const char *buf, struct iommu_group *group, > + struct device *dev) > +{ > + int type; > + > + if (sysfs_streq(buf, "identity")) > + type = IOMMU_DOMAIN_IDENTITY; > + else if (sysfs_streq(buf, "DMA")) > + type = IOMMU_DOMAIN_DMA; > + else if (sysfs_streq(buf, "DMA-FQ")) > + type = IOMMU_DOMAIN_DMA_FQ; > + else if (sysfs_streq(buf, "auto")) > + type = 0; > + else > + return -EINVAL; > + > + /* > + * Check if the only device in the group still has a driver bound or > + * we're transistioning from DMA -> DMA-FQ > + */ > + if (device_is_bound(dev) && !(type == IOMMU_DOMAIN_DMA_FQ && > + group->default_domain->type == IOMMU_DOMAIN_DMA)) { > + pr_err_ratelimited("Device is still bound to driver\n"); > + return -EINVAL; > + } > + > + return iommu_change_dev_def_domain(group, dev, type); > +} > + > /* > * Changing the default domain through sysfs requires the users to unbind the > * drivers from the devices in the iommu group, except for a DMA -> DMA-FQ > - * transition. Return failure if this isn't met. > + * transition. Changing or any other IOMMU group attribute still requires the > + * user to unbind the drivers from the devices in the iommu group. Return > + * failure if these conditions are not met. > * > * We need to consider the race between this and the device release path. > * device_lock(dev) is used here to guarantee that the device release path > * will not be entered at the same time. > */ > -static ssize_t iommu_group_store_type(struct iommu_group *group, > - const char *buf, size_t count) > +static ssize_t iommu_group_store_common(struct iommu_group *group, > + enum iommu_group_op op, > + const char *buf, size_t count) > { > struct group_device *grp_dev; > struct device *dev; > - int ret, req_type; > + int ret; > > if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) > return -EACCES; > @@ -3022,27 +3058,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, > if (WARN_ON(!group)) > return -EINVAL; > > - if (sysfs_streq(buf, "identity")) > - req_type = IOMMU_DOMAIN_IDENTITY; > - else if (sysfs_streq(buf, "DMA")) > - req_type = IOMMU_DOMAIN_DMA; > - else if (sysfs_streq(buf, "DMA-FQ")) > - req_type = IOMMU_DOMAIN_DMA_FQ; > - else if (sysfs_streq(buf, "auto")) > - req_type = 0; > - else > - return -EINVAL; > - > /* > * Lock/Unlock the group mutex here before device lock to > - * 1. Make sure that the iommu group has only one device (this is a > + * 1. Make sure that the IOMMU group has only one device (this is a > * prerequisite for step 2) > * 2. Get struct *dev which is needed to lock device > */ > mutex_lock(&group->mutex); > if (iommu_group_device_count(group) != 1) { > mutex_unlock(&group->mutex); > - pr_err_ratelimited("Cannot change default domain: Group has more than one device\n"); > + pr_err_ratelimited("Cannot change IOMMU group default domain attribute: Group has more than one device\n"); > return -EINVAL; > } > > @@ -3054,16 +3079,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, > /* > * Don't hold the group mutex because taking group mutex first and then > * the device lock could potentially cause a deadlock as below. Assume > - * two threads T1 and T2. T1 is trying to change default domain of an > - * iommu group and T2 is trying to hot unplug a device or release [1] VF > - * of a PCIe device which is in the same iommu group. T1 takes group > - * mutex and before it could take device lock assume T2 has taken device > - * lock and is yet to take group mutex. Now, both the threads will be > - * waiting for the other thread to release lock. Below, lock order was > - * suggested. > + * two threads, T1 and T2. T1 is trying to change default domain > + * attribute of an IOMMU group and T2 is trying to hot unplug a device > + * or release [1] VF of a PCIe device which is in the same IOMMU group. > + * T1 takes the group mutex and before it could take device lock T2 may > + * have taken device lock and is yet to take group mutex. Now, both the > + * threads will be waiting for the other thread to release lock. Below, > + * lock order was suggested. > * device_lock(dev); > * mutex_lock(&group->mutex); > - * iommu_change_dev_def_domain(); > + * cb->iommu_change_dev_def_domain(); [example cb] > * mutex_unlock(&group->mutex); > * device_unlock(dev); > * > @@ -3077,21 +3102,24 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, > */ > mutex_unlock(&group->mutex); > > - /* Check if the device in the group still has a driver bound to it */ > device_lock(dev); > - if (device_is_bound(dev) && !(req_type == IOMMU_DOMAIN_DMA_FQ && > - group->default_domain->type == IOMMU_DOMAIN_DMA)) { > - pr_err_ratelimited("Device is still bound to driver\n"); > - ret = -EBUSY; > - goto out; > + switch (op) { > + case CHANGE_GROUP_TYPE: > + ret = __iommu_group_store_type(buf, group, dev); > + break; > + default: > + ret = -EINVAL; > } > - > - ret = iommu_change_dev_def_domain(group, dev, req_type); > ret = ret ?: count; > > -out: > device_unlock(dev); > put_device(dev); > > return ret; > } > + > +static ssize_t iommu_group_store_type(struct iommu_group *group, > + const char *buf, size_t count) > +{ > + return iommu_group_store_common(group, CHANGE_GROUP_TYPE, buf, count); > +} > -- Regards, Zhen Lei