Received: by 10.213.65.68 with SMTP id h4csp772152imn; Tue, 13 Mar 2018 22:33:09 -0700 (PDT) X-Google-Smtp-Source: AG47ELuDdL+JKZ/jHDfcXyA99fFNaO7jRf0U5e59xfXspJnKI+BODZI1R4oZ3N9ewfDBbPN8c569 X-Received: by 10.99.120.197 with SMTP id t188mr2639678pgc.358.1521005589831; Tue, 13 Mar 2018 22:33:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521005589; cv=none; d=google.com; s=arc-20160816; b=Nwo4J1A1TNIixgMNZlOe01MshTGDk1EESLHLLbf4BuFfZC95XjiOhUH6jYUMoj0ieE rAMLSHEK0Z0NeIXW2LLMsdTjaa3zrwBTY+QFbxuKAa4GJ4w0I7FJH1XNp9xJRpdOdyTq qQNG2TuuoZY86nREVsxV65QUZNqL57NFLFCBCA18JUCjaNeF3ZEteuZQ4Yu+WnZmIM/F dw5Qg57jNXnvCAP8/o/ujT2gm4pworIS98DgGh542kvjGbIu40PWJS7pxsqAvPTnVr5J 2+txPIsobj9KU5IdVthCqS+7+Rhld6z3LxZu4FxJKKIldnxwMJ16JPOkKWKdUNbFhvdI e6uw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:arc-authentication-results; bh=xKdCOf67/A2BYjZWm7bKWVNsQd+nE2BTYWt6WMHdWH0=; b=ScEr7G/u1Fw7zrTot0mMbxLLQkbP2v9/bwZ7CEdx2da5qcfkcjyDcb1OYSrTzI9b/y wbEFwKkl5PhUXb2tFrdb+6oo3jh8aMJ0U7TWLCe6CqTom8UE0swtBfbaFXDR0/BBd0Q6 y2bWoLUtTCONesVlN2669aUo+yLt4syd+xXSvfVTcBBTw1nIObh1Y2NeJ29UX+wB75Zq qDCuwo55aQs/GX3GGNlopQTvL3HuQm/4yxtKURfINGRClFE43mjcR182r76XjS7KZtN4 jFynw2YeyMjWYlbRy8OPjAB/QxrMTRm4mrRbygNo4jAiT5zijnio95BujnYQESQpTcdd PIDA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33-v6si1376761plf.98.2018.03.13.22.32.55; Tue, 13 Mar 2018 22:33:09 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753344AbeCNFbS (ORCPT + 99 others); Wed, 14 Mar 2018 01:31:18 -0400 Received: from mga12.intel.com ([192.55.52.136]:40628 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750862AbeCNFbQ (ORCPT ); Wed, 14 Mar 2018 01:31:16 -0400 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 22:31:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,468,1515484800"; d="scan'208";a="25066333" Received: from hao-dev.bj.intel.com (HELO localhost) ([10.238.157.61]) by orsmga008.jf.intel.com with ESMTP; 13 Mar 2018 22:31:12 -0700 Date: Wed, 14 Mar 2018 13:21:21 +0800 From: Wu Hao To: Alan Tull Cc: Moritz Fischer , linux-fpga@vger.kernel.org, linux-kernel , linux-api@vger.kernel.org, "Kang, Luwei" , "Zhang, Yi Z" , Tim Whisonant , Enno Luebbers , Shiva Rao , Christopher Rauer , Xiao Guangrong Subject: Re: [PATCH v4 09/24] fpga: dfl-pci: add enumeration for feature devices Message-ID: <20180314052121.GB32276@hao-dev> References: <1518513893-4719-1-git-send-email-hao.wu@intel.com> <1518513893-4719-10-git-send-email-hao.wu@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Mar 13, 2018 at 01:30:24PM -0500, Alan Tull wrote: > On Tue, Feb 13, 2018 at 3:24 AM, Wu Hao wrote: > > Hi Hao, > > Thanks again for splitting the pci part of the code from enumeration > and everything else. > > One thing that may need to be fixed below, so with that fixed, adding my ack. Hi Alan Thanks a lot for your review and acked-by on these patches, please see my replies below. : ) > > > The Device Feature List (DFL) is implemented in MMIO, and features > > are linked via the DFLs. This patch enables pcie driver to prepare > > enumeration information (e.g locations of all device feature lists > > in MMIO) and use common APIs provided by the Device Feature List > > framework to enumerate each feature device linked. > > > > Signed-off-by: Tim Whisonant > > Signed-off-by: Enno Luebbers > > Signed-off-by: Shiva Rao > > Signed-off-by: Christopher Rauer > > Signed-off-by: Zhang Yi > > Signed-off-by: Xiao Guangrong > > Signed-off-by: Wu Hao > Acked-by: Alan Tull > > > --- > > v3: split from another patch > > use common functions from DFL framework for enumeration. > > v4: rebase > > --- > > drivers/fpga/dfl-pci.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++- > > 1 file changed, 197 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c > > index d91ea42..8ce8a94 100644 > > --- a/drivers/fpga/dfl-pci.c > > +++ b/drivers/fpga/dfl-pci.c > > @@ -22,9 +22,52 @@ > > #include > > #include > > > > +#include "dfl.h" > > + > > #define DRV_VERSION "0.8" > > #define DRV_NAME "dfl-pci" > > > > +struct cci_drvdata { > > + struct fpga_cdev *cdev; /* container device */ > > + struct list_head regions; /* list of pci bar mapping region */ > > +}; > > + > > +/* pci bar mapping info */ > > +struct cci_region { > > + int bar; > > + void __iomem *ioaddr; /* pointer to mapped bar region */ > > + struct list_head node; > > +}; > > + > > +static void __iomem *cci_pci_ioremap_bar(struct pci_dev *pcidev, int bar) > > +{ > > + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); > > + struct cci_region *region; > > + > > + list_for_each_entry(region, &drvdata->regions, node) > > + if (region->bar == bar) { > > + dev_dbg(&pcidev->dev, "BAR %d region exists\n", bar); > > + return region->ioaddr; > > + } > > + > > + region = devm_kzalloc(&pcidev->dev, sizeof(*region), GFP_KERNEL); > > + if (!region) > > + return NULL; > > + > > + region->bar = bar; > > + region->ioaddr = pci_ioremap_bar(pcidev, bar); > > + if (!region->ioaddr) { > > + dev_err(&pcidev->dev, "can't ioremap memory from BAR %d.\n", > > + bar); > > + devm_kfree(&pcidev->dev, region); > > + return NULL; > > + } > > + > > + list_add(®ion->node, &drvdata->regions); > > + > > + return region->ioaddr; > > +} > > + > > /* PCI Device ID */ > > #define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD > > #define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0 > > @@ -45,6 +88,143 @@ static struct pci_device_id cci_pcie_id_tbl[] = { > > }; > > MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl); > > > > +static int cci_init_drvdata(struct pci_dev *pcidev) > > +{ > > + struct cci_drvdata *drvdata; > > + > > + drvdata = devm_kzalloc(&pcidev->dev, sizeof(*drvdata), GFP_KERNEL); > > + if (!drvdata) > > + return -ENOMEM; > > + > > + INIT_LIST_HEAD(&drvdata->regions); > > + > > + pci_set_drvdata(pcidev, drvdata); > > + > > + return 0; > > +} > > + > > +static void cci_pci_release_regions(struct pci_dev *pcidev) > > +{ > > + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); > > + struct cci_region *tmp, *region; > > + > > + list_for_each_entry_safe(region, tmp, &drvdata->regions, node) { > > + list_del(®ion->node); > > + if (region->ioaddr) > > + pci_iounmap(pcidev, region->ioaddr); > > + devm_kfree(&pcidev->dev, region); > > + } > > +} > > + > > +static void cci_remove_drvdata(struct pci_dev *pcidev) > > +{ > > + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); > > + > > + cci_pci_release_regions(pcidev); > > Would it make sense to call fpga_enum_info_free here? I understand > fpga_enum_info_alloc uses devm, but it does a get_device which needs > to be put. > > > + pci_set_drvdata(pcidev, NULL); > > + devm_kfree(&pcidev->dev, drvdata); > > +} > > + > > +static void cci_remove_feature_devs(struct pci_dev *pcidev) > > +{ > > + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); > > + > > + /* remove all children feature devices */ > > + fpga_remove_feature_devs(drvdata->cdev); > > +} > > + > > +/* enumerate feature devices under pci device */ > > +static int cci_enumerate_feature_devs(struct pci_dev *pcidev) > > +{ > > + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); > > + struct fpga_cdev *cdev; > > + struct fpga_enum_info *info; > > + resource_size_t start, len; > > + void __iomem *base; > > + int port_num, bar, i, ret = 0; > > + u32 offset; > > + u64 v; > > + > > + /* allocate enumeration info via pci_dev */ > > + info = fpga_enum_info_alloc(&pcidev->dev); > > + if (!info) > > + return -ENOMEM; > > + > > + /* start to find Device Feature List from Bar 0 */ > > + base = cci_pci_ioremap_bar(pcidev, 0); > > + if (!base) { > > + ret = -ENOMEM; > > + goto enum_info_free_exit; > > + } > > + > > + /* > > + * PF device has FME and Ports/AFUs, and VF device only has 1 Port/AFU. > > + * check them and add related "Device Feature List" info for the next > > + * step enumeration. > > + */ > > + if (feature_is_fme(base)) { > > + start = pci_resource_start(pcidev, 0); > > + len = pci_resource_len(pcidev, 0); > > + > > + fpga_enum_info_add_dfl(info, start, len, base); > > + > > + /* > > + * find more Device Feature Lists (e.g Ports) per information > > + * indicated by FME module. > > + */ > > + v = readq(base + FME_HDR_CAP); > > + port_num = FIELD_GET(FME_CAP_NUM_PORTS, v); > > + > > + WARN_ON(port_num > MAX_FPGA_PORT_NUM); > > + > > + for (i = 0; i < port_num; i++) { > > + v = readq(base + FME_HDR_PORT_OFST(i)); > > + > > + /* skip ports which are not implemented. */ > > + if (!(v & FME_PORT_OFST_IMP)) > > + continue; > > + > > + /* > > + * add Port's Device Feature List information for next > > + * step enumeration. > > + */ > > + bar = FIELD_GET(FME_PORT_OFST_BAR_ID, v); > > + offset = FIELD_GET(FME_PORT_OFST_DFH_OFST, v); > > + base = cci_pci_ioremap_bar(pcidev, bar); > > + if (!base) > > + continue; > > + > > + start = pci_resource_start(pcidev, bar) + offset; > > + len = pci_resource_len(pcidev, bar) - offset; > > + > > + fpga_enum_info_add_dfl(info, start, len, base + offset); > > + } > > + } else if (feature_is_port(base)) { > > + start = pci_resource_start(pcidev, 0); > > + len = pci_resource_len(pcidev, 0); > > + > > + fpga_enum_info_add_dfl(info, start, len, base); > > + } else { > > + ret = -ENODEV; > > + goto enum_info_free_exit; > > + } > > + > > + /* start enumeration with prepared enumeration information */ > > + cdev = fpga_enumerate_feature_devs(info); > > + if (IS_ERR(cdev)) { > > + dev_err(&pcidev->dev, "Enumeration failure\n"); > > + ret = PTR_ERR(cdev); > > + goto enum_info_free_exit; > > + } > > + > > + drvdata->cdev = cdev; > > + > > +enum_info_free_exit: > > + fpga_enum_info_free(info); > > This is the only place I saw fpga_enum_info_free being called. It doesn't need to keep the enumeration inforamtion data structure once the enumeration done, so in the driver, it always did fpga_enum_info_free once fpga_enumerate_feature_devs(info) returned in this function. so no need to consider it in other places per my understanding. : ) Thanks Hao > > Thanks, > Alan > > > + > > + return ret; > > +} > > + > > static > > int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid) > > { > > @@ -82,9 +262,22 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid) > > goto release_region_exit; > > } > > > > - /* TODO: create and add the platform device per feature list */ > > - return 0; > > + ret = cci_init_drvdata(pcidev); > > + if (ret) { > > + dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret); > > + goto release_region_exit; > > + } > > + > > + ret = cci_enumerate_feature_devs(pcidev); > > + if (ret) { > > + dev_err(&pcidev->dev, "enumeration failure %d.\n", ret); > > + goto remove_drvdata_exit; > > + } > > + > > + return ret; > > > > +remove_drvdata_exit: > > + cci_remove_drvdata(pcidev); > > release_region_exit: > > pci_release_regions(pcidev); > > disable_error_report_exit: > > @@ -95,6 +288,8 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid) > > > > static void cci_pci_remove(struct pci_dev *pcidev) > > { > > + cci_remove_feature_devs(pcidev); > > + cci_remove_drvdata(pcidev); > > pci_release_regions(pcidev); > > pci_disable_pcie_error_reporting(pcidev); > > pci_disable_device(pcidev); > > -- > > 2.7.4 > >