From patchwork Fri Aug 2 00:05:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140853 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606w52D6tz9sNx for ; Fri, 2 Aug 2019 10:09:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729739AbfHBAJB (ORCPT ); Thu, 1 Aug 2019 20:09:01 -0400 Received: from mga02.intel.com ([134.134.136.20]:59856 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728696AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993957" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 1/7] PCI/ATS: Fix pci_prg_resp_pasid_required() dependency issues Date: Thu, 1 Aug 2019 17:05:58 -0700 Message-Id: <0d7e0e0d079c438897f4da8cdca4b55994b1233b.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan Since pci_prg_resp_pasid_required() function has dependency on both PASID and PRI, define it only if both CONFIG_PCI_PRI and CONFIG_PCI_PASID config options are enabled. Fixes: e5567f5f6762 ("PCI/ATS: Add pci_prg_resp_pasid_required() interface.") Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 10 ++++++---- include/linux/pci-ats.h | 12 +++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index e18499243f84..cdd936d10f68 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -395,6 +395,8 @@ int pci_pasid_features(struct pci_dev *pdev) } EXPORT_SYMBOL_GPL(pci_pasid_features); +#ifdef CONFIG_PCI_PRI + /** * pci_prg_resp_pasid_required - Return PRG Response PASID Required bit * status. @@ -402,10 +404,8 @@ EXPORT_SYMBOL_GPL(pci_pasid_features); * * Returns 1 if PASID is required in PRG Response Message, 0 otherwise. * - * Even though the PRG response PASID status is read from PRI Status - * Register, since this API will mainly be used by PASID users, this - * function is defined within #ifdef CONFIG_PCI_PASID instead of - * CONFIG_PCI_PRI. + * Since this API has dependency on both PRI and PASID, protect it + * with both CONFIG_PCI_PRI and CONFIG_PCI_PASID. */ int pci_prg_resp_pasid_required(struct pci_dev *pdev) { @@ -425,6 +425,8 @@ int pci_prg_resp_pasid_required(struct pci_dev *pdev) } EXPORT_SYMBOL_GPL(pci_prg_resp_pasid_required); +#endif + #define PASID_NUMBER_SHIFT 8 #define PASID_NUMBER_MASK (0x1f << PASID_NUMBER_SHIFT) /** diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 1ebb88e7c184..1a0bdaee2f32 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -40,7 +40,6 @@ void pci_disable_pasid(struct pci_dev *pdev); void pci_restore_pasid_state(struct pci_dev *pdev); int pci_pasid_features(struct pci_dev *pdev); int pci_max_pasids(struct pci_dev *pdev); -int pci_prg_resp_pasid_required(struct pci_dev *pdev); #else /* CONFIG_PCI_PASID */ @@ -67,11 +66,18 @@ static inline int pci_max_pasids(struct pci_dev *pdev) return -EINVAL; } +#endif /* CONFIG_PCI_PASID */ + +#if defined(CONFIG_PCI_PRI) && defined(CONFIG_PCI_PASID) + +int pci_prg_resp_pasid_required(struct pci_dev *pdev); + +#else /* CONFIG_PCI_PASID && CONFIG_PCI_PRI */ + static inline int pci_prg_resp_pasid_required(struct pci_dev *pdev) { return 0; } -#endif /* CONFIG_PCI_PASID */ - +#endif #endif /* LINUX_PCI_ATS_H*/ From patchwork Fri Aug 2 00:05:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140852 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606vv5bfTz9sBF for ; Fri, 2 Aug 2019 10:08:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728888AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 Received: from mga02.intel.com ([134.134.136.20]:59857 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728794AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993958" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 2/7] PCI/ATS: Initialize PRI in pci_ats_init() Date: Thu, 1 Aug 2019 17:05:59 -0700 Message-Id: <3dd8c36177ac52d9a87655badb000d11785a5a4a.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan Currently, PRI Capability checks are repeated across all PRI API's. Instead, cache the capability check result in pci_pri_init() and use it in other PRI API's. Also, since PRI is a shared resource between PF/VF, initialize default values for common PRI features in pci_pri_init(). Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 80 ++++++++++++++++++++++++++++------------- include/linux/pci-ats.h | 5 +++ include/linux/pci.h | 1 + 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index cdd936d10f68..280be911f190 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -28,6 +28,8 @@ void pci_ats_init(struct pci_dev *dev) return; dev->ats_cap = pos; + + pci_pri_init(dev); } /** @@ -170,36 +172,72 @@ int pci_ats_page_aligned(struct pci_dev *pdev) EXPORT_SYMBOL_GPL(pci_ats_page_aligned); #ifdef CONFIG_PCI_PRI + +void pci_pri_init(struct pci_dev *pdev) +{ + u32 max_requests; + int pos; + + /* + * As per PCIe r4.0, sec 9.3.7.11, only PF is permitted to + * implement PRI and all associated VFs can only use it. + * Since PF already initialized the PRI parameters there is + * no need to proceed further. + */ + if (pdev->is_virtfn) + return; + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); + if (!pos) + return; + + pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests); + + /* + * Since PRI is a shared resource between PF and VF, we must not + * configure Outstanding Page Allocation Quota as a per device + * resource in pci_enable_pri(). So use maximum value possible + * as default value. + */ + pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, max_requests); + + pdev->pri_reqs_alloc = max_requests; + pdev->pri_cap = pos; +} + /** * pci_enable_pri - Enable PRI capability * @ pdev: PCI device structure * * Returns 0 on success, negative value on error + * + * TODO: Since PRI is a shared resource between PF/VF, don't update + * Outstanding Page Allocation Quota in the same API as a per device + * feature. */ int pci_enable_pri(struct pci_dev *pdev, u32 reqs) { u16 control, status; u32 max_requests; - int pos; if (WARN_ON(pdev->pri_enabled)) return -EBUSY; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) + if (!pdev->pri_cap) return -EINVAL; - pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); + pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_STATUS, &status); if (!(status & PCI_PRI_STATUS_STOPPED)) return -EBUSY; - pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests); + pci_read_config_dword(pdev, pdev->pri_cap + PCI_PRI_MAX_REQ, + &max_requests); reqs = min(max_requests, reqs); pdev->pri_reqs_alloc = reqs; - pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs); + pci_write_config_dword(pdev, pdev->pri_cap + PCI_PRI_ALLOC_REQ, reqs); control = PCI_PRI_CTRL_ENABLE; - pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); + pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); pdev->pri_enabled = 1; @@ -216,18 +254,16 @@ EXPORT_SYMBOL_GPL(pci_enable_pri); void pci_disable_pri(struct pci_dev *pdev) { u16 control; - int pos; if (WARN_ON(!pdev->pri_enabled)) return; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) + if (!pdev->pri_cap) return; - pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); + pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, &control); control &= ~PCI_PRI_CTRL_ENABLE; - pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); + pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); pdev->pri_enabled = 0; } @@ -241,17 +277,15 @@ void pci_restore_pri_state(struct pci_dev *pdev) { u16 control = PCI_PRI_CTRL_ENABLE; u32 reqs = pdev->pri_reqs_alloc; - int pos; if (!pdev->pri_enabled) return; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) + if (!pdev->pri_cap) return; - pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs); - pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); + pci_write_config_dword(pdev, pdev->pri_cap + PCI_PRI_ALLOC_REQ, reqs); + pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); } EXPORT_SYMBOL_GPL(pci_restore_pri_state); @@ -265,17 +299,15 @@ EXPORT_SYMBOL_GPL(pci_restore_pri_state); int pci_reset_pri(struct pci_dev *pdev) { u16 control; - int pos; if (WARN_ON(pdev->pri_enabled)) return -EBUSY; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) + if (!pdev->pri_cap) return -EINVAL; control = PCI_PRI_CTRL_RESET; - pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); + pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); return 0; } @@ -410,13 +442,11 @@ EXPORT_SYMBOL_GPL(pci_pasid_features); int pci_prg_resp_pasid_required(struct pci_dev *pdev) { u16 status; - int pos; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) + if (!pdev->pri_cap) return 0; - pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); + pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_STATUS, &status); if (status & PCI_PRI_STATUS_PASID) return 1; diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 1a0bdaee2f32..33653d4ca94f 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -6,6 +6,7 @@ #ifdef CONFIG_PCI_PRI +void pci_pri_init(struct pci_dev *pdev); int pci_enable_pri(struct pci_dev *pdev, u32 reqs); void pci_disable_pri(struct pci_dev *pdev); void pci_restore_pri_state(struct pci_dev *pdev); @@ -13,6 +14,10 @@ int pci_reset_pri(struct pci_dev *pdev); #else /* CONFIG_PCI_PRI */ +static inline void pci_pri_init(struct pci_dev *pdev) +{ +} + static inline int pci_enable_pri(struct pci_dev *pdev, u32 reqs) { return -ENODEV; diff --git a/include/linux/pci.h b/include/linux/pci.h index 9e700d9f9f28..56b55db099fc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -455,6 +455,7 @@ struct pci_dev { atomic_t ats_ref_cnt; /* Number of VFs with ATS enabled */ #endif #ifdef CONFIG_PCI_PRI + u16 pri_cap; /* PRI Capability offset */ u32 pri_reqs_alloc; /* Number of PRI requests allocated */ #endif #ifdef CONFIG_PCI_PASID From patchwork Fri Aug 2 00:06:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140851 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606vv0DyMz9s7T for ; Fri, 2 Aug 2019 10:08:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729411AbfHBAIw (ORCPT ); Thu, 1 Aug 2019 20:08:52 -0400 Received: from mga02.intel.com ([134.134.136.20]:59856 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727604AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993961" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 3/7] PCI/ATS: Initialize PASID in pci_ats_init() Date: Thu, 1 Aug 2019 17:06:00 -0700 Message-Id: <5edb0209f7657e0706d4e5305ea0087873603daf.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan Currently, PASID Capability checks are repeated across all PASID API's. Instead, cache the capability check result in pci_pasid_init() and use it in other PASID API's. Also, since PASID is a shared resource between PF/VF, initialize PASID features with default values in pci_pasid_init(). Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 74 +++++++++++++++++++++++++++++------------ include/linux/pci-ats.h | 5 +++ include/linux/pci.h | 1 + 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 280be911f190..1f4be27a071d 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -30,6 +30,8 @@ void pci_ats_init(struct pci_dev *dev) dev->ats_cap = pos; pci_pri_init(dev); + + pci_pasid_init(dev); } /** @@ -315,6 +317,40 @@ EXPORT_SYMBOL_GPL(pci_reset_pri); #endif /* CONFIG_PCI_PRI */ #ifdef CONFIG_PCI_PASID + +void pci_pasid_init(struct pci_dev *pdev) +{ + u16 supported; + int pos; + + /* + * As per PCIe r4.0, sec 9.3.7.14, only PF is permitted to + * implement PASID Capability and all associated VFs can + * only use it. Since PF already initialized the PASID + * parameters there is no need to proceed further. + */ + if (pdev->is_virtfn) + return; + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); + if (!pos) + return; + + pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); + + supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; + + /* + * Enable all supported features. Since PASID is a shared + * resource between PF/VF, we must not set this feature as + * a per device property in pci_enable_pasid(). + */ + pci_write_config_word(pdev, pos + PCI_PASID_CTRL, supported); + + pdev->pasid_features = supported; + pdev->pasid_cap = pos; +} + /** * pci_enable_pasid - Enable the PASID capability * @pdev: PCI device structure @@ -323,11 +359,13 @@ EXPORT_SYMBOL_GPL(pci_reset_pri); * Returns 0 on success, negative value on error. This function checks * whether the features are actually supported by the device and returns * an error if not. + * + * TODO: Since PASID is a shared resource between PF/VF, don't update + * PASID features in the same API as a per device feature. */ int pci_enable_pasid(struct pci_dev *pdev, int features) { u16 control, supported; - int pos; if (WARN_ON(pdev->pasid_enabled)) return -EBUSY; @@ -335,11 +373,11 @@ int pci_enable_pasid(struct pci_dev *pdev, int features) if (!pdev->eetlp_prefix_path) return -EINVAL; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); - if (!pos) + if (!pdev->pasid_cap) return -EINVAL; - pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); + pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, + &supported); supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; /* User wants to enable anything unsupported? */ @@ -349,7 +387,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features) control = PCI_PASID_CTRL_ENABLE | features; pdev->pasid_features = features; - pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); + pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); pdev->pasid_enabled = 1; @@ -364,16 +402,14 @@ EXPORT_SYMBOL_GPL(pci_enable_pasid); void pci_disable_pasid(struct pci_dev *pdev) { u16 control = 0; - int pos; if (WARN_ON(!pdev->pasid_enabled)) return; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); - if (!pos) + if (!pdev->pasid_cap) return; - pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); + pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); pdev->pasid_enabled = 0; } @@ -386,17 +422,15 @@ EXPORT_SYMBOL_GPL(pci_disable_pasid); void pci_restore_pasid_state(struct pci_dev *pdev) { u16 control; - int pos; if (!pdev->pasid_enabled) return; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); - if (!pos) + if (!pdev->pasid_cap) return; control = PCI_PASID_CTRL_ENABLE | pdev->pasid_features; - pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); + pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); } EXPORT_SYMBOL_GPL(pci_restore_pasid_state); @@ -413,13 +447,12 @@ EXPORT_SYMBOL_GPL(pci_restore_pasid_state); int pci_pasid_features(struct pci_dev *pdev) { u16 supported; - int pos; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); - if (!pos) + if (!pdev->pasid_cap) return -EINVAL; - pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); + pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, + &supported); supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; @@ -469,13 +502,12 @@ EXPORT_SYMBOL_GPL(pci_prg_resp_pasid_required); int pci_max_pasids(struct pci_dev *pdev) { u16 supported; - int pos; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); - if (!pos) + if (!pdev->pasid_cap) return -EINVAL; - pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); + pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, + &supported); supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT; diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 33653d4ca94f..bc7f815d38ff 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -40,6 +40,7 @@ static inline int pci_reset_pri(struct pci_dev *pdev) #ifdef CONFIG_PCI_PASID +void pci_pasid_init(struct pci_dev *pdev); int pci_enable_pasid(struct pci_dev *pdev, int features); void pci_disable_pasid(struct pci_dev *pdev); void pci_restore_pasid_state(struct pci_dev *pdev); @@ -48,6 +49,10 @@ int pci_max_pasids(struct pci_dev *pdev); #else /* CONFIG_PCI_PASID */ +static inline void pci_pasid_init(struct pci_dev *pdev) +{ +} + static inline int pci_enable_pasid(struct pci_dev *pdev, int features) { return -EINVAL; diff --git a/include/linux/pci.h b/include/linux/pci.h index 56b55db099fc..27224c0db849 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -459,6 +459,7 @@ struct pci_dev { u32 pri_reqs_alloc; /* Number of PRI requests allocated */ #endif #ifdef CONFIG_PCI_PASID + u16 pasid_cap; /* PASID Capability offset */ u16 pasid_features; #endif #ifdef CONFIG_PCI_P2PDMA From patchwork Fri Aug 2 00:06:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140855 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606w76rK7z9sNx for ; Fri, 2 Aug 2019 10:09:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729929AbfHBAJK (ORCPT ); Thu, 1 Aug 2019 20:09:10 -0400 Received: from mga02.intel.com ([134.134.136.20]:59857 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728268AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993965" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 4/7] PCI/ATS: Add PRI support for PCIe VF devices Date: Thu, 1 Aug 2019 17:06:01 -0700 Message-Id: <827d051ef8c8bbfa815908ce927e607870780cb6.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan When IOMMU tries to enable Page Request Interface (PRI) for VF device in iommu_enable_dev_iotlb(), it always fails because PRI support for PCIe VF device is currently broken. Current implementation expects the given PCIe device (PF & VF) to implement PRI capability before enabling the PRI support. But this assumption is incorrect. As per PCIe spec r4.0, sec 9.3.7.11, all VFs associated with PF can only use the PRI of the PF and not implement it. Hence we need to create exception for handling the PRI support for PCIe VF device. Also, since PRI is a shared resource between PF/VF, following rules should apply. 1. Use proper locking before accessing/modifying PF resources in VF PRI enable/disable call. 2. Use reference count logic to track the usage of PRI resource. 3. Disable PRI only if the PRI reference count (pri_ref_cnt) is zero. Cc: Ashok Raj Cc: Keith Busch Suggested-by: Ashok Raj Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 143 ++++++++++++++++++++++++++++++++++---------- include/linux/pci.h | 2 + 2 files changed, 112 insertions(+), 33 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 1f4be27a071d..079dc5444444 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -189,6 +189,8 @@ void pci_pri_init(struct pci_dev *pdev) if (pdev->is_virtfn) return; + mutex_init(&pdev->pri_lock); + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); if (!pos) return; @@ -221,29 +223,57 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs) { u16 control, status; u32 max_requests; + int ret = 0; + struct pci_dev *pf = pci_physfn(pdev); - if (WARN_ON(pdev->pri_enabled)) - return -EBUSY; + mutex_lock(&pf->pri_lock); - if (!pdev->pri_cap) - return -EINVAL; + if (WARN_ON(pdev->pri_enabled)) { + ret = -EBUSY; + goto pri_unlock; + } - pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_STATUS, &status); - if (!(status & PCI_PRI_STATUS_STOPPED)) - return -EBUSY; + if (!pf->pri_cap) { + ret = -EINVAL; + goto pri_unlock; + } + + if (pdev->is_virtfn && pf->pri_enabled) + goto update_status; + + /* + * Before updating PRI registers, make sure there is no + * outstanding PRI requests. + */ + pci_read_config_word(pf, pf->pri_cap + PCI_PRI_STATUS, &status); + if (!(status & PCI_PRI_STATUS_STOPPED)) { + ret = -EBUSY; + goto pri_unlock; + } - pci_read_config_dword(pdev, pdev->pri_cap + PCI_PRI_MAX_REQ, - &max_requests); + pci_read_config_dword(pf, pf->pri_cap + PCI_PRI_MAX_REQ, &max_requests); reqs = min(max_requests, reqs); - pdev->pri_reqs_alloc = reqs; - pci_write_config_dword(pdev, pdev->pri_cap + PCI_PRI_ALLOC_REQ, reqs); + pf->pri_reqs_alloc = reqs; + pci_write_config_dword(pf, pf->pri_cap + PCI_PRI_ALLOC_REQ, reqs); control = PCI_PRI_CTRL_ENABLE; - pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); + pci_write_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, control); - pdev->pri_enabled = 1; + /* + * If PRI is not already enabled in PF, increment the PF + * pri_ref_cnt to track the usage of PRI interface. + */ + if (pdev->is_virtfn && !pf->pri_enabled) { + atomic_inc(&pf->pri_ref_cnt); + pf->pri_enabled = 1; + } - return 0; +update_status: + atomic_inc(&pf->pri_ref_cnt); + pdev->pri_enabled = 1; +pri_unlock: + mutex_unlock(&pf->pri_lock); + return ret; } EXPORT_SYMBOL_GPL(pci_enable_pri); @@ -256,18 +286,30 @@ EXPORT_SYMBOL_GPL(pci_enable_pri); void pci_disable_pri(struct pci_dev *pdev) { u16 control; + struct pci_dev *pf = pci_physfn(pdev); - if (WARN_ON(!pdev->pri_enabled)) - return; + mutex_lock(&pf->pri_lock); - if (!pdev->pri_cap) - return; + if (WARN_ON(!pdev->pri_enabled) || !pf->pri_cap) + goto pri_unlock; + + atomic_dec(&pf->pri_ref_cnt); - pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, &control); + /* + * If pri_ref_cnt is not zero, then don't modify hardware + * registers. + */ + if (atomic_read(&pf->pri_ref_cnt)) + goto done; + + pci_read_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, &control); control &= ~PCI_PRI_CTRL_ENABLE; - pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); + pci_write_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, control); +done: pdev->pri_enabled = 0; +pri_unlock: + mutex_unlock(&pf->pri_lock); } EXPORT_SYMBOL_GPL(pci_disable_pri); @@ -277,17 +319,31 @@ EXPORT_SYMBOL_GPL(pci_disable_pri); */ void pci_restore_pri_state(struct pci_dev *pdev) { - u16 control = PCI_PRI_CTRL_ENABLE; - u32 reqs = pdev->pri_reqs_alloc; + u16 control; + u32 reqs; + struct pci_dev *pf = pci_physfn(pdev); if (!pdev->pri_enabled) return; - if (!pdev->pri_cap) + if (!pf->pri_cap) return; - pci_write_config_dword(pdev, pdev->pri_cap + PCI_PRI_ALLOC_REQ, reqs); - pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); + mutex_lock(&pf->pri_lock); + + /* If PRI is already enabled by other VF's or PF, return */ + pci_read_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, &control); + if (control & PCI_PRI_CTRL_ENABLE) + goto pri_unlock; + + reqs = pf->pri_reqs_alloc; + control = PCI_PRI_CTRL_ENABLE; + + pci_write_config_dword(pf, pf->pri_cap + PCI_PRI_ALLOC_REQ, reqs); + pci_write_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, control); + +pri_unlock: + mutex_unlock(&pf->pri_lock); } EXPORT_SYMBOL_GPL(pci_restore_pri_state); @@ -300,18 +356,32 @@ EXPORT_SYMBOL_GPL(pci_restore_pri_state); */ int pci_reset_pri(struct pci_dev *pdev) { + struct pci_dev *pf = pci_physfn(pdev); u16 control; + int ret = 0; - if (WARN_ON(pdev->pri_enabled)) - return -EBUSY; + mutex_lock(&pf->pri_lock); - if (!pdev->pri_cap) - return -EINVAL; + if (WARN_ON(pdev->pri_enabled)) { + ret = -EBUSY; + goto done; + } + + if (!pf->pri_cap) { + ret = -EINVAL; + goto done; + } + + /* If PRI is already enabled by other VF's or PF, return 0 */ + if (pf->pri_enabled) + goto done; control = PCI_PRI_CTRL_RESET; - pci_write_config_word(pdev, pdev->pri_cap + PCI_PRI_CTRL, control); - return 0; + pci_write_config_word(pf, pf->pri_cap + PCI_PRI_CTRL, control); +done: + mutex_unlock(&pf->pri_lock); + return ret; } EXPORT_SYMBOL_GPL(pci_reset_pri); #endif /* CONFIG_PCI_PRI */ @@ -475,11 +545,18 @@ EXPORT_SYMBOL_GPL(pci_pasid_features); int pci_prg_resp_pasid_required(struct pci_dev *pdev) { u16 status; + struct pci_dev *pf = pci_physfn(pdev); + + mutex_lock(&pf->pri_lock); - if (!pdev->pri_cap) + if (!pf->pri_cap) { + mutex_unlock(&pf->pri_lock); return 0; + } + + pci_read_config_word(pf, pf->pri_cap + PCI_PRI_STATUS, &status); - pci_read_config_word(pdev, pdev->pri_cap + PCI_PRI_STATUS, &status); + mutex_unlock(&pf->pri_lock); if (status & PCI_PRI_STATUS_PASID) return 1; diff --git a/include/linux/pci.h b/include/linux/pci.h index 27224c0db849..3c9c4c82be27 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -455,8 +455,10 @@ struct pci_dev { atomic_t ats_ref_cnt; /* Number of VFs with ATS enabled */ #endif #ifdef CONFIG_PCI_PRI + struct mutex pri_lock; /* PRI enable lock */ u16 pri_cap; /* PRI Capability offset */ u32 pri_reqs_alloc; /* Number of PRI requests allocated */ + atomic_t pri_ref_cnt; /* Number of PF/VF PRI users */ #endif #ifdef CONFIG_PCI_PASID u16 pasid_cap; /* PASID Capability offset */ From patchwork Fri Aug 2 00:06:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140856 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606w93xlSz9s7T for ; Fri, 2 Aug 2019 10:09:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730049AbfHBAJL (ORCPT ); Thu, 1 Aug 2019 20:09:11 -0400 Received: from mga02.intel.com ([134.134.136.20]:59856 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726340AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993968" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 5/7] PCI/ATS: Add PASID support for PCIe VF devices Date: Thu, 1 Aug 2019 17:06:02 -0700 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan When IOMMU tries to enable PASID for VF device in iommu_enable_dev_iotlb(), it always fails because PASID support for PCIe VF device is currently broken in PCIE driver. Current implementation expects the given PCIe device (PF & VF) to implement PASID capability before enabling the PASID support. But this assumption is incorrect. As per PCIe spec r4.0, sec 9.3.7.14, all VFs associated with PF can only use the PASID of the PF and not implement it. Also, since PASID is a shared resource between PF/VF, following rules should apply. 1. Use proper locking before accessing/modifying PF resources in VF PASID enable/disable call. 2. Use reference count logic to track the usage of PASID resource. 3. Disable PASID only if the PASID reference count (pasid_ref_cnt) is zero. Cc: Ashok Raj Cc: Keith Busch Suggested-by: Ashok Raj Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 113 ++++++++++++++++++++++++++++++++++---------- include/linux/pci.h | 2 + 2 files changed, 90 insertions(+), 25 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 079dc5444444..9384afd7d00e 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -402,6 +402,8 @@ void pci_pasid_init(struct pci_dev *pdev) if (pdev->is_virtfn) return; + mutex_init(&pdev->pasid_lock); + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); if (!pos) return; @@ -436,32 +438,57 @@ void pci_pasid_init(struct pci_dev *pdev) int pci_enable_pasid(struct pci_dev *pdev, int features) { u16 control, supported; + int ret = 0; + struct pci_dev *pf = pci_physfn(pdev); - if (WARN_ON(pdev->pasid_enabled)) - return -EBUSY; + mutex_lock(&pf->pasid_lock); - if (!pdev->eetlp_prefix_path) - return -EINVAL; + if (WARN_ON(pdev->pasid_enabled)) { + ret = -EBUSY; + goto pasid_unlock; + } - if (!pdev->pasid_cap) - return -EINVAL; + if (!pdev->eetlp_prefix_path) { + ret = -EINVAL; + goto pasid_unlock; + } - pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, - &supported); + if (!pf->pasid_cap) { + ret = -EINVAL; + goto pasid_unlock; + } + + if (pdev->is_virtfn && pf->pasid_enabled) + goto update_status; + + pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CAP, &supported); supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; /* User wants to enable anything unsupported? */ - if ((supported & features) != features) - return -EINVAL; + if ((supported & features) != features) { + ret = -EINVAL; + goto pasid_unlock; + } control = PCI_PASID_CTRL_ENABLE | features; - pdev->pasid_features = features; - + pf->pasid_features = features; pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); - pdev->pasid_enabled = 1; + /* + * If PASID is not already enabled in PF, increment pasid_ref_cnt + * to count PF PASID usage. + */ + if (pdev->is_virtfn && !pf->pasid_enabled) { + atomic_inc(&pf->pasid_ref_cnt); + pf->pasid_enabled = 1; + } - return 0; +update_status: + atomic_inc(&pf->pasid_ref_cnt); + pdev->pasid_enabled = 1; +pasid_unlock: + mutex_unlock(&pf->pasid_lock); + return ret; } EXPORT_SYMBOL_GPL(pci_enable_pasid); @@ -472,16 +499,29 @@ EXPORT_SYMBOL_GPL(pci_enable_pasid); void pci_disable_pasid(struct pci_dev *pdev) { u16 control = 0; + struct pci_dev *pf = pci_physfn(pdev); + + mutex_lock(&pf->pasid_lock); if (WARN_ON(!pdev->pasid_enabled)) - return; + goto pasid_unlock; - if (!pdev->pasid_cap) - return; + if (!pf->pasid_cap) + goto pasid_unlock; - pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); + atomic_dec(&pf->pasid_ref_cnt); + if (atomic_read(&pf->pasid_ref_cnt)) + goto done; + + /* Disable PASID only if pasid_ref_cnt is zero */ + pci_write_config_word(pf, pf->pasid_cap + PCI_PASID_CTRL, control); + +done: pdev->pasid_enabled = 0; +pasid_unlock: + mutex_unlock(&pf->pasid_lock); + } EXPORT_SYMBOL_GPL(pci_disable_pasid); @@ -492,15 +532,25 @@ EXPORT_SYMBOL_GPL(pci_disable_pasid); void pci_restore_pasid_state(struct pci_dev *pdev) { u16 control; + struct pci_dev *pf = pci_physfn(pdev); if (!pdev->pasid_enabled) return; - if (!pdev->pasid_cap) + if (!pf->pasid_cap) return; + mutex_lock(&pf->pasid_lock); + + pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CTRL, &control); + if (control & PCI_PASID_CTRL_ENABLE) + goto pasid_unlock; + control = PCI_PASID_CTRL_ENABLE | pdev->pasid_features; - pci_write_config_word(pdev, pdev->pasid_cap + PCI_PASID_CTRL, control); + pci_write_config_word(pf, pf->pasid_cap + PCI_PASID_CTRL, control); + +pasid_unlock: + mutex_unlock(&pf->pasid_lock); } EXPORT_SYMBOL_GPL(pci_restore_pasid_state); @@ -517,15 +567,22 @@ EXPORT_SYMBOL_GPL(pci_restore_pasid_state); int pci_pasid_features(struct pci_dev *pdev) { u16 supported; + struct pci_dev *pf = pci_physfn(pdev); + + mutex_lock(&pf->pasid_lock); - if (!pdev->pasid_cap) + if (!pf->pasid_cap) { + mutex_unlock(&pf->pasid_lock); return -EINVAL; + } - pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, + pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CAP, &supported); supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; + mutex_unlock(&pf->pasid_lock); + return supported; } EXPORT_SYMBOL_GPL(pci_pasid_features); @@ -579,15 +636,21 @@ EXPORT_SYMBOL_GPL(pci_prg_resp_pasid_required); int pci_max_pasids(struct pci_dev *pdev) { u16 supported; + struct pci_dev *pf = pci_physfn(pdev); + + mutex_lock(&pf->pasid_lock); - if (!pdev->pasid_cap) + if (!pf->pasid_cap) { + mutex_unlock(&pf->pasid_lock); return -EINVAL; + } - pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP, - &supported); + pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CAP, &supported); supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT; + mutex_unlock(&pf->pasid_lock); + return (1 << supported); } EXPORT_SYMBOL_GPL(pci_max_pasids); diff --git a/include/linux/pci.h b/include/linux/pci.h index 3c9c4c82be27..4bfcca045afd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -461,8 +461,10 @@ struct pci_dev { atomic_t pri_ref_cnt; /* Number of PF/VF PRI users */ #endif #ifdef CONFIG_PCI_PASID + struct mutex pasid_lock; /* PASID enable lock */ u16 pasid_cap; /* PASID Capability offset */ u16 pasid_features; + atomic_t pasid_ref_cnt; /* Number of VFs with PASID enabled */ #endif #ifdef CONFIG_PCI_P2PDMA struct pci_p2pdma *p2pdma; From patchwork Fri Aug 2 00:06:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140854 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606w71qmpz9s7T for ; Fri, 2 Aug 2019 10:09:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728662AbfHBAIr (ORCPT ); Thu, 1 Aug 2019 20:08:47 -0400 Received: from mga02.intel.com ([134.134.136.20]:59856 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726997AbfHBAIq (ORCPT ); Thu, 1 Aug 2019 20:08:46 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993971" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 6/7] PCI/ATS: Disable PF/VF ATS service independently Date: Thu, 1 Aug 2019 17:06:03 -0700 Message-Id: <2407a2a39a4bb1e3904ebfda8ebaec3d88741082.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan Currently all VF's needs to be disable their ATS service before disabling the ATS service in corresponding PF device. But this logic is incorrect and does not align with the spec. Also it might lead to some power and performance impact in the system. As per PCIe spec r4.0, sec 9.3.7.8, ATS Capabilities in VFs and their associated PFs may be enabled/disabled independently. So remove this dependency logic in enable/disable code. Cc: Ashok Raj Cc: Keith Busch Suggested-by: Ashok Raj Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/ats.c | 11 ----------- include/linux/pci.h | 1 - 2 files changed, 12 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 9384afd7d00e..df2d20079e38 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -64,8 +64,6 @@ int pci_enable_ats(struct pci_dev *dev, int ps) pdev = pci_physfn(dev); if (pdev->ats_stu != ps) return -EINVAL; - - atomic_inc(&pdev->ats_ref_cnt); /* count enabled VFs */ } else { dev->ats_stu = ps; ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); @@ -83,20 +81,11 @@ EXPORT_SYMBOL_GPL(pci_enable_ats); */ void pci_disable_ats(struct pci_dev *dev) { - struct pci_dev *pdev; u16 ctrl; if (WARN_ON(!dev->ats_enabled)) return; - if (atomic_read(&dev->ats_ref_cnt)) - return; /* VFs still enabled */ - - if (dev->is_virtfn) { - pdev = pci_physfn(dev); - atomic_dec(&pdev->ats_ref_cnt); - } - pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, &ctrl); ctrl &= ~PCI_ATS_CTRL_ENABLE; pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); diff --git a/include/linux/pci.h b/include/linux/pci.h index 4bfcca045afd..84301db2fbef 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -452,7 +452,6 @@ struct pci_dev { }; u16 ats_cap; /* ATS Capability offset */ u8 ats_stu; /* ATS Smallest Translation Unit */ - atomic_t ats_ref_cnt; /* Number of VFs with ATS enabled */ #endif #ifdef CONFIG_PCI_PRI struct mutex pri_lock; /* PRI enable lock */ From patchwork Fri Aug 2 00:06:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuppuswamy Sathyanarayanan X-Patchwork-Id: 1140850 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4606vk03ZRz9sBF for ; Fri, 2 Aug 2019 10:08:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728333AbfHBAIq (ORCPT ); Thu, 1 Aug 2019 20:08:46 -0400 Received: from mga02.intel.com ([134.134.136.20]:59857 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727604AbfHBAIq (ORCPT ); Thu, 1 Aug 2019 20:08:46 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 17:08:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="177993973" Received: from skuppusw-desk.jf.intel.com ([10.54.74.33]) by orsmga006.jf.intel.com with ESMTP; 01 Aug 2019 17:08:44 -0700 From: sathyanarayanan.kuppuswamy@linux.intel.com To: bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, ashok.raj@intel.com, keith.busch@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com Subject: [PATCH v5 7/7] PCI: Skip Enhanced Allocation (EA) initialization for VF device Date: Thu, 1 Aug 2019 17:06:04 -0700 Message-Id: <0418e168c33b9373af104ffda623f266d45e6f9f.1564702313.git.sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Kuppuswamy Sathyanarayanan As per PCIe r4.0, sec 9.3.6, VF must not implement Enhanced Allocation Capability. So skip pci_ea_init() for virtual devices. Cc: Ashok Raj Cc: Keith Busch Suggested-by: Ashok Raj Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/pci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 29ed5ec1ac27..4b2844c3606c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3020,6 +3020,13 @@ void pci_ea_init(struct pci_dev *dev) int offset; int i; + /* + * Per PCIe r4.0, sec 9.3.6, VF must not implement Enhanced + * Allocation Capability. + */ + if (dev->is_virtfn) + return; + /* find PCI EA capability in list */ ea = pci_find_capability(dev, PCI_CAP_ID_EA); if (!ea)