Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp5412747ybi; Tue, 4 Jun 2019 06:22:08 -0700 (PDT) X-Google-Smtp-Source: APXvYqxKMuRh08PDqVuETCCBDN0r3j8VpjIfCwXKSmar5LInB6RP66cMvODBvIZFJBnyQipABlNM X-Received: by 2002:a17:90a:de14:: with SMTP id m20mr36474603pjv.36.1559654528362; Tue, 04 Jun 2019 06:22:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559654528; cv=none; d=google.com; s=arc-20160816; b=q/EL+XNpmGqdEE6Xk7J/70VakaNjeHZBCJmaHnEaqJu3h4Y52ukUGBndwULIMwFHxJ 45tmgUgO3z3X1NnK8xoiZXtTZIValX66s6fVjXXXLwmofUr29f9M7i5Jmrja8Np9nejI UnqGJhsWdkyoIY7wdNfOGuhLqWNrtT/+DAqn1JHQyBvS2uN7b0TPktFuHNyhS9sOEMHt F/O+vK2AfOZU2uQIWZsbtg+XMIZthttoZ+tk7agCfP+9LW+G8gSHMwz/NOeqFq0aaO64 5QmUGUBm9uOiNiM3/4GYvHfiMh6deYF3s2ZmLnB3ueSEszhetombOVRIfSXQEpX3ArEn Jikg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=C/sbI2/b2qQ1XTfqgFKre8IkHgEbeuIVF5EXBBu+zZA=; b=GBUg7ZKaB5zXMNJGLlWOVm5UAld4FSyN+5kjHK7aLUTkfbilLfp+Xh7tk5trkTh5bE ivmcWru/mlkSHpJkOtS1OK80LLYHWGayWOGrhNSYFMsAe6ovjAkwB+B4CSQLNx+dQxDo 1gOT0lLpcjHYL3cSYGdZogHTl21fN4dbpAce11b3QmS/xKbLwt9iVRyT7vXRNTzaWZol nkPVlsqzNOpPtbTcgAt+15e/OmEiaX9JQKOf6Ma+OXpuCn6Rz9KJgseJUyyE9A2U92MI UOoMI6b9dU5Jo3Veg+/1pphSWf5rMSKJBY8EA8EXn6e4JhWXecawHV2W9arevBQV43G/ UGPg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=tVtC25aN; 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; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 12si17233412pfi.213.2019.06.04.06.21.50; Tue, 04 Jun 2019 06:22:08 -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; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=tVtC25aN; 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; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727809AbfFDNSo (ORCPT + 99 others); Tue, 4 Jun 2019 09:18:44 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:50512 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727182AbfFDNSk (ORCPT ); Tue, 4 Jun 2019 09:18:40 -0400 Received: from fllv0034.itg.ti.com ([10.64.40.246]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x54DIPMD082496; Tue, 4 Jun 2019 08:18:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1559654305; bh=C/sbI2/b2qQ1XTfqgFKre8IkHgEbeuIVF5EXBBu+zZA=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=tVtC25aNx35AwQaaMae5nBpNeFM4uhNGvd+7yjQaCL/WGiUHctq0tAyJl+UpC5i8y Z9urBq8jX/1Dx5ZCILpy3i8528usHA08+Qn356pGaf3GaKaTWVUH59GTnZz8Kz0WVN 5Fc2o+VX3/2xT2cZgNT/dhQmWXOMXr7zx2c5DZ1E= Received: from DFLE101.ent.ti.com (dfle101.ent.ti.com [10.64.6.22]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x54DIPSV002785 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2019 08:18:25 -0500 Received: from DFLE101.ent.ti.com (10.64.6.22) by DFLE101.ent.ti.com (10.64.6.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Tue, 4 Jun 2019 08:18:25 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE101.ent.ti.com (10.64.6.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Tue, 4 Jun 2019 08:18:25 -0500 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id x54DGdGY098972; Tue, 4 Jun 2019 08:18:20 -0500 From: Kishon Vijay Abraham I To: Tom Joseph , Bjorn Helgaas , Rob Herring , Mark Rutland , Lorenzo Pieralisi , Arnd Bergmann , Gustavo Pimentel CC: Greg Kroah-Hartman , Frank Rowand , Jingoo Han , , , , , , , Kishon Vijay Abraham I Subject: [RFC PATCH 18/30] PCI: endpoint: Add support to add virtual function in endpoint core Date: Tue, 4 Jun 2019 18:45:04 +0530 Message-ID: <20190604131516.13596-19-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190604131516.13596-1-kishon@ti.com> References: <20190604131516.13596-1-kishon@ti.com> MIME-Version: 1.0 Content-Type: text/plain X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support to add virtual function in endpoint core. Every virtual function should be associated with a physical function. Provide APIs to associate a virtual function with a physical function. Signed-off-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/pci-epc-core.c | 2 +- drivers/pci/endpoint/pci-epf-core.c | 92 ++++++++++++++++++++++++++++- include/linux/pci-epf.h | 18 +++++- 3 files changed, 109 insertions(+), 3 deletions(-) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index e5d8d8370686..55417504791b 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -473,7 +473,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) { u32 func_no = 0; - if (epf->epc) + if (epf->epc || epf->is_vf) return -EBUSY; if (IS_ERR(epc)) diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 6e0648991b5c..ce9651ee552a 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -30,13 +30,20 @@ static const struct device_type pci_epf_type; */ void pci_epf_unbind(struct pci_epf *epf) { + struct pci_epf *epf_vf; + if (!epf->driver) { dev_WARN(&epf->dev, "epf device not bound to driver\n"); return; } mutex_lock(&epf->lock); - epf->driver->ops->unbind(epf); + list_for_each_entry(epf_vf, &epf->pci_vepf, list) { + if (epf_vf->is_bound) + epf_vf->driver->ops->unbind(epf_vf); + } + if (epf->is_bound) + epf->driver->ops->unbind(epf); mutex_unlock(&epf->lock); module_put(epf->driver->owner); } @@ -51,6 +58,7 @@ EXPORT_SYMBOL_GPL(pci_epf_unbind); */ int pci_epf_bind(struct pci_epf *epf) { + struct pci_epf *epf_vf; int ret; if (!epf->driver) { @@ -62,13 +70,91 @@ int pci_epf_bind(struct pci_epf *epf) return -EAGAIN; mutex_lock(&epf->lock); + list_for_each_entry(epf_vf, &epf->pci_vepf, list) { + epf_vf->func_no = epf->func_no; + epf_vf->epc = epf->epc; + ret = epf_vf->driver->ops->bind(epf_vf); + if (ret) + goto ret; + epf_vf->is_bound = true; + } + ret = epf->driver->ops->bind(epf); + if (ret) + goto ret; + epf->is_bound = true; + + mutex_unlock(&epf->lock); + return 0; + +ret: mutex_unlock(&epf->lock); + pci_epf_unbind(epf); return ret; } EXPORT_SYMBOL_GPL(pci_epf_bind); +/** + * pci_epf_add_vepf() - associate virtual EP function to physical EP function + * @epf_pf: the physical EP function to which the virtual EP function should be + * associated + * @epf_vf: the virtual EP function to be added + * + * A physical endpoint function can be associated with multiple virtual + * endpoint functions. Invoke pci_epf_add_epf() to add a virtual PCI endpoint + * function to a physical PCI endpoint function. + */ +int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf) +{ + u32 vfunc_no; + + if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf)) + return -EINVAL; + + if (epf_pf->epc || epf_vf->epc || epf_vf->epf_pf) + return -EBUSY; + + mutex_lock(&epf_pf->lock); + vfunc_no = find_first_zero_bit(&epf_pf->vfunction_num_map, + BITS_PER_LONG); + if (vfunc_no >= BITS_PER_LONG) + return -EINVAL; + + set_bit(vfunc_no, &epf_pf->vfunction_num_map); + epf_vf->vfunc_no = vfunc_no; + + epf_vf->epf_pf = epf_pf; + epf_vf->is_vf = true; + + list_add_tail(&epf_vf->list, &epf_pf->pci_vepf); + mutex_unlock(&epf_pf->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pci_epf_add_vepf); + +/** + * pci_epf_remove_vepf() - remove virtual EP function from physical EP function + * @epf_pf: the physical EP function from which the virtual EP function should + * be removed + * @epf_vf: the virtual EP function to be removed + * + * Invoke to remove a virtual endpoint function from the physcial endpoint + * function. + */ +void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf) +{ + if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf)) + return; + + mutex_lock(&epf_pf->lock); + clear_bit(epf_vf->vfunc_no, &epf_pf->vfunction_num_map); + list_del(&epf_vf->list); + mutex_unlock(&epf_pf->lock); +} +EXPORT_SYMBOL_GPL(pci_epf_remove_vepf); + /** * pci_epf_free_space() - free the allocated PCI EPF register space * @addr: the virtual address of the PCI EPF register space @@ -256,6 +342,10 @@ struct pci_epf *pci_epf_create(const char *name) return ERR_PTR(-ENOMEM); } + /* VFs are numbered starting with 1. So set BIT(0) by default */ + epf->vfunction_num_map = 1; + INIT_LIST_HEAD(&epf->pci_vepf); + dev = &epf->dev; device_initialize(dev); dev->bus = &pci_epf_bus_type; diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index bcdf4f07bde7..c36e474bc9c7 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -105,12 +105,20 @@ struct pci_epf_bar { * @header: represents standard configuration header * @bar: represents the BAR of EPF device * @msi_interrupts: number of MSI interrupts required by this function - * @func_no: unique function number within this endpoint device + * @func_no: unique (physical) function number within this endpoint device + * @vfunc_no: unique virtual function number within a physical function * @epc: the EPC device to which this EPF device is bound + * @epf_pf: the physical EPF device to which this virtual EPF device is bound + * An EPF cannot be associated with both EPC and physical EPF device at the + * same time. * @driver: the EPF driver to which this EPF device is bound * @list: to add pci_epf as a list of PCI endpoint functions to pci_epc * @nb: notifier block to notify EPF of any EPC events (like linkup) * @lock: mutex to protect pci_epf_ops + * @is_bound: indicates if bind notification to function driver has been invoked + * @is_vf: true - virtual function, false - physical function + * @vfunction_num_map: bitmap to manage virtual function number + * @pci_vepf: list of virtual endpoint function associated with this function */ struct pci_epf { struct device dev; @@ -120,13 +128,19 @@ struct pci_epf { u8 msi_interrupts; u16 msix_interrupts; u8 func_no; + u8 vfunc_no; struct pci_epc *epc; + struct pci_epf *epf_pf; struct pci_epf_driver *driver; struct list_head list; struct notifier_block nb; /* mutex to protect against concurrent access of pci_epf_ops */ struct mutex lock; + unsigned int is_bound; + unsigned int is_vf; + unsigned long vfunction_num_map; + struct list_head pci_vepf; }; #define to_pci_epf(epf_dev) container_of((epf_dev), struct pci_epf, dev) @@ -156,4 +170,6 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar); int pci_epf_bind(struct pci_epf *epf); void pci_epf_unbind(struct pci_epf *epf); +int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf); +void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf); #endif /* __LINUX_PCI_EPF_H */ -- 2.17.1