From patchwork Mon Feb 12 01:22:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolu Lu X-Patchwork-Id: 199578 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp2217758dyd; Sun, 11 Feb 2024 19:49:47 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCU82/Upw+Rj2CnqAbiSeL7fTzOem0c9wffrHYDHyZVMaoHeNJjfxkQvPLsLZyJF+mvOMZ4PJ2ObpF9mdBVOkK2KFAAq6A== X-Google-Smtp-Source: AGHT+IGGmzU8/rE+mzBOzDAYP15O3WbugcCLqeoxiU8bP7aeLshhpfoCyfeSZsz1AmGTPNsDKssL X-Received: by 2002:a17:902:ed93:b0:1d8:cbca:8fdd with SMTP id e19-20020a170902ed9300b001d8cbca8fddmr4169289plj.67.1707709787537; Sun, 11 Feb 2024 19:49:47 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707709787; cv=pass; d=google.com; s=arc-20160816; b=isL1C6mLsMuCk+lCgDJyzRLdQlCKGL8bpOEaXckLwoUW46gK3CJKSNciA9HPsyXpOl HXbIg6lNnXQIHQMjOn+iEY6yQjm+CBB5vahqyH3zvJ41I31QeCcYu18z+xacFvPPKCQV f2zfxtikskma8pb5VszVNBOrfQGYPVzd2N6MijMBbLYWjFCz5JMHSIdZtf/TXwkEG+Kj CdEtGEIgI16cyRp0iuCI2Rgqhu7zb2eeHJthAKs0cC2xrZ5KsM2x+wsMNXLp2iW1Pxm3 MRRpLxNo+bN8MfqmsSA85JudCAnFxPgsX76+dRt3ej7dnA1rWQj/d0kVwkZa1Ltc+iGC kvRw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=b75YhHm4DK+yjrf+X6NGNQ002tjK000BGpD7/tPl78I=; fh=TYSTbsrHLL5WnfigqEann9pzuq+5y9S6hPPbZrrNim8=; b=MLHOEkz6imxMWUSku+ndAcIbstaSZtxk80L+ACxYzzZdAPCu9GE5Sqp+r+5Oq+Mos0 rhiGU7RRMHF2xaTUeDQrKColGvhHZn1iqezu4emVgXj+WCF30tDgBQFxPsI/ykoxiXyD cqpEyphVryhdSzJLb4r2geItB71jB46AwMQEbq5baeD+8rFThGS5oC1J5t8Ecm2LwmT1 rXAiwSt/z+d+8H/Tp9pApEUyxM6w8LBxqz9pPP/Kho5DUcgGrAvmzGyUZi1OH4tiDwe7 N/mZGe+6bwYeFABJT97Pb2exOF8tCsfbwefpcD3kVeR5Cp0+hxstiqOy1zCWM9toDE9o yTtQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=izena+OB; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-61053-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-61053-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Forwarded-Encrypted: i=2; AJvYcCU54L/91sreQ8O43zgcBR7kjb9sJSfRMJO35Q0GGFkIko7IpY8CZK3+uAosyXcqNoCGL24L/ICzsg2IVi3KeaacblzYGg== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id q12-20020a170902a3cc00b001da15c5bbf5si4442486plb.38.2024.02.11.19.49.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Feb 2024 19:49:47 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-61053-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=izena+OB; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-61053-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-61053-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id B16C1287306 for ; Mon, 12 Feb 2024 01:32:52 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 636761803D; Mon, 12 Feb 2024 01:29:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="izena+OB" Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7389A17BAC; Mon, 12 Feb 2024 01:29:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707701350; cv=none; b=aET+LzURcgDcX/jfJxjQji77rLWjuHNX1q7rkWVUd1cnM7bjSeuZ3DQIrAfMUUgS5JGkkpacycQEY3UQjwjA2ppv0mT0BP4EtRd0DZ8q2k/H1WnAOHMoMJSk/t4RbsT4rbk++FhvxQAnTjISuIMaz36V+ac7BJERXfXwR+IAfuQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707701350; c=relaxed/simple; bh=dEgDV86cjZ8dp5JIAF0Is3+xbJXv/aIhdpY+Qja40O0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IeZQiVW/MjKrc4QrQMhQyRAr4mrTDhPX7o3bLg0ctBzvbUskVcXZmneoVa3Ucouxc52daOxuR47qPDaYA4WsVoBi0KKVmZRxAak3v0iTqYCsJIekGKM4rfvqhF80QQEy+z9X5aZkGKsWlmzQaKYTMrylpqnedRzmHnnlO1m4Doo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=izena+OB; arc=none smtp.client-ip=198.175.65.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1707701349; x=1739237349; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dEgDV86cjZ8dp5JIAF0Is3+xbJXv/aIhdpY+Qja40O0=; b=izena+OBPsei/VjHQaRtRCJjWMmpjpd1LoBAqSsbqYT0TqoU+WrbLoBc KQCmyihkGakAIPleO76Sn2V7+rUSaUDa3hd9X8uAX++ytwJgX01mBTvCy X9yl5QAfANbHbWGmL1VS7BUnj04OrYKZy/kQSe0RWx8ycxl5DLvE8r0OM /FGDnNApm1pLF3hlQpW47j8L/hFURNHu70WMdUcVi36QJqVzjGZCW3S/n DIpLd0OMerDE0lOCn7iX/mmXf4h48SP/EkF/B7cPwjfRUG5w11UQdwmAm cH7rV8xXfcZZHGaH3WNCWBFvimv79674v8+nQyCYGgnFhLkqH8puhqG4L w==; X-IronPort-AV: E=McAfee;i="6600,9927,10981"; a="5502188" X-IronPort-AV: E=Sophos;i="6.05,261,1701158400"; d="scan'208";a="5502188" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Feb 2024 17:29:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.05,261,1701158400"; d="scan'208";a="7132245" Received: from allen-box.sh.intel.com ([10.239.159.127]) by orviesa005.jf.intel.com with ESMTP; 11 Feb 2024 17:29:04 -0800 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian , Jean-Philippe Brucker , Nicolin Chen Cc: Yi Liu , Jacob Pan , Longfang Liu , Yan Zhao , Joel Granados , iommu@lists.linux.dev, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Lu Baolu , Jason Gunthorpe Subject: [PATCH v13 13/16] iommu: Improve iopf_queue_remove_device() Date: Mon, 12 Feb 2024 09:22:24 +0800 Message-Id: <20240212012227.119381-14-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240212012227.119381-1-baolu.lu@linux.intel.com> References: <20240212012227.119381-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790663497786298567 X-GMAIL-MSGID: 1790663497786298567 Convert iopf_queue_remove_device() to return void instead of an error code, as the return value is never used. This removal helper is designed to be never-failed, so there's no need for error handling. Ack all outstanding page requests from the device with the response code of IOMMU_PAGE_RESP_INVALID, indicating device should not attempt any retry. Add comments to this helper explaining the steps involved in removing a device from the iopf queue and disabling its PRI. The individual drivers are expected to be adjusted accordingly. Here we just define the expected behaviors of the individual iommu driver from the core's perspective. Suggested-by: Jason Gunthorpe Signed-off-by: Lu Baolu Reviewed-by: Jason Gunthorpe Tested-by: Yan Zhao --- include/linux/iommu.h | 5 ++-- drivers/iommu/intel/iommu.c | 7 +---- drivers/iommu/io-pgfault.c | 59 ++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 99cc55c3137f..7c60692d9cf2 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -1566,7 +1566,7 @@ iommu_sva_domain_alloc(struct device *dev, struct mm_struct *mm) #ifdef CONFIG_IOMMU_IOPF int iopf_queue_add_device(struct iopf_queue *queue, struct device *dev); -int iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev); +void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev); int iopf_queue_flush_dev(struct device *dev); struct iopf_queue *iopf_queue_alloc(const char *name); void iopf_queue_free(struct iopf_queue *queue); @@ -1582,10 +1582,9 @@ iopf_queue_add_device(struct iopf_queue *queue, struct device *dev) return -ENODEV; } -static inline int +static inline void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev) { - return -ENODEV; } static inline int iopf_queue_flush_dev(struct device *dev) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 29a12f289e2e..a81a2be9b870 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4455,12 +4455,7 @@ static int intel_iommu_disable_iopf(struct device *dev) */ pci_disable_pri(to_pci_dev(dev)); info->pri_enabled = 0; - - /* - * With PRI disabled and outstanding PRQs drained, removing device - * from iopf queue should never fail. - */ - WARN_ON(iopf_queue_remove_device(iommu->iopf_queue, dev)); + iopf_queue_remove_device(iommu->iopf_queue, dev); return 0; } diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c index ce7058892b59..ece09552e5cf 100644 --- a/drivers/iommu/io-pgfault.c +++ b/drivers/iommu/io-pgfault.c @@ -448,50 +448,67 @@ EXPORT_SYMBOL_GPL(iopf_queue_add_device); * @queue: IOPF queue * @dev: device to remove * - * Caller makes sure that no more faults are reported for this device. + * Removing a device from an iopf_queue. It's recommended to follow these + * steps when removing a device: * - * Return: 0 on success and <0 on error. + * - Disable new PRI reception: Turn off PRI generation in the IOMMU hardware + * and flush any hardware page request queues. This should be done before + * calling into this helper. + * - Acknowledge all outstanding PRQs to the device: Respond to all outstanding + * page requests with IOMMU_PAGE_RESP_INVALID, indicating the device should + * not retry. This helper function handles this. + * - Disable PRI on the device: After calling this helper, the caller could + * then disable PRI on the device. + * + * Calling iopf_queue_remove_device() essentially disassociates the device. + * The fault_param might still exist, but iommu_page_response() will do + * nothing. The device fault parameter reference count has been properly + * passed from iommu_report_device_fault() to the fault handling work, and + * will eventually be released after iommu_page_response(). */ -int iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev) +void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev) { - int ret = 0; struct iopf_fault *iopf, *next; + struct iommu_page_response resp; struct dev_iommu *param = dev->iommu; struct iommu_fault_param *fault_param; + const struct iommu_ops *ops = dev_iommu_ops(dev); mutex_lock(&queue->lock); mutex_lock(¶m->lock); fault_param = rcu_dereference_check(param->fault_param, lockdep_is_held(¶m->lock)); - if (!fault_param) { - ret = -ENODEV; - goto unlock; - } - - if (fault_param->queue != queue) { - ret = -EINVAL; - goto unlock; - } - if (!list_empty(&fault_param->faults)) { - ret = -EBUSY; + if (WARN_ON(!fault_param || fault_param->queue != queue)) goto unlock; - } - - list_del(&fault_param->queue_list); - /* Just in case some faults are still stuck */ + mutex_lock(&fault_param->lock); list_for_each_entry_safe(iopf, next, &fault_param->partial, list) kfree(iopf); + list_for_each_entry_safe(iopf, next, &fault_param->faults, list) { + memset(&resp, 0, sizeof(struct iommu_page_response)); + resp.pasid = iopf->fault.prm.pasid; + resp.grpid = iopf->fault.prm.grpid; + resp.code = IOMMU_PAGE_RESP_INVALID; + + if (iopf->fault.prm.flags & IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID) + resp.flags = IOMMU_PAGE_RESP_PASID_VALID; + + ops->page_response(dev, iopf, &resp); + list_del(&iopf->list); + kfree(iopf); + } + mutex_unlock(&fault_param->lock); + + list_del(&fault_param->queue_list); + /* dec the ref owned by iopf_queue_add_device() */ rcu_assign_pointer(param->fault_param, NULL); iopf_put_dev_fault_param(fault_param); unlock: mutex_unlock(¶m->lock); mutex_unlock(&queue->lock); - - return ret; } EXPORT_SYMBOL_GPL(iopf_queue_remove_device);