LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V4 12/26] powerpc/powermac: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2017-12-19  5:37 UTC (permalink / raw)
  To: linux-pci, timur
  Cc: linux-arm-msm, linux-arm-kernel, Sinan Kaya,
	Benjamin Herrenschmidt, open list:LINUX FOR POWER MACINTOSH,
	open list
In-Reply-To: <1513661883-28662-1-git-send-email-okaya@codeaurora.org>

pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
where a PCI device is present. This restricts the device drivers to be
reused for other domain numbers.

Getting ready to remove pci_get_bus_and_slot() function in favor of
pci_get_domain_bus_and_slot().

Hard-code the domain number as 0 to match the previous behavior.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/macintosh/via-pmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index e8b29fc..08849e3 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -1799,7 +1799,7 @@ static int powerbook_sleep_grackle(void)
 	struct adb_request req;
 	struct pci_dev *grackle;
 
-	grackle = pci_get_bus_and_slot(0, 0);
+	grackle = pci_get_domain_bus_and_slot(0, 0, 0);
 	if (!grackle)
 		return -ENODEV;
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH V4 02/26] powerpc/PCI: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2017-12-19  5:37 UTC (permalink / raw)
  To: linux-pci, timur
  Cc: linux-arm-msm, linux-arm-kernel, Sinan Kaya,
	Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	Tyrel Datwyler, Rob Herring, Bhumika Goyal,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT), open list
In-Reply-To: <1513661883-28662-1-git-send-email-okaya@codeaurora.org>

pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
where a PCI device is present. This restricts the device drivers to be
reused for other domain numbers.

Getting ready to remove pci_get_bus_and_slot() function in favor of
pci_get_domain_bus_and_slot().

Use pci_get_domain_bus_and_slot() with a domain number of 0 as the code
is not ready to consume multiple domains and existing code used domain
number 0.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 arch/powerpc/kernel/pci_32.c              | 3 ++-
 arch/powerpc/platforms/powermac/feature.c | 2 +-
 arch/powerpc/sysdev/mv64x60_pci.c         | 4 ++--
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 1d817f4..85ad2f7 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -96,7 +96,8 @@
 		reg = of_get_property(node, "reg", NULL);
 		if (!reg)
 			continue;
-		dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
+		dev = pci_get_domain_bus_and_slot(0, pci_bus,
+						  ((reg[0] >> 8) & 0xff));
 		if (!dev || !dev->subordinate) {
 			pci_dev_put(dev);
 			continue;
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 466b842..3f82cb2 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -829,7 +829,7 @@ static long core99_scc_enable(struct device_node *node, long param, long value)
 
 	if (value) {
 		if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
-			pdev = pci_get_bus_and_slot(pbus, pid);
+			pdev = pci_get_domain_bus_and_slot(0, pbus, pid);
 		if (pdev == NULL)
 			return 0;
 		rc = pci_enable_device(pdev);
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index d52b3b8..6fe9104 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -37,7 +37,7 @@ static ssize_t mv64x60_hs_reg_read(struct file *filp, struct kobject *kobj,
 	if (count < MV64X60_VAL_LEN_MAX)
 		return -EINVAL;
 
-	phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+	phb = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
 	if (!phb)
 		return -ENODEV;
 	pci_read_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, &v);
@@ -61,7 +61,7 @@ static ssize_t mv64x60_hs_reg_write(struct file *filp, struct kobject *kobj,
 	if (sscanf(buf, "%i", &v) != 1)
 		return -EINVAL;
 
-	phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+	phb = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
 	if (!phb)
 		return -ENODEV;
 	pci_write_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, v);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v2 2/7] powerpc/kernel: Add uevents in EEH error/resume
From: Russell Currey @ 2017-12-19  4:59 UTC (permalink / raw)
  To: Bjorn Helgaas, Bryant G. Ly
  Cc: benh, paulus, mpe, seroyer, jjalvare, alex.williamson, aik,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Keith Busch,
	Gabriele Paoloni, Dongdong Liu
In-Reply-To: <20171219045009.GC14941@bhelgaas-glaptop.roam.corp.google.com>

On Mon, 2017-12-18 at 22:50 -0600, Bjorn Helgaas wrote:
> [+cc Keith, Gabriele, Dongdong]
> 
> On Mon, Dec 18, 2017 at 04:38:03PM -0600, Bryant G. Ly wrote:
> > Devices can go offline when EEH is reported. This patch adds
> > a change to the kernel object and lets udev know of error.
> > When device resumes a change is also set reporting device as
> > online. Therefore, EEH events are better propagated to user
> > space for devices in powerpc arch.
> 
> I'm on vacation and can't review this in detail, but I wonder if you
> can compare this with the uevents we emit for DPC, AER, and hotplug
> events (if any).  I hope we don't end up with userspace having to be
> aware of the differences between EEH, DPC, AER, etc.
> 
> From a very quick look, I only see a few uevents even mentioned in
> drivers/pci: KOBJ_ADD in __pci_hp_register() and KOBJ_CHANGE in the
> SR-IOV code.  I'm worried that we're missing some important uevents
> in
> the PCI core.  That's not an argument against what you're doing here;
> it just would be nice to fill in any missing pieces in the core also,
> and hopefully make them consistent with these EEH events.

I don't think this needs to be particularly complex, could we get away
with events for when devices do the following?

- begin recovery
- successfully recover
- fail recovery

It might be worthwhile sorting out some consistent, non-EEH-specific
naming, and then other device error recovery systems can do the same
later.

- Russell

> 
> > Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
> > Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>

^ permalink raw reply

* Re: [PATCH v2 2/7] powerpc/kernel: Add uevents in EEH error/resume
From: Bjorn Helgaas @ 2017-12-19  4:50 UTC (permalink / raw)
  To: Bryant G. Ly
  Cc: benh, paulus, mpe, seroyer, jjalvare, alex.williamson, aik,
	ruscur, linux-pci, linuxppc-dev, bodong, eli, saeedm, Keith Busch,
	Gabriele Paoloni, Dongdong Liu
In-Reply-To: <20171218223808.83928-3-bryantly@linux.vnet.ibm.com>

[+cc Keith, Gabriele, Dongdong]

On Mon, Dec 18, 2017 at 04:38:03PM -0600, Bryant G. Ly wrote:
> Devices can go offline when EEH is reported. This patch adds
> a change to the kernel object and lets udev know of error.
> When device resumes a change is also set reporting device as
> online. Therefore, EEH events are better propagated to user
> space for devices in powerpc arch.

I'm on vacation and can't review this in detail, but I wonder if you
can compare this with the uevents we emit for DPC, AER, and hotplug
events (if any).  I hope we don't end up with userspace having to be
aware of the differences between EEH, DPC, AER, etc.

>From a very quick look, I only see a few uevents even mentioned in
drivers/pci: KOBJ_ADD in __pci_hp_register() and KOBJ_CHANGE in the
SR-IOV code.  I'm worried that we're missing some important uevents in
the PCI core.  That's not an argument against what you're doing here;
it just would be nice to fill in any missing pieces in the core also,
and hopefully make them consistent with these EEH events.

> Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
> Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
> ---
>  arch/powerpc/kernel/eeh_driver.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
> index 3c0fa99c5533..9d4e8177c2e0 100644
> --- a/arch/powerpc/kernel/eeh_driver.c
> +++ b/arch/powerpc/kernel/eeh_driver.c
> @@ -204,6 +204,7 @@ static void *eeh_report_error(void *data, void *userdata)
>  	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
>  	enum pci_ers_result rc, *res = userdata;
>  	struct pci_driver *driver;
> +	char *envp[] = {"EVENT=EEH_ERROR", "ONLINE=0", NULL};
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> @@ -228,6 +229,7 @@ static void *eeh_report_error(void *data, void *userdata)
>  
>  	edev->in_error = true;
>  	eeh_pcid_put(dev);
> +	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
>  	return NULL;
>  }
>  
> @@ -358,6 +360,7 @@ static void *eeh_report_resume(void *data, void *userdata)
>  	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
>  	bool was_in_error;
>  	struct pci_driver *driver;
> +	char *envp[] = {"EVENT=EEH_RESUME", "ONLINE=1", NULL};
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> @@ -381,6 +384,7 @@ static void *eeh_report_resume(void *data, void *userdata)
>  	driver->err_handler->resume(dev);
>  
>  	eeh_pcid_put(dev);
> +	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
>  	return NULL;
>  }
>  
> @@ -397,6 +401,7 @@ static void *eeh_report_failure(void *data, void *userdata)
>  	struct eeh_dev *edev = (struct eeh_dev *)data;
>  	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
>  	struct pci_driver *driver;
> +	char * envp[] = {"EVENT=EEH_PERMANENT_FAILURE", "ONLINE=0", NULL};
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> @@ -415,6 +420,7 @@ static void *eeh_report_failure(void *data, void *userdata)
>  
>  	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
>  
> +	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
>  	eeh_pcid_put(dev);
>  	return NULL;
>  }
> -- 
> 2.14.3 (Apple Git-98)
> 

^ permalink raw reply

* Re: [trivial PATCH] treewide: Align function definition open/close braces
From: Martin K. Petersen @ 2017-12-19  3:31 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jiri Kosina, Linus Torvalds, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-media, MPT-FusionLinux.pdl, linux-scsi, netdev,
	linux-wireless, acpi4asus-user, platform-driver-x86, linux-rtc,
	linux-fsdevel, ocfs2-devel, linux-xfs, linux-audit, alsa-devel,
	linuxppc-dev
In-Reply-To: <1513556924.31581.51.camel@perches.com>


Joe,

> Some functions definitions have either the initial open brace and/or
> the closing brace outside of column 1.
>
> Move those braces to column 1.

SCSI bits look OK.

Acked-by: Martin K. Petersen <martin.petersen@oracle.com>

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply

* Re: [PATCH 11/13] cxl: Remove support for "Processing accelerators" class
From: Andrew Donnellan @ 2017-12-18 23:47 UTC (permalink / raw)
  To: Frederic Barrat, linuxppc-dev, linux-kernel; +Cc: arnd, gregkh, mpe, alastair
In-Reply-To: <199cdb186d837daa838a37d937c6586bb9cfe1a2.1513608243.git.fbarrat@linux.vnet.ibm.com>

On 19/12/17 02:21, Frederic Barrat wrote:
> The cxl driver currently declares in its table of supported PCI
> devices the class "Processing accelerators". Therefore it may be
> called to probe for opencapi devices, which generates errors, as the
> config space of a cxl device is not compatible with opencapi.
> 
> So remove support for the generic class, as we now have (at least) two
> drivers for devices of the same class. Most cxl devices are FPGAs with
> a PSL which will show a known device ID of 0x477. Other devices are
> really supported by the cxlflash driver and are already listed in the
> table. So removing the class is expected to go unnoticed.
> 
> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>

Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>

> ---
>   drivers/misc/cxl/pci.c | 2 --
>   1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
> index 19969ee86d6f..758842f65a1b 100644
> --- a/drivers/misc/cxl/pci.c
> +++ b/drivers/misc/cxl/pci.c
> @@ -125,8 +125,6 @@ static const struct pci_device_id cxl_pci_tbl[] = {
>   	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0601), },
>   	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0623), },
>   	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0628), },
> -	{ PCI_DEVICE_CLASS(0x120000, ~0), },
> -
>   	{ }
>   };
>   MODULE_DEVICE_TABLE(pci, cxl_pci_tbl);
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com  IBM Australia Limited

^ permalink raw reply

* Re: [PATCH 07/13] ocxl: Add AFU interrupt support
From: Benjamin Herrenschmidt @ 2017-12-19  4:05 UTC (permalink / raw)
  To: Frederic Barrat, linuxppc-dev, linux-kernel
  Cc: arnd, gregkh, mpe, andrew.donnellan, alastair,
	Cédric Le Goater
In-Reply-To: <d7666f69b09f1e5dc713bf0524912184c978b963.1513608243.git.fbarrat@linux.vnet.ibm.com>

On Mon, 2017-12-18 at 16:21 +0100, Frederic Barrat wrote:
> Add user APIs through ioctl to allocate, free, and be notified of an
> AFU interrupt.
> 
> For opencapi, an AFU can trigger an interrupt on the host by sending a
> specific command targeting a 64-bit object handle. On POWER9, this is
> implemented by mapping a special page in the address space of a
> process and a write to that page will trigger an interrupt.

We need to figure out how that plays with KVM. +Cedric..

For all those "generic xive" interrupts, whether they are used for
OpenCAPI, plain guest IPIs, NX interrupts etc... but also for actual
pass-through ones, we'll need a mechanism to map the trigger and ESB
pages into qemu.

We can't have a bazillion VMAs and KVM memory regions either, so we'll
need some kind of mechanism/driver which allows for a single fairly
large mmap'ed VMA which can then be "populated" with interrupt control
pages.

The issue of course is that we can't really do a "generic" system that
allows to map any interrupt, it's a security issue. So we need the
interrupt "owner" to be the one allowing this. VFIO for PCI for
example, possibly a specific VFIO variant for OpenCAPI, something else
for guest IPIs ?

Food for thoughts...

Ben.

> 
> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
> ---
>  arch/powerpc/include/asm/pnv-ocxl.h   |   3 +
>  arch/powerpc/platforms/powernv/ocxl.c |  30 +++++
>  drivers/misc/ocxl/afu_irq.c           | 204 ++++++++++++++++++++++++++++++++++
>  drivers/misc/ocxl/context.c           |  40 ++++++-
>  drivers/misc/ocxl/file.c              |  33 ++++++
>  drivers/misc/ocxl/link.c              |  28 +++++
>  drivers/misc/ocxl/ocxl_internal.h     |   7 ++
>  include/uapi/misc/ocxl.h              |   9 ++
>  8 files changed, 352 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/misc/ocxl/afu_irq.c
> 
> diff --git a/arch/powerpc/include/asm/pnv-ocxl.h b/arch/powerpc/include/asm/pnv-ocxl.h
> index 5a7ae7f28209..1e26f0a39500 100644
> --- a/arch/powerpc/include/asm/pnv-ocxl.h
> +++ b/arch/powerpc/include/asm/pnv-ocxl.h
> @@ -37,4 +37,7 @@ extern int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask,
>  extern void pnv_ocxl_spa_release(void *platform_data);
>  extern int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle);
>  
> +extern int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr);
> +extern void pnv_ocxl_free_xive_irq(u32 irq);
> +
>  #endif /* _ASM_PVN_OCXL_H */
> diff --git a/arch/powerpc/platforms/powernv/ocxl.c b/arch/powerpc/platforms/powernv/ocxl.c
> index 6c79924b95c8..96cafba6aef1 100644
> --- a/arch/powerpc/platforms/powernv/ocxl.c
> +++ b/arch/powerpc/platforms/powernv/ocxl.c
> @@ -9,6 +9,7 @@
>  
>  #include <asm/pnv-ocxl.h>
>  #include <asm/opal.h>
> +#include <asm/xive.h>
>  #include <misc/ocxl-config.h>
>  #include "pci.h"
>  
> @@ -487,3 +488,32 @@ int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle)
>  	return rc;
>  }
>  EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe);
> +
> +int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr)
> +{
> +	__be64 flags, trigger_page;
> +	s64 rc;
> +	u32 hwirq;
> +
> +	hwirq = xive_native_alloc_irq();
> +	if (!hwirq)
> +		return -ENOENT;
> +
> +	rc = opal_xive_get_irq_info(hwirq, &flags, NULL, &trigger_page, NULL,
> +				NULL);
> +	if (rc || !trigger_page) {
> +		xive_native_free_irq(hwirq);
> +		return -ENOENT;
> +	}
> +	*irq = hwirq;
> +	*trigger_addr = be64_to_cpu(trigger_page);
> +	return 0;
> +
> +}
> +EXPORT_SYMBOL_GPL(pnv_ocxl_alloc_xive_irq);
> +
> +void pnv_ocxl_free_xive_irq(u32 irq)
> +{
> +	xive_native_free_irq(irq);
> +}
> +EXPORT_SYMBOL_GPL(pnv_ocxl_free_xive_irq);
> diff --git a/drivers/misc/ocxl/afu_irq.c b/drivers/misc/ocxl/afu_irq.c
> new file mode 100644
> index 000000000000..0b217a854837
> --- /dev/null
> +++ b/drivers/misc/ocxl/afu_irq.c
> @@ -0,0 +1,204 @@
> +/*
> + * Copyright 2017 IBM Corp.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/eventfd.h>
> +#include <asm/pnv-ocxl.h>
> +#include "ocxl_internal.h"
> +
> +struct afu_irq {
> +	int id;
> +	int hw_irq;
> +	unsigned int virq;
> +	char *name;
> +	u64 trigger_page;
> +	struct eventfd_ctx *ev_ctx;
> +};
> +
> +static int irq_offset_to_id(struct ocxl_context *ctx, u64 offset)
> +{
> +	return (offset - ctx->afu->irq_base_offset) >> PAGE_SHIFT;
> +}
> +
> +static u64 irq_id_to_offset(struct ocxl_context *ctx, int id)
> +{
> +	return ctx->afu->irq_base_offset + (id << PAGE_SHIFT);
> +}
> +
> +static irqreturn_t afu_irq_handler(int virq, void *data)
> +{
> +	struct afu_irq *irq = (struct afu_irq *) data;
> +
> +	if (irq->ev_ctx)
> +		eventfd_signal(irq->ev_ctx, 1);
> +	return IRQ_HANDLED;
> +}
> +
> +static int setup_afu_irq(struct ocxl_context *ctx, struct afu_irq *irq)
> +{
> +	int rc;
> +
> +	irq->virq = irq_create_mapping(NULL, irq->hw_irq);
> +	if (!irq->virq) {
> +		pr_err("irq_create_mapping failed\n");
> +		return -ENOMEM;
> +	}
> +	pr_debug("hw_irq %d mapped to virq %u\n", irq->hw_irq, irq->virq);
> +
> +	irq->name = kasprintf(GFP_KERNEL, "ocxl-afu-%u", irq->virq);
> +	if (!irq->name) {
> +		irq_dispose_mapping(irq->virq);
> +		return -ENOMEM;
> +	}
> +
> +	rc = request_irq(irq->virq, afu_irq_handler, 0, irq->name, irq);
> +	if (rc) {
> +		kfree(irq->name);
> +		irq->name = NULL;
> +		irq_dispose_mapping(irq->virq);
> +		pr_err("request_irq failed: %d\n", rc);
> +		return rc;
> +	}
> +	return 0;
> +}
> +
> +static void release_afu_irq(struct afu_irq *irq)
> +{
> +	free_irq(irq->virq, irq);
> +	irq_dispose_mapping(irq->virq);
> +	kfree(irq->name);
> +}
> +
> +int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset)
> +{
> +	struct afu_irq *irq;
> +	int rc;
> +
> +	irq = kzalloc(sizeof(struct afu_irq), GFP_KERNEL);
> +	if (!irq)
> +		return -ENOMEM;
> +
> +	/*
> +	 * We limit the number of afu irqs per context and per link to
> +	 * avoid a single process or user depleting the pool of IPIs
> +	 */
> +
> +	mutex_lock(&ctx->irq_lock);
> +
> +	irq->id = idr_alloc(&ctx->irq_idr, irq, 0, MAX_IRQ_PER_CONTEXT,
> +			GFP_KERNEL);
> +	if (irq->id < 0) {
> +		rc = -ENOSPC;
> +		goto err_unlock;
> +	}
> +
> +	rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq,
> +				&irq->trigger_page);
> +	if (rc)
> +		goto err_idr;
> +
> +	rc = setup_afu_irq(ctx, irq);
> +	if (rc)
> +		goto err_alloc;
> +
> +	*irq_offset = irq_id_to_offset(ctx, irq->id);
> +
> +	mutex_unlock(&ctx->irq_lock);
> +	return 0;
> +
> +err_alloc:
> +	ocxl_link_free_irq(ctx->afu->fn->link, irq->hw_irq);
> +err_idr:
> +	idr_remove(&ctx->irq_idr, irq->id);
> +err_unlock:
> +	mutex_unlock(&ctx->irq_lock);
> +	kfree(irq);
> +	return rc;
> +}
> +
> +static void afu_irq_free(struct afu_irq *irq, struct ocxl_context *ctx)
> +{
> +	if (ctx->mapping)
> +		unmap_mapping_range(ctx->mapping,
> +				irq_id_to_offset(ctx, irq->id),
> +				1 << PAGE_SHIFT, 1);
> +	release_afu_irq(irq);
> +	if (irq->ev_ctx)
> +		eventfd_ctx_put(irq->ev_ctx);
> +	ocxl_link_free_irq(ctx->afu->fn->link, irq->hw_irq);
> +	kfree(irq);
> +}
> +
> +int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset)
> +{
> +	struct afu_irq *irq;
> +	int id = irq_offset_to_id(ctx, irq_offset);
> +
> +	mutex_lock(&ctx->irq_lock);
> +
> +	irq = idr_find(&ctx->irq_idr, id);
> +	if (!irq) {
> +		mutex_unlock(&ctx->irq_lock);
> +		return -EINVAL;
> +	}
> +	idr_remove(&ctx->irq_idr, irq->id);
> +	afu_irq_free(irq, ctx);
> +	mutex_unlock(&ctx->irq_lock);
> +	return 0;
> +}
> +
> +void ocxl_afu_irq_free_all(struct ocxl_context *ctx)
> +{
> +	struct afu_irq *irq;
> +	int id;
> +
> +	mutex_lock(&ctx->irq_lock);
> +	idr_for_each_entry(&ctx->irq_idr, irq, id)
> +		afu_irq_free(irq, ctx);
> +	mutex_unlock(&ctx->irq_lock);
> +}
> +
> +int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset, int eventfd)
> +{
> +	struct afu_irq *irq;
> +	struct eventfd_ctx *ev_ctx;
> +	int rc = 0, id = irq_offset_to_id(ctx, irq_offset);
> +
> +	mutex_lock(&ctx->irq_lock);
> +	irq = idr_find(&ctx->irq_idr, id);
> +	if (!irq) {
> +		rc = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	ev_ctx = eventfd_ctx_fdget(eventfd);
> +	if (IS_ERR(ev_ctx)) {
> +		rc = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	irq->ev_ctx = ev_ctx;
> +unlock:
> +	mutex_unlock(&ctx->irq_lock);
> +	return rc;
> +}
> +
> +u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset)
> +{
> +	struct afu_irq *irq;
> +	int id = irq_offset_to_id(ctx, irq_offset);
> +	u64 addr = 0;
> +
> +	mutex_lock(&ctx->irq_lock);
> +	irq = idr_find(&ctx->irq_idr, id);
> +	if (irq)
> +		addr = irq->trigger_page;
> +	mutex_unlock(&ctx->irq_lock);
> +	return addr;
> +}
> diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c
> index 0bc0dd97d784..19575269ed22 100644
> --- a/drivers/misc/ocxl/context.c
> +++ b/drivers/misc/ocxl/context.c
> @@ -38,6 +38,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
>  	mutex_init(&ctx->mapping_lock);
>  	init_waitqueue_head(&ctx->events_wq);
>  	mutex_init(&ctx->xsl_error_lock);
> +	mutex_init(&ctx->irq_lock);
> +	idr_init(&ctx->irq_idr);
>  	/*
>  	 * Keep a reference on the AFU to make sure it's valid for the
>  	 * duration of the life of the context
> @@ -87,6 +89,19 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
>  	return rc;
>  }
>  
> +static int map_afu_irq(struct vm_area_struct *vma, unsigned long address,
> +		u64 offset, struct ocxl_context *ctx)
> +{
> +	u64 trigger_addr;
> +
> +	trigger_addr = ocxl_afu_irq_get_addr(ctx, offset);
> +	if (!trigger_addr)
> +		return VM_FAULT_SIGBUS;
> +
> +	vm_insert_pfn(vma, address, trigger_addr >> PAGE_SHIFT);
> +	return VM_FAULT_NOPAGE;
> +}
> +
>  static int map_pp_mmio(struct vm_area_struct *vma, unsigned long address,
>  		u64 offset, struct ocxl_context *ctx)
>  {
> @@ -125,7 +140,10 @@ static int ocxl_mmap_fault(struct vm_fault *vmf)
>  	pr_debug("%s: pasid %d address 0x%lx offset 0x%llx\n", __func__,
>  		ctx->pasid, vmf->address, offset);
>  
> -	rc = map_pp_mmio(vma, vmf->address, offset, ctx);
> +	if (offset < ctx->afu->irq_base_offset)
> +		rc = map_pp_mmio(vma, vmf->address, offset, ctx);
> +	else
> +		rc = map_afu_irq(vma, vmf->address, offset, ctx);
>  	return rc;
>  }
>  
> @@ -133,6 +151,19 @@ static const struct vm_operations_struct ocxl_vmops = {
>  	.fault = ocxl_mmap_fault,
>  };
>  
> +static int check_mmap_afu_irq(struct ocxl_context *ctx,
> +			struct vm_area_struct *vma)
> +{
> +	/* only one page */
> +	if (vma_pages(vma) != 1)
> +		return -EINVAL;
> +
> +	/* check offset validty */
> +	if (!ocxl_afu_irq_get_addr(ctx, vma->vm_pgoff << PAGE_SHIFT))
> +		return -EINVAL;
> +	return 0;
> +}
> +
>  static int check_mmap_mmio(struct ocxl_context *ctx,
>  			struct vm_area_struct *vma)
>  {
> @@ -146,7 +177,10 @@ int ocxl_context_mmap(struct ocxl_context *ctx, struct vm_area_struct *vma)
>  {
>  	int rc;
>  
> -	rc = check_mmap_mmio(ctx, vma);
> +	if ((vma->vm_pgoff << PAGE_SHIFT) < ctx->afu->irq_base_offset)
> +		rc = check_mmap_mmio(ctx, vma);
> +	else
> +		rc = check_mmap_afu_irq(ctx, vma);
>  	if (rc)
>  		return rc;
>  
> @@ -231,6 +265,8 @@ void ocxl_context_free(struct ocxl_context *ctx)
>  	idr_remove(&ctx->afu->contexts_idr, ctx->pasid);
>  	mutex_unlock(&ctx->afu->contexts_lock);
>  
> +	ocxl_afu_irq_free_all(ctx);
> +	idr_destroy(&ctx->irq_idr);
>  	/* reference to the AFU taken in ocxl_context_init */
>  	ocxl_afu_put(ctx->afu);
>  	kfree(ctx);
> diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
> index a51386eff4f5..0a73e2c11ba6 100644
> --- a/drivers/misc/ocxl/file.c
> +++ b/drivers/misc/ocxl/file.c
> @@ -110,12 +110,17 @@ static long afu_ioctl_attach(struct ocxl_context *ctx,
>  }
>  
>  #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" :			\
> +			x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" :	\
> +			x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" :		\
> +			x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" :	\
>  			"UNKNOWN")
>  
>  static long afu_ioctl(struct file *file, unsigned int cmd,
>  		unsigned long args)
>  {
>  	struct ocxl_context *ctx = file->private_data;
> +	struct ocxl_ioctl_irq_fd irq_fd;
> +	u64 irq_offset;
>  	long rc;
>  
>  	pr_debug("%s for context %d, command %s\n", __func__, ctx->pasid,
> @@ -130,6 +135,34 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
>  				(struct ocxl_ioctl_attach __user *) args);
>  		break;
>  
> +	case OCXL_IOCTL_IRQ_ALLOC:
> +		rc = ocxl_afu_irq_alloc(ctx, &irq_offset);
> +		if (!rc) {
> +			rc = copy_to_user((u64 *) args, &irq_offset,
> +					sizeof(irq_offset));
> +			if (rc)
> +				ocxl_afu_irq_free(ctx, irq_offset);
> +		}
> +		break;
> +
> +	case OCXL_IOCTL_IRQ_FREE:
> +		rc = copy_from_user(&irq_offset, (u64 *) args,
> +				sizeof(irq_offset));
> +		if (rc)
> +			return -EFAULT;
> +		rc = ocxl_afu_irq_free(ctx, irq_offset);
> +		break;
> +
> +	case OCXL_IOCTL_IRQ_SET_FD:
> +		rc = copy_from_user(&irq_fd, (u64 *) args, sizeof(irq_fd));
> +		if (rc)
> +			return -EFAULT;
> +		if (irq_fd.reserved)
> +			return -EINVAL;
> +		rc = ocxl_afu_irq_set_fd(ctx, irq_fd.irq_offset,
> +					irq_fd.eventfd);
> +		break;
> +
>  	default:
>  		rc = -EINVAL;
>  	}
> diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
> index 6b184cd7d2a6..5f12564eea99 100644
> --- a/drivers/misc/ocxl/link.c
> +++ b/drivers/misc/ocxl/link.c
> @@ -608,3 +608,31 @@ int ocxl_link_remove_pe(void *link_handle, int pasid)
>  	mutex_unlock(&spa->spa_lock);
>  	return rc;
>  }
> +
> +int ocxl_link_irq_alloc(void *link_handle, int *hw_irq, u64 *trigger_addr)
> +{
> +	struct link *link = (struct link *) link_handle;
> +	int rc, irq;
> +	u64 addr;
> +
> +	if (atomic_dec_if_positive(&link->irq_available) < 0)
> +		return -ENOSPC;
> +
> +	rc = pnv_ocxl_alloc_xive_irq(&irq, &addr);
> +	if (rc) {
> +		atomic_inc(&link->irq_available);
> +		return rc;
> +	}
> +
> +	*hw_irq = irq;
> +	*trigger_addr = addr;
> +	return 0;
> +}
> +
> +void ocxl_link_free_irq(void *link_handle, int hw_irq)
> +{
> +	struct link *link = (struct link *) link_handle;
> +
> +	pnv_ocxl_free_xive_irq(hw_irq);
> +	atomic_inc(&link->irq_available);
> +}
> diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
> index e07f7d523275..829369c5f004 100644
> --- a/drivers/misc/ocxl/ocxl_internal.h
> +++ b/drivers/misc/ocxl/ocxl_internal.h
> @@ -197,4 +197,11 @@ extern void ocxl_context_free(struct ocxl_context *ctx);
>  extern int ocxl_sysfs_add_afu(struct ocxl_afu *afu);
>  extern void ocxl_sysfs_remove_afu(struct ocxl_afu *afu);
>  
> +extern int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset);
> +extern int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset);
> +extern void ocxl_afu_irq_free_all(struct ocxl_context *ctx);
> +extern int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset,
> +			int eventfd);
> +extern u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset);
> +
>  #endif /* _OCXL_INTERNAL_H_ */
> diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h
> index 71fa387f2efd..488e75228c33 100644
> --- a/include/uapi/misc/ocxl.h
> +++ b/include/uapi/misc/ocxl.h
> @@ -39,9 +39,18 @@ struct ocxl_ioctl_attach {
>  	__u64 reserved3;
>  };
>  
> +struct ocxl_ioctl_irq_fd {
> +	__u64 irq_offset;
> +	__s32 eventfd;
> +	__u32 reserved;
> +};
> +
>  /* ioctl numbers */
>  #define OCXL_MAGIC 0xCA
>  /* AFU devices */
>  #define OCXL_IOCTL_ATTACH	_IOW(OCXL_MAGIC, 0x10, struct ocxl_ioctl_attach)
> +#define OCXL_IOCTL_IRQ_ALLOC	_IOR(OCXL_MAGIC, 0x11, __u64)
> +#define OCXL_IOCTL_IRQ_FREE	_IOW(OCXL_MAGIC, 0x12, __u64)
> +#define OCXL_IOCTL_IRQ_SET_FD	_IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
>  
>  #endif /* _UAPI_MISC_OCXL_H */

^ permalink raw reply

* Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE
From: Nicholas Piggin @ 2017-12-19  2:46 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Torsten Duwe, linux-kernel, Jiri Kosina, live-patching,
	linuxppc-dev
In-Reply-To: <20171218185622.rgoyy5doyh3gyqh5@treble>

On Mon, 18 Dec 2017 12:56:22 -0600
Josh Poimboeuf <jpoimboe@redhat.com> wrote:

> On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> > On Sun, 17 Dec 2017 20:58:54 -0600
> > Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> >   
> > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:  
> > > > On Tue, 12 Dec 2017 08:05:01 -0600
> > > > Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> > > >     
> > > > > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:    
> > > > > > Hi all,
> > > > > > 
> > > > > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> > > > > > 
> > > > > > [...] There are several rules that must be adhered to in order to ensure
> > > > > > reliable and consistent call chain backtracing:
> > > > > > 
> > > > > > * Before a function calls any other function, it shall establish its
> > > > > >   own stack frame, whose size shall be a multiple of 16 bytes.      
> > > > > 
> > > > > What about leaf functions?  If a leaf function doesn't establish a stack
> > > > > frame, and it has inline asm which contains a blr to another function,
> > > > > this ABI is broken.    
> > > 
> > > Oops, I meant to say "bl" instead of "blr".
> > >   
> > > > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > > > inline asm before it sets up the stack frame?  (This is an occasional
> > > > > problem on x86.)    
> > > > 
> > > > Inline asm must not have control transfer out of the statement unless
> > > > it is asm goto.    
> > > 
> > > Can inline asm have calls to other functions?  
> > 
> > I don't believe so.  
> 
> It's allowed on x86, I don't see why it wouldn't be allowed on powerpc.

It's not allowed in general, but there's a lot of architecture specific
differences there, so maybe x86 has an exception. I don't think such an
exception exists for powerpc.... If you know exactly how the code
generation works then you could write inline asm works.

> As you mentioned, GCC doesn't pay attention to what's inside asm("").

And as you mentioned, it doesn't set up the stack frame properly for
leaf functions that call others in asm. There's other concerns too like
different ABI versions (v1/v2) have different stack and calling
conventions.

> > > > > Also, what about hand-coded asm?    
> > > > 
> > > > Should follow the same rules if it uses the stack.    
> > > 
> > > How is that enforced?  
> > 
> > It's not, AFAIK. Gcc doesn't understand what's inside asm("").  
> 
> Here I was talking about .S files.

Not enforced, but you can assume hand coded asm will not set up a
non-standard stack frame and calling convention, that would be a
bug.

> 
> > > > > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > > > > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > > > > > user of this flag so far is livepatching, which is only implemented on
> > > > > > PPCs with 64-LE, a.k.a. ELF ABI v2.      
> > > > > 
> > > > > In addition to fixing the above issues, the unwinder also needs to
> > > > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > > > blocked task.  If a function were preempted before it created a stack
> > > > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > > > will skip the function's caller, so such a trace will need to be
> > > > > reported to livepatch as unreliable.    
> > > > 
> > > > I don't think there is much problem there for powerpc. Stack frame
> > > > creation and function call with return pointer are each atomic.    
> > > 
> > > What if the function is interrupted before it creates the stack frame?
> > >   
> > 
> > Then there will be no stack frame, but you still get the caller address
> > because it's saved in LR register as part of the function call. Then
> > you get the caller's caller in its stack frame.  
> 
> Ok.  So what about the interrupted function itself?  Looking at the
> powerpc version of save_context_stack(), it doesn't do anything special
> for exception frames like checking regs->nip.
> 
> Though it looks like that should be possible since show_stack() has a
> way to identify exception frames.
> 

Yes, the low level interrupt code stores a marker in the stack frame
which identifies where an exception occurs.

Thanks,
Nick

^ permalink raw reply

* Re: [trivial PATCH] treewide: Align function definition open/close braces
From: Darrick J. Wong @ 2017-12-18 22:08 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jiri Kosina, Linus Torvalds, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-media, MPT-FusionLinux.pdl, linux-scsi, netdev,
	linux-wireless, acpi4asus-user, platform-driver-x86, linux-rtc,
	linux-fsdevel, ocfs2-devel, linux-xfs, linux-audit, alsa-devel,
	linuxppc-dev
In-Reply-To: <1513556924.31581.51.camel@perches.com>

On Sun, Dec 17, 2017 at 04:28:44PM -0800, Joe Perches wrote:
> Some functions definitions have either the initial open brace and/or
> the closing brace outside of column 1.
> 
> Move those braces to column 1.
> 
> This allows various function analyzers like gnu complexity to work
> properly for these modified functions.
> 
> Miscellanea:
> 
> o Remove extra trailing ; and blank line from xfs_agf_verify
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> git diff -w shows no difference other than the above 'Miscellanea'
> 
> (this is against -next, but it applies against Linus' tree
>  with a couple offsets)
> 
>  arch/x86/include/asm/atomic64_32.h                   |  2 +-
>  drivers/acpi/custom_method.c                         |  2 +-
>  drivers/acpi/fan.c                                   |  2 +-
>  drivers/gpu/drm/amd/display/dc/core/dc.c             |  2 +-
>  drivers/media/i2c/msp3400-kthreads.c                 |  2 +-
>  drivers/message/fusion/mptsas.c                      |  2 +-
>  drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c |  2 +-
>  drivers/net/wireless/ath/ath9k/xmit.c                |  2 +-
>  drivers/platform/x86/eeepc-laptop.c                  |  2 +-
>  drivers/rtc/rtc-ab-b5ze-s3.c                         |  2 +-
>  drivers/scsi/dpt_i2o.c                               |  2 +-
>  drivers/scsi/sym53c8xx_2/sym_glue.c                  |  2 +-
>  fs/locks.c                                           |  2 +-
>  fs/ocfs2/stack_user.c                                |  2 +-
>  fs/xfs/libxfs/xfs_alloc.c                            |  5 ++---
>  fs/xfs/xfs_export.c                                  |  2 +-
>  kernel/audit.c                                       |  6 +++---
>  kernel/trace/trace_printk.c                          |  4 ++--
>  lib/raid6/sse2.c                                     | 14 +++++++-------
>  sound/soc/fsl/fsl_dma.c                              |  2 +-
>  20 files changed, 30 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
> index 97c46b8169b7..d4d4883080fa 100644
> --- a/arch/x86/include/asm/atomic64_32.h
> +++ b/arch/x86/include/asm/atomic64_32.h
> @@ -122,7 +122,7 @@ static inline long long atomic64_read(const atomic64_t *v)
>  	long long r;
>  	alternative_atomic64(read, "=&A" (r), "c" (v) : "memory");
>  	return r;
> - }
> +}
>  
>  /**
>   * atomic64_add_return - add and return
> diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
> index c68e72414a67..e967c1173ba3 100644
> --- a/drivers/acpi/custom_method.c
> +++ b/drivers/acpi/custom_method.c
> @@ -94,7 +94,7 @@ static void __exit acpi_custom_method_exit(void)
>  {
>  	if (cm_dentry)
>  		debugfs_remove(cm_dentry);
> - }
> +}
>  
>  module_init(acpi_custom_method_init);
>  module_exit(acpi_custom_method_exit);
> diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
> index 6cf4988206f2..3563103590c6 100644
> --- a/drivers/acpi/fan.c
> +++ b/drivers/acpi/fan.c
> @@ -219,7 +219,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
>  		return fan_set_state_acpi4(device, state);
>  	else
>  		return fan_set_state(device, state);
> - }
> +}
>  
>  static const struct thermal_cooling_device_ops fan_cooling_ops = {
>  	.get_max_state = fan_get_max_state,
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
> index d1488d5ee028..1e0d1e7c5324 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
> @@ -461,7 +461,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
>   ******************************************************************************/
>  
>  struct dc *dc_create(const struct dc_init_data *init_params)
> - {
> +{
>  	struct dc *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
>  	unsigned int full_pipe_count;
>  
> diff --git a/drivers/media/i2c/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c
> index 4dd01e9f553b..dc6cb8d475b3 100644
> --- a/drivers/media/i2c/msp3400-kthreads.c
> +++ b/drivers/media/i2c/msp3400-kthreads.c
> @@ -885,7 +885,7 @@ static int msp34xxg_modus(struct i2c_client *client)
>  }
>  
>  static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
> - {
> +{
>  	struct msp_state *state = to_state(i2c_get_clientdata(client));
>  	int source, matrix;
>  
> diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
> index 345f6035599e..69a62d23514b 100644
> --- a/drivers/message/fusion/mptsas.c
> +++ b/drivers/message/fusion/mptsas.c
> @@ -2968,7 +2968,7 @@ mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
>  	mutex_unlock(&ioc->sas_mgmt.mutex);
>  out:
>  	return ret;
> - }
> +}
>  
>  static void
>  mptsas_parse_device_info(struct sas_identify *identify,
> diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> index 3dd973475125..0ea141ece19e 100644
> --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> @@ -603,7 +603,7 @@ static struct uni_table_desc *nx_get_table_desc(const u8 *unirom, int section)
>  
>  static int
>  netxen_nic_validate_header(struct netxen_adapter *adapter)
> - {
> +{
>  	const u8 *unirom = adapter->fw->data;
>  	struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
>  	u32 fw_file_size = adapter->fw->size;
> diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
> index bd438062a6db..baedc7186b10 100644
> --- a/drivers/net/wireless/ath/ath9k/xmit.c
> +++ b/drivers/net/wireless/ath/ath9k/xmit.c
> @@ -196,7 +196,7 @@ ath_tid_pull(struct ath_atx_tid *tid)
>  	}
>  
>  	return skb;
> - }
> +}
>  
>  static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
>  {
> diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
> index 5a681962899c..4c38904a8a32 100644
> --- a/drivers/platform/x86/eeepc-laptop.c
> +++ b/drivers/platform/x86/eeepc-laptop.c
> @@ -492,7 +492,7 @@ static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
>   * potentially bad time, such as a timer interrupt.
>   */
>  static void tpd_led_update(struct work_struct *work)
> - {
> +{
>  	struct eeepc_laptop *eeepc;
>  
>  	eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
> diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
> index a319bf1e49de..ef5c16dfabfa 100644
> --- a/drivers/rtc/rtc-ab-b5ze-s3.c
> +++ b/drivers/rtc/rtc-ab-b5ze-s3.c
> @@ -648,7 +648,7 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
>  			ret);
>  
>  	return ret;
> - }
> +}
>  
>  /* Enable or disable battery low irq generation */
>  static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap,
> diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
> index fd172b0890d3..a00d822e3142 100644
> --- a/drivers/scsi/dpt_i2o.c
> +++ b/drivers/scsi/dpt_i2o.c
> @@ -3524,7 +3524,7 @@ static int adpt_i2o_systab_send(adpt_hba* pHba)
>  #endif
>  
>  	return ret;	
> - }
> +}
>  
>  
>  /*============================================================================
> diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
> index 791a2182de53..7320d5fe4cbc 100644
> --- a/drivers/scsi/sym53c8xx_2/sym_glue.c
> +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
> @@ -1393,7 +1393,7 @@ static struct Scsi_Host *sym_attach(struct scsi_host_template *tpnt, int unit,
>  		scsi_host_put(shost);
>  
>  	return NULL;
> - }
> +}
>  
>  
>  /*
> diff --git a/fs/locks.c b/fs/locks.c
> index 21b4dfa289ee..d2399d001afe 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -559,7 +559,7 @@ static const struct lock_manager_operations lease_manager_ops = {
>   * Initialize a lease, use the default lock manager operations
>   */
>  static int lease_init(struct file *filp, long type, struct file_lock *fl)
> - {
> +{
>  	if (assign_type(fl, type) != 0)
>  		return -EINVAL;
>  
> diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
> index dae9eb7c441e..d2fb97b173da 100644
> --- a/fs/ocfs2/stack_user.c
> +++ b/fs/ocfs2/stack_user.c
> @@ -398,7 +398,7 @@ static int ocfs2_control_do_setnode_msg(struct file *file,
>  
>  static int ocfs2_control_do_setversion_msg(struct file *file,
>  					   struct ocfs2_control_message_setv *msg)
> - {
> +{
>  	long major, minor;
>  	char *ptr = NULL;
>  	struct ocfs2_control_private *p = file->private_data;
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index 0da80019a917..217108f765d5 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -2401,7 +2401,7 @@ static bool
>  xfs_agf_verify(
>  	struct xfs_mount *mp,
>  	struct xfs_buf	*bp)
> - {
> +{
>  	struct xfs_agf	*agf = XFS_BUF_TO_AGF(bp);
>  
>  	if (xfs_sb_version_hascrc(&mp->m_sb)) {
> @@ -2449,8 +2449,7 @@ xfs_agf_verify(
>  	     be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS))
>  		return false;
>  
> -	return true;;
> -
> +	return true;
>  }
>  
>  static void
> diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
> index fe1bfee35898..7d5c355d78b5 100644
> --- a/fs/xfs/xfs_export.c
> +++ b/fs/xfs/xfs_export.c
> @@ -122,7 +122,7 @@ xfs_nfs_get_inode(
>  	struct super_block	*sb,
>  	u64			ino,
>  	u32			generation)
> - {
> +{
>   	xfs_mount_t		*mp = XFS_M(sb);
>  	xfs_inode_t		*ip;
>  	int			error;


The xfs bits look ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> diff --git a/kernel/audit.c b/kernel/audit.c
> index 227db99b0f19..d97e8f0f73ca 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -443,15 +443,15 @@ static int audit_set_failure(u32 state)
>   * Drop any references inside the auditd connection tracking struct and free
>   * the memory.
>   */
> - static void auditd_conn_free(struct rcu_head *rcu)
> - {
> +static void auditd_conn_free(struct rcu_head *rcu)
> +{
>  	struct auditd_connection *ac;
>  
>  	ac = container_of(rcu, struct auditd_connection, rcu);
>  	put_pid(ac->pid);
>  	put_net(ac->net);
>  	kfree(ac);
> - }
> +}
>  
>  /**
>   * auditd_set - Set/Reset the auditd connection state
> diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
> index ad1d6164e946..50f44b7b2b32 100644
> --- a/kernel/trace/trace_printk.c
> +++ b/kernel/trace/trace_printk.c
> @@ -196,7 +196,7 @@ struct notifier_block module_trace_bprintk_format_nb = {
>  };
>  
>  int __trace_bprintk(unsigned long ip, const char *fmt, ...)
> - {
> +{
>  	int ret;
>  	va_list ap;
>  
> @@ -214,7 +214,7 @@ int __trace_bprintk(unsigned long ip, const char *fmt, ...)
>  EXPORT_SYMBOL_GPL(__trace_bprintk);
>  
>  int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap)
> - {
> +{
>  	if (unlikely(!fmt))
>  		return 0;
>  
> diff --git a/lib/raid6/sse2.c b/lib/raid6/sse2.c
> index 1d2276b007ee..8191e1d0d2fb 100644
> --- a/lib/raid6/sse2.c
> +++ b/lib/raid6/sse2.c
> @@ -91,7 +91,7 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs)
>  
>  static void raid6_sse21_xor_syndrome(int disks, int start, int stop,
>  				     size_t bytes, void **ptrs)
> - {
> +{
>  	u8 **dptr = (u8 **)ptrs;
>  	u8 *p, *q;
>  	int d, z, z0;
> @@ -200,9 +200,9 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs)
>  	kernel_fpu_end();
>  }
>  
> - static void raid6_sse22_xor_syndrome(int disks, int start, int stop,
> +static void raid6_sse22_xor_syndrome(int disks, int start, int stop,
>  				     size_t bytes, void **ptrs)
> - {
> +{
>  	u8 **dptr = (u8 **)ptrs;
>  	u8 *p, *q;
>  	int d, z, z0;
> @@ -265,7 +265,7 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs)
>  
>  	asm volatile("sfence" : : : "memory");
>  	kernel_fpu_end();
> - }
> +}
>  
>  const struct raid6_calls raid6_sse2x2 = {
>  	raid6_sse22_gen_syndrome,
> @@ -366,9 +366,9 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs)
>  	kernel_fpu_end();
>  }
>  
> - static void raid6_sse24_xor_syndrome(int disks, int start, int stop,
> +static void raid6_sse24_xor_syndrome(int disks, int start, int stop,
>  				     size_t bytes, void **ptrs)
> - {
> +{
>  	u8 **dptr = (u8 **)ptrs;
>  	u8 *p, *q;
>  	int d, z, z0;
> @@ -471,7 +471,7 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs)
>  	}
>  	asm volatile("sfence" : : : "memory");
>  	kernel_fpu_end();
> - }
> +}
>  
>  
>  const struct raid6_calls raid6_sse2x4 = {
> diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
> index 0c11f434a374..ec619f51d336 100644
> --- a/sound/soc/fsl/fsl_dma.c
> +++ b/sound/soc/fsl/fsl_dma.c
> @@ -879,7 +879,7 @@ static const struct snd_pcm_ops fsl_dma_ops = {
>  };
>  
>  static int fsl_soc_dma_probe(struct platform_device *pdev)
> - {
> +{
>  	struct dma_object *dma;
>  	struct device_node *np = pdev->dev.of_node;
>  	struct device_node *ssi_np;
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 02/13] powerpc/powernv: Set correct configuration space size for opencapi devices
From: Andrew Donnellan @ 2017-12-19  1:14 UTC (permalink / raw)
  To: Frederic Barrat, linuxppc-dev, linux-kernel; +Cc: arnd, gregkh, mpe, alastair
In-Reply-To: <386af9b4afde2a0f9cd699d79b0fdf3e4fc0e2d7.1513608243.git.fbarrat@linux.vnet.ibm.com>

On 19/12/17 02:21, Frederic Barrat wrote:
>  From Andrew Donnellan <andrew.donnellan@au1.ibm.com>

Good try :) That should be "From: ..."

git format-patch/send-email will handle this automatically if the commit 
author is set correctly, ie:

git commit --amend --author="Andrew Donnellan 
<andrew.donnellan@au1.ibm.com>"

> 
> The configuration space for opencapi devices doesn't have a PCI
> Express capability, therefore confusing linux in thinking it's of an
> old PCI type with a 256-byte configuration space size, instead of the
> desired 4k. So add a PCI fixup to declare the correct size.
> 
> 
> Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
> ---
>   arch/powerpc/platforms/powernv/pci-ioda.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
> index c37b5d288f9c..b8ec76aa266f 100644
> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
> @@ -4079,6 +4079,16 @@ void __init pnv_pci_init_npu2_opencapi_phb(struct device_node *np)
>   	pnv_pci_init_ioda_phb(np, 0, PNV_PHB_NPU_OCAPI);
>   }
> 
> +static void pnv_npu2_opencapi_cfg_size_fixup(struct pci_dev *dev)
> +{
> +	struct pci_controller *hose = pci_bus_to_host(dev->bus);
> +	struct pnv_phb *phb = hose->private_data;
> +
> +	if (phb->type == PNV_PHB_NPU_OCAPI)
> +		dev->cfg_size = PCI_CFG_SPACE_EXP_SIZE;
> +}
> +DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pnv_npu2_opencapi_cfg_size_fixup);
> +
>   void __init pnv_pci_init_ioda_hub(struct device_node *np)
>   {
>   	struct device_node *phbn;
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com  IBM Australia Limited

^ permalink raw reply

* Re: [PATCH 03/13] powerpc/powernv: Add opal calls for opencapi
From: Andrew Donnellan @ 2017-12-19  0:47 UTC (permalink / raw)
  To: Frederic Barrat, linuxppc-dev, linux-kernel; +Cc: gregkh, alastair, arnd
In-Reply-To: <f2189f8a9c578e5515472b0f44e5469ce36f9e5f.1513608243.git.fbarrat@linux.vnet.ibm.com>

On 19/12/17 02:21, Frederic Barrat wrote:
> Add opal calls to interact with the NPU:
> 
> OPAL_NPU_SPA_SETUP: set the Shared Process Area (SPA)
> The SPA is a table containing one entry (Process Element) per memory
> context which can be accessed by the opencapi device.
> 
> OPAL_NPU_SPA_CLEAR_CACHE: clear the context cache
> The NPU keeps a cache of recently accessed memory contexts. When a
> Process Element is removed from the SPA, the cache for the link must
> be cleared.
> 
> OPAL_NPU_TL_SET: configure the Transaction Layer
> The Transaction Layer specification defines several templates for
> messages to be exchanged on the link. During link setup, the host and
> device must negotiate what templates are supported on both sides and
> at what rates those messages can be sent.
> 
> 
> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>

Corresponding skiboot patch: https://patchwork.ozlabs.org/patch/849830/

Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>

> ---
>   arch/powerpc/include/asm/opal-api.h            | 5 ++++-
>   arch/powerpc/include/asm/opal.h                | 6 ++++++
>   arch/powerpc/platforms/powernv/opal-wrappers.S | 3 +++
>   3 files changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
> index 233c7504b1f2..24c73f5575ee 100644
> --- a/arch/powerpc/include/asm/opal-api.h
> +++ b/arch/powerpc/include/asm/opal-api.h
> @@ -201,7 +201,10 @@
>   #define OPAL_SET_POWER_SHIFT_RATIO		155
>   #define OPAL_SENSOR_GROUP_CLEAR			156
>   #define OPAL_PCI_SET_P2P			157
> -#define OPAL_LAST				157
> +#define OPAL_NPU_SPA_SETUP			159
> +#define OPAL_NPU_SPA_CLEAR_CACHE		160
> +#define OPAL_NPU_TL_SET				161
> +#define OPAL_LAST				161
>   
>   /* Device tree flags */
>   
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 0c545f7fc77b..12e70fb58700 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -34,6 +34,12 @@ int64_t opal_npu_init_context(uint64_t phb_id, int pasid, uint64_t msr,
>   			uint64_t bdf);
>   int64_t opal_npu_map_lpar(uint64_t phb_id, uint64_t bdf, uint64_t lparid,
>   			uint64_t lpcr);
> +int64_t opal_npu_spa_setup(uint64_t phb_id, uint32_t bdfn,
> +			uint64_t addr, uint64_t PE_mask);
> +int64_t opal_npu_spa_clear_cache(uint64_t phb_id, uint32_t bdfn,
> +				uint64_t PE_handle);
> +int64_t opal_npu_tl_set(uint64_t phb_id, uint32_t bdfn, long cap,
> +			uint64_t rate_phys, uint32_t size);

The function prototype on the skiboot side has slightly different 
parameter names: long capabilities, uint32_t rate_sz.

>   int64_t opal_console_write(int64_t term_number, __be64 *length,
>   			   const uint8_t *buffer);
>   int64_t opal_console_read(int64_t term_number, __be64 *length,
> diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
> index 6f4b00a2ac46..1b2936ba6040 100644
> --- a/arch/powerpc/platforms/powernv/opal-wrappers.S
> +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
> @@ -320,3 +320,6 @@ OPAL_CALL(opal_set_powercap,			OPAL_SET_POWERCAP);
>   OPAL_CALL(opal_get_power_shift_ratio,		OPAL_GET_POWER_SHIFT_RATIO);
>   OPAL_CALL(opal_set_power_shift_ratio,		OPAL_SET_POWER_SHIFT_RATIO);
>   OPAL_CALL(opal_sensor_group_clear,		OPAL_SENSOR_GROUP_CLEAR);
> +OPAL_CALL(opal_npu_spa_setup,			OPAL_NPU_SPA_SETUP);
> +OPAL_CALL(opal_npu_spa_clear_cache,		OPAL_NPU_SPA_CLEAR_CACHE);
> +OPAL_CALL(opal_npu_tl_set,			OPAL_NPU_TL_SET);
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com  IBM Australia Limited

^ permalink raw reply

* Re: [PATCH v9 29/51] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
From: Ram Pai @ 2017-12-18 23:15 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-arch, ebiederm, arnd, corbet, x86, linux-doc, linux-kernel,
	mhocko, linux-mm, mingo, paulus, aneesh.kumar, linux-kselftest,
	bauerman, akpm, linuxppc-dev, khandual
In-Reply-To: <e7971d03-6ad1-40d5-9b79-f01242db5293@intel.com>

On Mon, Dec 18, 2017 at 02:28:14PM -0800, Dave Hansen wrote:
> On 12/18/2017 02:18 PM, Ram Pai wrote:
> > b) minimum number of keys available to the application.
> > 	if libraries consumes a few, they could provide a library
> > 	interface to the application informing the number available to
> > 	the application.  The library interface can leverage (b) to
> > 	provide the information.
> 
> OK, let's see a real user of this including a few libraries.  Then we'll
> put it in the kernel.
> 
> > c) types of disable-rights supported by keys.
> > 	Helps the application to determine the types of disable-features
> > 	available. This is helpful, otherwise the app has to 
> > 	make pkey_alloc() call with the corresponding parameter set
> > 	and see if it suceeds or fails. Painful from an application
> > 	point of view, in my opinion.
> 
> Again, let's see a real-world use of this.  How does it look?  How does
> an app "fall back" if it can't set a restriction the way it wants to?
> 
> Are we *sure* that such an interface makes sense?  For instance, will it
> be possible for some keys to be execute-disable while other are only
> write-disable?

Can it be on x86?

its not possible on ppc. the keys can *all* be  the-same-attributes-disable all the
time.

However you are right. Its conceivable that some arch could provide a
feature where it can be x-attribute-disable for key 'a' and
y-attribute-disable for key 'b'.  But than its a bit of a headache
for an application to consume such a feature.

Ben: I recall you requesting this feature.  Thoughts?

> 
> > I think on x86 you look for some hardware registers to determine
> > which hardware features are enabled by the kernel.
> 
> No, we use CPUID.  It's a part of the ISA that's designed for
> enumerating CPU and (sometimes) OS support for CPU features.
> 
> > We do not have generic support for something like that on ppc.  The
> > kernel looks at the device tree to determine what hardware features
> > are available. But does not have mechanism to tell the hardware to
> > track which of its features are currently enabled/used by the
> > kernel; atleast not for the memory-key feature.
> 
> Bummer.  You're missing out.
> 
> But, you could still do this with a syscall.  "Hey, kernel, do you
> support this feature?"

or do powerpc specific sysfs interface.
or a debugfs interface.

RP

^ permalink raw reply

* Re: [PATCH v4 00/11] ASoC: fsl_ssi: Clean up - coding style level
From: Caleb Crome @ 2017-12-19  0:25 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: Mark Brown, Timur Tabi, linux-kernel, linuxppc-dev, alsa-devel,
	Liam Girdwood, Fabio Estevam, mail, Arnaud Mouiche, lukma,
	Sascha Hauer
In-Reply-To: <20171218230220.GA16161@Asurada-Nvidia>

On Mon, Dec 18, 2017 at 3:02 PM, Nicolin Chen <nicoleotsuka@gmail.com> wrote:
> On Mon, Dec 18, 2017 at 02:19:08PM -0800, Caleb Crome wrote:
>
>> > Acked-by: Timur Tabi <timur@tabi.org>
>
> --- To Mark ---
>
> Mark, can you still take these changes first? Since this failed
> test that Caleb reported here is already existing on the top of
> the mainline tree, I would like to treat this mail as a separate
> bug report and fix it with a separate patch.
>
> Besides, this series of changes don't change any function flow.
>
> Thank you
>

Sorry!  I should have created a separate thread for this subject.  My
comments have *nothing* to do with this patch set, except they are
about the same source files.

>
> --- To Caleb ---
>
>> I'm re-setting up my loopback test to try to verify these most recent changes.
>
> I really appreciate your verification and help.

Of course!  I have this wandboard permanently set up for this
verification test, so that I can easily repeat whenever I touch our
kernel.

It's a dead-simple hardware mod just to connect TX to RX.

>
>> warn:   11a0 11a1 1160 11a3 11a4 11a5 11a6 11a7
>> warn: Valid frame after 1 invalid frames
>> warn:   11c0 11c1 11c2 11c3 11c4 11c5 11c6 11c7
>> warn: first invalid frame while expecting frame 0x00a0
>> warn:   13e7 1400 1401 1402 1403 1404 1405 1404
>> warn:   1407 1420 1421 1422 1423 1424 1425 1426
>> warn:   1427 1440 1441 1442 1443 1444 1445 1484
>> warn:   1447 1460 1461 1462 1463 1464 1465 1466
>>
>> Those last 4 lines are the channel slips -- the least significant
>> nibble should be the channel number:  i.e. should go 0, 1, 2, 3, 4, 5,
>> 6, 7.
>>
>> Ugh, so it's basically quite broken again -- before these patches.
>
> I remember Arnaud reviewed one of my changes back to September.
> So I suppose the test should be fine at that time -- so a change
> being merged recently might have impacted the test result.


It's certainly possible that I'm doing something wrong again -- it
wouldn't be the first time :-)

>
>> I guess I need to go backwards in time and see what rev re-broke it.
>> I don't really have time to dig too deep on this again.
>>
>> I'd be happy to provide the hardware to anybody that can diagnose and
>> debug this more quickly than I can.  I'm very inefficient at kernel
>> drivers I think.   My day job is acoustical and electrical
>> engineering.
>>
>> Here's what the hardware looks like for anybody that's interested.
>> Just a single wire loopback on the wandboard header.
>
> I would definitely like to take the hardware to debug it as long
> as you are willing to provide me. Can you send me a private mail
> to discuss about it?

Absolutely.
-Caleb


>
> Thanks
> Nicolin

^ permalink raw reply

* Re: [PATCH 00/13] New driver to support OpenCAPI devices on POWER9
From: Andrew Donnellan @ 2017-12-19  0:22 UTC (permalink / raw)
  To: Frederic Barrat, linuxppc-dev, linux-kernel
  Cc: arnd, gregkh, mpe, alastair, linux-accelerators
In-Reply-To: <cover.1513608243.git.fbarrat@linux.vnet.ibm.com>

On 19/12/17 02:21, Frederic Barrat wrote:
> This series adds support for Open Coherent Accelerator (ocxl) devices
> on POWER9 processor. OpenCAPI is a consortium developing the
> specifications for an interface between processors and accelerators,
> allowing sharing the host memory with the accelerators, using virtual
> addresses.
> 
> The OpenCAPI device can also have its own local memory and provide
> access to the host, though it is not supported by that series.
> 
> The OpenCAPI specification is processor agnostic, but this series adds
> support specifically for powerpc.
> 
> Even though the underlying transport is not PCI, the firmware
> abstracts the hardware like a PCI host bridge and Linux sees the
> OpenCAPI devices as PCI devices. So a lot of existing infrastructure
> and commands can be reused.
> 
> Patches 1-5:  add the platform-specific services needed by the driver
> Patches 6-10: driver code
> Patch 11:     small correction to existing cxl driver
> Patch 12:     documentation
> 
> Current limitations, that will be addressed in later patches:
>   - no capability to trigger a reset of the opencapi adapter
>   - no support for the 'wake_host_thread' command
>   - no support for adapters with a dual-link connection (none exists yet)
>   - no access to the adapter-local memory
> 
> Many people contributed directly or indirectly, from the software,
> hardware and bringup teams. In particular Andrew Donnellan and
> Alastair D'Silva, who are developing the related firmware and library.
> 
> Feedback welcome!

[+ linux-accelerators]

The corresponding patch series for skiboot/OPAL can be found at:

     https://patchwork.ozlabs.org/project/skiboot/list/?series=19043


Andrew

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com  IBM Australia Limited

^ permalink raw reply

* Re: [PATCH v4 00/11] ASoC: fsl_ssi: Clean up - coding style level
From: Nicolin Chen @ 2017-12-18 23:02 UTC (permalink / raw)
  To: Caleb Crome, Mark Brown
  Cc: Timur Tabi, linux-kernel, linuxppc-dev, alsa-devel, Liam Girdwood,
	Fabio Estevam, mail, Arnaud Mouiche, lukma, Sascha Hauer
In-Reply-To: <CAG5mAdxsWmHfCc=vFkO+Wmi8m0c_9t7B6BTUBGVOmPoGOQrsyg@mail.gmail.com>

On Mon, Dec 18, 2017 at 02:19:08PM -0800, Caleb Crome wrote:

> > Acked-by: Timur Tabi <timur@tabi.org>

--- To Mark ---

Mark, can you still take these changes first? Since this failed
test that Caleb reported here is already existing on the top of
the mainline tree, I would like to treat this mail as a separate
bug report and fix it with a separate patch.

Besides, this series of changes don't change any function flow.

Thank you


--- To Caleb ---

> I'm re-setting up my loopback test to try to verify these most recent changes.

I really appreciate your verification and help.

> warn:   11a0 11a1 1160 11a3 11a4 11a5 11a6 11a7
> warn: Valid frame after 1 invalid frames
> warn:   11c0 11c1 11c2 11c3 11c4 11c5 11c6 11c7
> warn: first invalid frame while expecting frame 0x00a0
> warn:   13e7 1400 1401 1402 1403 1404 1405 1404
> warn:   1407 1420 1421 1422 1423 1424 1425 1426
> warn:   1427 1440 1441 1442 1443 1444 1445 1484
> warn:   1447 1460 1461 1462 1463 1464 1465 1466
> 
> Those last 4 lines are the channel slips -- the least significant
> nibble should be the channel number:  i.e. should go 0, 1, 2, 3, 4, 5,
> 6, 7.
> 
> Ugh, so it's basically quite broken again -- before these patches.

I remember Arnaud reviewed one of my changes back to September.
So I suppose the test should be fine at that time -- so a change
being merged recently might have impacted the test result.

> I guess I need to go backwards in time and see what rev re-broke it.
> I don't really have time to dig too deep on this again.
> 
> I'd be happy to provide the hardware to anybody that can diagnose and
> debug this more quickly than I can.  I'm very inefficient at kernel
> drivers I think.   My day job is acoustical and electrical
> engineering.
> 
> Here's what the hardware looks like for anybody that's interested.
> Just a single wire loopback on the wandboard header.

I would definitely like to take the hardware to debug it as long
as you are willing to provide me. Can you send me a private mail
to discuss about it?

Thanks
Nicolin

^ permalink raw reply

* [PATCH v2 7/7] pseries/setup: Add Initialization of VF Bars
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

When enabling SR-IOV in pseries platform,
the VF bar properties for a PF are reported on
the device node in the device tree.

This patch adds the IOV Bar resources to Linux
structures from the device tree for later use
when configuring SR-IOV by PF driver.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/pci.h         |   2 +
 arch/powerpc/kernel/pci_of_scan.c      |   2 +-
 arch/powerpc/platforms/pseries/setup.c | 167 +++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 8dc32eacc97c..d82802ff5088 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -121,6 +121,8 @@ extern int remove_phb_dynamic(struct pci_controller *phb);
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
 					struct pci_bus *bus, int devfn);
 
+extern unsigned int pci_parse_of_flags(u32 addr0, int bridge);
+
 extern void of_scan_pci_bridge(struct pci_dev *dev);
 
 extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 0d790f8432d2..20ceec4a5f5e 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -38,7 +38,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
  * @addr0: value of 1st cell of a device tree PCI address.
  * @bridge: Set this flag if the address is from a bridge 'ranges' property
  */
-static unsigned int pci_parse_of_flags(u32 addr0, int bridge)
+unsigned int pci_parse_of_flags(u32 addr0, int bridge)
 {
 	unsigned int flags = 0;
 
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5f1beb8367ac..cbb716315070 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -459,6 +459,165 @@ static void __init find_and_init_phbs(void)
 	of_pci_check_probe_only();
 }
 
+#ifdef CONFIG_PCI_IOV
+enum rtas_iov_fw_value_map {
+	NUM_RES_PROPERTY  = 0, ///< Number of Resources
+	LOW_INT           = 1, ///< Lowest 32 bits of Address
+	START_OF_ENTRIES  = 2, ///< Always start of entry
+	APERTURE_PROPERTY = 2, ///< Start of entry+ to  Aperture Size
+	WDW_SIZE_PROPERTY = 4, ///< Start of entry+ to Window Size
+	NEXT_ENTRY        = 7  ///< Go to next entry on array
+};
+
+enum get_iov_fw_value_index {
+	BAR_ADDRS     = 1,    ///<  Get Bar Address
+	APERTURE_SIZE = 2,    ///<  Get Aperture Size
+	WDW_SIZE      = 3     ///<  Get Window Size
+};
+
+resource_size_t pseries_get_iov_fw_value(struct pci_dev *dev, int resno,
+					 enum get_iov_fw_value_index value)
+{
+	const int *indexes;
+	struct device_node *dn = pci_device_to_OF_node(dev);
+	int i, num_res, ret = 0;
+
+	indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
+	if (!indexes)
+		return  0;
+
+	/*
+	 * First element in the array is the number of Bars
+	 * returned.  Search through the list to find the matching
+	 * bar
+	 */
+	num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
+	if (resno >= num_res)
+		return 0; /* or an errror */
+
+	i = START_OF_ENTRIES + NEXT_ENTRY * resno;
+	switch (value) {
+	case BAR_ADDRS:
+		ret = of_read_number(&indexes[i], 2);
+		break;
+	case APERTURE_SIZE:
+		ret = of_read_number(&indexes[i + APERTURE_PROPERTY], 2);
+		break;
+	case WDW_SIZE:
+		ret = of_read_number(&indexes[i + WDW_SIZE_PROPERTY], 2);
+		break;
+	}
+
+	return ret;
+}
+
+void of_pci_set_vf_bar_size(struct pci_dev *dev, const int *indexes)
+{
+	struct resource *res;
+	resource_size_t base, size;
+	int i, r, num_res;
+
+	num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
+	num_res = min_t(int, num_res, PCI_SRIOV_NUM_BARS);
+	for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS;
+	     i += NEXT_ENTRY, r++) {
+		res = &dev->resource[r + PCI_IOV_RESOURCES];
+		base = of_read_number(&indexes[i], 2);
+		size = of_read_number(&indexes[i + APERTURE_PROPERTY], 2);
+		res->flags = pci_parse_of_flags(of_read_number
+						(&indexes[i + LOW_INT], 1), 0);
+		res->flags |= (IORESOURCE_MEM_64 | IORESOURCE_PCI_FIXED);
+		res->name = pci_name(dev);
+		res->start = base;
+		res->end = base + size - 1;
+	}
+}
+
+void of_pci_parse_iov_addrs(struct pci_dev *dev, const int *indexes)
+{
+	struct resource *res, *root, *conflict;
+	resource_size_t base, size;
+	int i, r, num_res;
+
+	/*
+	 * First element in the array is the number of Bars
+	 * returned.  Search through the list to find the matching
+	 * bars assign them from firmware into resources structure.
+	 */
+	num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
+	for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS;
+	     i += NEXT_ENTRY, r++) {
+		res = &dev->resource[r + PCI_IOV_RESOURCES];
+		base = of_read_number(&indexes[i], 2);
+		size = of_read_number(&indexes[i + WDW_SIZE_PROPERTY], 2);
+		res->name = pci_name(dev);
+		res->start = base;
+		res->end = base + size - 1;
+		root = pci_find_parent_resource(dev, res);
+
+		if (!root)
+			root = &iomem_resource;
+		dev_dbg(&dev->dev,
+			"pSeries IOV BAR %d: trying firmware assignment %pR\n",
+			 r + PCI_IOV_RESOURCES, res);
+		conflict = request_resource_conflict(root, res);
+		if (conflict) {
+			dev_info(&dev->dev,
+				 "BAR %d: %pR conflicts with %s %pR\n",
+				 r + PCI_IOV_RESOURCES, res,
+				 conflict->name, conflict);
+			res->flags |= IORESOURCE_UNSET;
+		}
+	}
+}
+
+static void pseries_pci_fixup_resources(struct pci_dev *pdev)
+{
+	const int *indexes;
+	struct device_node *dn = pci_device_to_OF_node(pdev);
+
+	/*Firmware must support open sriov otherwise dont configure*/
+	indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
+	if (!indexes)
+		return;
+	/* Assign the addresses from device tree*/
+	of_pci_set_vf_bar_size(pdev, indexes);
+}
+
+static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev)
+{
+	const int *indexes;
+	struct device_node *dn = pci_device_to_OF_node(pdev);
+
+	if (!pdev->is_physfn || pdev->is_added)
+		return;
+	/*Firmware must support open sriov otherwise dont configure*/
+	indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
+	if (!indexes)
+		return;
+	/* Assign the addresses from device tree*/
+	of_pci_parse_iov_addrs(pdev, indexes);
+}
+
+static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev,
+							  int resno)
+{
+	const __be32 *reg;
+	struct device_node *dn = pci_device_to_OF_node(pdev);
+
+	/*Firmware must support open sriov otherwise report regular alignment*/
+	reg = of_get_property(dn, "ibm,is-open-sriov-pf", NULL);
+	if (!reg)
+		return pci_iov_resource_size(pdev, resno);
+
+	if (!pdev->is_physfn)
+		return 0;
+	return pseries_get_iov_fw_value(pdev,
+					resno - PCI_IOV_RESOURCES,
+					APERTURE_SIZE);
+}
+#endif
+
 static void __init pSeries_setup_arch(void)
 {
 	set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
@@ -490,6 +649,14 @@ static void __init pSeries_setup_arch(void)
 		vpa_init(boot_cpuid);
 		ppc_md.power_save = pseries_lpar_idle;
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
+#ifdef CONFIG_PCI_IOV
+		ppc_md.pcibios_fixup_resources =
+			pseries_pci_fixup_resources;
+		ppc_md.pcibios_fixup_sriov =
+			pseries_pci_fixup_iov_resources;
+		ppc_md.pcibios_iov_resource_alignment =
+			pseries_pci_iov_resource_alignment;
+#endif
 	} else {
 		/* No special idle routine */
 		ppc_md.enable_pmcs = power4_enable_pmcs;
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 6/7] pseries/pci: Associate PEs to VFs in configure SR-IOV
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

After initial validation of SR-IOV resources, firmware will
associate PEs to the dynamic VFs created within this call. This
patch adds the association of PEs to the PF array of PE numbers
indexed by VF.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/pci.c | 151 ++++++++++++++++++++++++++++++++++-
 1 file changed, 148 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 48d3af026f90..00e6475004ff 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -57,18 +57,163 @@ void pcibios_name_device(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
 #endif
-
 #ifdef CONFIG_PCI_IOV
+#define MAX_VFS_FOR_MAP_PE 256
+struct pe_map_bar_entry {
+	__be64     bar;       /* Input:  Virtual Function BAR */
+	__be16     rid;       /* Input:  Virtual Function Router ID */
+	__be16     pe_num;    /* Output: Virtual Function PE Number */
+	__be32     reserved;  /* Reserved Space */
+};
+
+int pseries_send_map_pe(struct pci_dev *pdev,
+			u16 num_vfs,
+			struct pe_map_bar_entry *vf_pe_array)
+{
+	struct pci_dn *pdn;
+	int rc;
+	unsigned long buid, addr;
+	int ibm_map_pes = rtas_token("ibm,open-sriov-map-pe-number");
+
+	if (ibm_map_pes == RTAS_UNKNOWN_SERVICE)
+		return -EINVAL;
+
+	pdn = pci_get_pdn(pdev);
+	addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+	buid = pdn->phb->buid;
+	spin_lock(&rtas_data_buf_lock);
+	memcpy(rtas_data_buf, vf_pe_array,
+	       RTAS_DATA_BUF_SIZE);
+	rc = rtas_call(ibm_map_pes, 5, 1, NULL, addr,
+		       BUID_HI(buid), BUID_LO(buid),
+		       rtas_data_buf,
+		       num_vfs * sizeof(struct pe_map_bar_entry));
+	memcpy(vf_pe_array, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+	spin_unlock(&rtas_data_buf_lock);
+
+	if (rc)
+		dev_err(&pdev->dev,
+			"%s: Failed to associate pes PE#%lx, rc=%x\n",
+			__func__,  addr, rc);
+
+	return rc;
+}
+
+void pseries_set_pe_num(struct pci_dev *pdev, u16 vf_index, __be16 pe_num)
+{
+	struct pci_dn *pdn;
+
+	pdn = pci_get_pdn(pdev);
+	pdn->pe_num_map[vf_index] = be16_to_cpu(pe_num);
+	dev_dbg(&pdev->dev, "VF %04x:%02x:%02x.%x associated with PE#%x\n",
+		pci_domain_nr(pdev->bus),
+		pdev->bus->number,
+		PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)),
+		PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)),
+		pdn->pe_num_map[vf_index]);
+}
+
+int pseries_associate_pes(struct pci_dev *pdev, u16 num_vfs)
+{
+	struct pci_dn *pdn;
+	int i, rc, vf_index;
+	struct pe_map_bar_entry *vf_pe_array;
+	struct resource *res;
+	u64 size;
+
+	vf_pe_array = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+	if (!vf_pe_array)
+		return -ENOMEM;
+
+	pdn = pci_get_pdn(pdev);
+	/* create firmware structure to associate pes */
+	for (vf_index = 0; vf_index < num_vfs; vf_index++) {
+		pdn->pe_num_map[vf_index] = IODA_INVALID_PE;
+		for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+			res = &pdev->resource[i + PCI_IOV_RESOURCES];
+			if (!res->parent)
+				continue;
+			size = pcibios_iov_resource_alignment(pdev, i +
+					PCI_IOV_RESOURCES);
+			vf_pe_array[vf_index].bar =
+				cpu_to_be64(res->start + size * vf_index);
+			vf_pe_array[vf_index].rid =
+				cpu_to_be16((pci_iov_virtfn_bus(pdev, vf_index)
+					    << 8) | pci_iov_virtfn_devfn(pdev,
+					    vf_index));
+			vf_pe_array[vf_index].pe_num =
+				cpu_to_be16(IODA_INVALID_PE);
+		}
+	}
+
+	rc = pseries_send_map_pe(pdev, num_vfs, vf_pe_array);
+	/* Only zero is success */
+	if (!rc)
+		for (vf_index = 0; vf_index < num_vfs; vf_index++)
+			pseries_set_pe_num(pdev, vf_index,
+					   vf_pe_array[vf_index].pe_num);
+
+	kfree(vf_pe_array);
+	return rc;
+}
+
+int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
+{
+	struct pci_dn         *pdn;
+	int                    rc;
+	const int *max_vfs;
+	int max_config_vfs;
+	struct device_node *dn = pci_device_to_OF_node(pdev);
+
+	max_vfs = of_get_property(dn, "ibm,number-of-configurable-vfs", NULL);
+
+	if (!max_vfs)
+		return -EINVAL;
+
+	/* First integer stores max config */
+	max_config_vfs = of_read_number(&max_vfs[0], 1);
+	if (max_config_vfs < num_vfs && num_vfs > MAX_VFS_FOR_MAP_PE) {
+		dev_err(&pdev->dev,
+			"Num VFs %x > %x Configurable VFs\n",
+			num_vfs, (num_vfs > MAX_VFS_FOR_MAP_PE) ?
+			MAX_VFS_FOR_MAP_PE : max_config_vfs);
+		return -EINVAL;
+	}
+
+	pdn = pci_get_pdn(pdev);
+	pdn->pe_num_map = kmalloc_array(num_vfs,
+					sizeof(*pdn->pe_num_map),
+					GFP_KERNEL);
+	if (!pdn->pe_num_map)
+		return -ENOMEM;
+
+	rc = pseries_associate_pes(pdev, num_vfs);
+
+	/* Anything other than zero is failure */
+	if (rc) {
+		dev_err(&pdev->dev, "Failure to enable sriov: %x\n", rc);
+		kfree(pdn->pe_num_map);
+	} else {
+		pci_vf_drivers_autoprobe(pdev, false);
+	}
+
+	return rc;
+}
+
 int pseries_pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
 {
 	/* Allocate PCI data */
 	add_dev_pci_data(pdev);
-	pci_vf_drivers_autoprobe(pdev, false);
-	return 0;
+	return pseries_pci_sriov_enable(pdev, num_vfs);
 }
 
 int pseries_pcibios_sriov_disable(struct pci_dev *pdev)
 {
+	struct pci_dn         *pdn;
+
+	pdn = pci_get_pdn(pdev);
+	/* Releasing pe_num_map */
+	kfree(pdn->pe_num_map);
 	/* Release PCI data */
 	remove_dev_pci_data(pdev);
 	pci_vf_drivers_autoprobe(pdev, true);
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 1/7] platform/pseries: Update VF config space after EEH
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

Add EEH platform operations for pseries to update VF
config space. With this change after EEH, the VF
will have updated config space for pseries platform.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h               |  1 +
 arch/powerpc/kernel/eeh.c                    | 59 +++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/eeh-powernv.c | 65 ++--------------------------
 arch/powerpc/platforms/pseries/eeh_pseries.c | 26 ++++++++++-
 4 files changed, 88 insertions(+), 63 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 5161c37dd039..82829c65f31a 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -297,6 +297,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option);
 int eeh_pe_configure(struct eeh_pe *pe);
 int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func,
 		      unsigned long addr, unsigned long mask);
+int eeh_restore_vf_config(struct pci_dn *pdn);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index cbca0a667682..cc649809885e 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -740,6 +740,65 @@ static void *eeh_restore_dev_state(void *data, void *userdata)
 	return NULL;
 }
 
+int eeh_restore_vf_config(struct pci_dn *pdn)
+{
+	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+	u32 devctl, cmd, cap2, aer_capctl;
+	int old_mps;
+
+	if (edev->pcie_cap) {
+		/* Restore MPS */
+		old_mps = (ffs(pdn->mps) - 8) << 5;
+		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+				     2, &devctl);
+		devctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+		devctl |= old_mps;
+		eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+				      2, devctl);
+
+		/* Disable Completion Timeout */
+		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP2,
+				     4, &cap2);
+		if (cap2 & 0x10) {
+			eeh_ops->read_config(pdn,
+					     edev->pcie_cap + PCI_EXP_DEVCTL2,
+					     4, &cap2);
+			cap2 |= 0x10;
+			eeh_ops->write_config(pdn,
+					      edev->pcie_cap + PCI_EXP_DEVCTL2,
+					      4, cap2);
+		}
+	}
+
+	/* Enable SERR and parity checking */
+	eeh_ops->read_config(pdn, PCI_COMMAND, 2, &cmd);
+	cmd |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	eeh_ops->write_config(pdn, PCI_COMMAND, 2, cmd);
+
+	/* Enable report various errors */
+	if (edev->pcie_cap) {
+		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+				     2, &devctl);
+		devctl &= ~PCI_EXP_DEVCTL_CERE;
+		devctl |= (PCI_EXP_DEVCTL_NFERE |
+			   PCI_EXP_DEVCTL_FERE |
+			   PCI_EXP_DEVCTL_URRE);
+		eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+				      2, devctl);
+	}
+
+	/* Enable ECRC generation and check */
+	if (edev->pcie_cap && edev->aer_cap) {
+		eeh_ops->read_config(pdn, edev->aer_cap + PCI_ERR_CAP,
+				     4, &aer_capctl);
+		aer_capctl |= (PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+		eeh_ops->write_config(pdn, edev->aer_cap + PCI_ERR_CAP,
+				      4, aer_capctl);
+	}
+
+	return 0;
+}
+
 /**
  * pcibios_set_pcie_reset_state - Set PCI-E reset state
  * @dev: pci device struct
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 961e64115d92..0665b6d03cb3 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -1655,70 +1655,11 @@ static int pnv_eeh_next_error(struct eeh_pe **pe)
 	return ret;
 }
 
-static int pnv_eeh_restore_vf_config(struct pci_dn *pdn)
-{
-	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
-	u32 devctl, cmd, cap2, aer_capctl;
-	int old_mps;
-
-	if (edev->pcie_cap) {
-		/* Restore MPS */
-		old_mps = (ffs(pdn->mps) - 8) << 5;
-		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
-				     2, &devctl);
-		devctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
-		devctl |= old_mps;
-		eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
-				      2, devctl);
-
-		/* Disable Completion Timeout */
-		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP2,
-				     4, &cap2);
-		if (cap2 & 0x10) {
-			eeh_ops->read_config(pdn,
-					     edev->pcie_cap + PCI_EXP_DEVCTL2,
-					     4, &cap2);
-			cap2 |= 0x10;
-			eeh_ops->write_config(pdn,
-					      edev->pcie_cap + PCI_EXP_DEVCTL2,
-					      4, cap2);
-		}
-	}
-
-	/* Enable SERR and parity checking */
-	eeh_ops->read_config(pdn, PCI_COMMAND, 2, &cmd);
-	cmd |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-	eeh_ops->write_config(pdn, PCI_COMMAND, 2, cmd);
-
-	/* Enable report various errors */
-	if (edev->pcie_cap) {
-		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
-				     2, &devctl);
-		devctl &= ~PCI_EXP_DEVCTL_CERE;
-		devctl |= (PCI_EXP_DEVCTL_NFERE |
-			   PCI_EXP_DEVCTL_FERE |
-			   PCI_EXP_DEVCTL_URRE);
-		eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
-				      2, devctl);
-	}
-
-	/* Enable ECRC generation and check */
-	if (edev->pcie_cap && edev->aer_cap) {
-		eeh_ops->read_config(pdn, edev->aer_cap + PCI_ERR_CAP,
-				     4, &aer_capctl);
-		aer_capctl |= (PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
-		eeh_ops->write_config(pdn, edev->aer_cap + PCI_ERR_CAP,
-				      4, aer_capctl);
-	}
-
-	return 0;
-}
-
 static int pnv_eeh_restore_config(struct pci_dn *pdn)
 {
 	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
 	struct pnv_phb *phb;
-	s64 ret;
+	s64 ret = 0;
 	int config_addr = (pdn->busno << 8) | (pdn->devfn);
 
 	if (!edev)
@@ -1732,7 +1673,7 @@ static int pnv_eeh_restore_config(struct pci_dn *pdn)
 	 * to be exported by firmware in extendible way.
 	 */
 	if (edev->physfn) {
-		ret = pnv_eeh_restore_vf_config(pdn);
+		ret = eeh_restore_vf_config(pdn);
 	} else {
 		phb = pdn->phb->private_data;
 		ret = opal_pci_reinit(phb->opal_id,
@@ -1745,7 +1686,7 @@ static int pnv_eeh_restore_config(struct pci_dn *pdn)
 		return -EIO;
 	}
 
-	return 0;
+	return ret;
 }
 
 static struct eeh_ops pnv_eeh_ops = {
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 2295f117e2d3..a671ef4f57f5 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -708,6 +708,30 @@ static int pseries_eeh_write_config(struct pci_dn *pdn, int where, int size, u32
 	return rtas_write_config(pdn, where, size, val);
 }
 
+static int pseries_eeh_restore_config(struct pci_dn *pdn)
+{
+	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+	s64 ret = 0;
+
+	if (!edev)
+		return -EEXIST;
+
+	/*
+	 * FIXME: The MPS, error routing rules, timeout setting are worthy
+	 * to be exported by firmware in extendible way.
+	 */
+	if (edev->physfn)
+		ret = eeh_restore_vf_config(pdn);
+
+	if (ret) {
+		pr_warn("%s: Can't reinit PCI dev 0x%x (%lld)\n",
+			__func__, edev->pe_config_addr, ret);
+		return -EIO;
+	}
+
+	return ret;
+}
+
 static struct eeh_ops pseries_eeh_ops = {
 	.name			= "pseries",
 	.init			= pseries_eeh_init,
@@ -723,7 +747,7 @@ static struct eeh_ops pseries_eeh_ops = {
 	.read_config		= pseries_eeh_read_config,
 	.write_config		= pseries_eeh_write_config,
 	.next_error		= NULL,
-	.restore_config		= NULL
+	.restore_config		= pseries_eeh_restore_config
 };
 
 /**
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 5/7] powerpc/kernel: Add EEH notify resume sysfs
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

Introduce a method for notify resume to be
called from sysfs. In this patch one can
now call notify resume from sysfs when
is supported by platform.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh_sysfs.c | 46 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/eeh_sysfs.c b/arch/powerpc/kernel/eeh_sysfs.c
index 797549289798..344e7607f2e0 100644
--- a/arch/powerpc/kernel/eeh_sysfs.c
+++ b/arch/powerpc/kernel/eeh_sysfs.c
@@ -90,6 +90,38 @@ static ssize_t eeh_pe_state_store(struct device *dev,
 
 static DEVICE_ATTR_RW(eeh_pe_state);
 
+#ifdef CONFIG_PCI_IOV
+static ssize_t eeh_notify_resume_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
+	struct pci_dn *pdn = pci_get_pdn(pdev);
+
+	if (!edev || !edev->pe)
+		return -ENODEV;
+
+	pdn = pci_get_pdn(pdev);
+	return sprintf(buf, "%d\n", pdn->last_allow_rc);
+}
+
+static ssize_t eeh_notify_resume_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
+
+	if (!edev || !edev->pe)
+		return -ENODEV;
+
+	if (eeh_ops->notify_resume(pci_get_pdn(pdev)))
+		return -EIO;
+	return count;
+}
+static DEVICE_ATTR_RW(eeh_notify_resume);
+#endif
+
 void eeh_sysfs_add_device(struct pci_dev *pdev)
 {
 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
@@ -104,7 +136,13 @@ void eeh_sysfs_add_device(struct pci_dev *pdev)
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_state);
-
+#ifdef CONFIG_PCI_IOV
+	if (of_get_property(pci_device_to_OF_node
+			    ((pdev->is_physfn ? pdev : pdev->physfn)),
+			    "ibm,is-open-sriov-pf", NULL))
+		rc += device_create_file(&pdev->dev,
+					 &dev_attr_eeh_notify_resume);
+#endif
 	if (rc)
 		pr_warn("EEH: Unable to create sysfs entries\n");
 	else if (edev)
@@ -128,6 +166,12 @@ void eeh_sysfs_remove_device(struct pci_dev *pdev)
 	device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
 	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
 	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_state);
+#ifdef CONFIG_PCI_IOV
+	if (of_get_property(pci_device_to_OF_node
+			    ((pdev->is_physfn ? pdev : pdev->physfn)),
+			    "ibm,is-open-sriov-pf", NULL))
+		device_remove_file(&pdev->dev, &dev_attr_eeh_notify_resume);
+#endif
 
 	if (edev)
 		edev->mode &= ~EEH_DEV_SYSFS;
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 2/7] powerpc/kernel: Add uevents in EEH error/resume
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

Devices can go offline when EEH is reported. This patch adds
a change to the kernel object and lets udev know of error.
When device resumes a change is also set reporting device as
online. Therefore, EEH events are better propagated to user
space for devices in powerpc arch.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh_driver.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 3c0fa99c5533..9d4e8177c2e0 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -204,6 +204,7 @@ static void *eeh_report_error(void *data, void *userdata)
 	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver;
+	char *envp[] = {"EVENT=EEH_ERROR", "ONLINE=0", NULL};
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
@@ -228,6 +229,7 @@ static void *eeh_report_error(void *data, void *userdata)
 
 	edev->in_error = true;
 	eeh_pcid_put(dev);
+	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
 	return NULL;
 }
 
@@ -358,6 +360,7 @@ static void *eeh_report_resume(void *data, void *userdata)
 	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	bool was_in_error;
 	struct pci_driver *driver;
+	char *envp[] = {"EVENT=EEH_RESUME", "ONLINE=1", NULL};
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
@@ -381,6 +384,7 @@ static void *eeh_report_resume(void *data, void *userdata)
 	driver->err_handler->resume(dev);
 
 	eeh_pcid_put(dev);
+	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
 	return NULL;
 }
 
@@ -397,6 +401,7 @@ static void *eeh_report_failure(void *data, void *userdata)
 	struct eeh_dev *edev = (struct eeh_dev *)data;
 	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	struct pci_driver *driver;
+	char * envp[] = {"EVENT=EEH_PERMANENT_FAILURE", "ONLINE=0", NULL};
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
@@ -415,6 +420,7 @@ static void *eeh_report_failure(void *data, void *userdata)
 
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 
+	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
 	eeh_pcid_put(dev);
 	return NULL;
 }
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 4/7] powerpc/kernel Add EEH operations to notify resume
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

When pseries SR-IOV is enabled and after a PF driver
has resumed from EEH, platform has to be notified
of the event so the child VFs can be allowed to
resume their normal recovery path.

This patch makes the EEH operation allow unfreeze
platform dependent code and adds the call to
pseries EEH code.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h               |  1 +
 arch/powerpc/kernel/eeh_driver.c             |  3 +
 arch/powerpc/platforms/powernv/eeh-powernv.c |  3 +-
 arch/powerpc/platforms/pseries/eeh_pseries.c | 90 +++++++++++++++++++++++++++-
 4 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 82829c65f31a..fd37cc101f4f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -214,6 +214,7 @@ struct eeh_ops {
 	int (*write_config)(struct pci_dn *pdn, int where, int size, u32 val);
 	int (*next_error)(struct eeh_pe **pe);
 	int (*restore_config)(struct pci_dn *pdn);
+	int (*notify_resume)(struct pci_dn *pdn);
 };
 
 extern int eeh_subsystem_flags;
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 9d4e8177c2e0..ed710076b042 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -385,6 +385,9 @@ static void *eeh_report_resume(void *data, void *userdata)
 
 	eeh_pcid_put(dev);
 	kobject_uevent_env(&dev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_PCI_IOV
+	eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
+#endif
 	return NULL;
 }
 
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 0665b6d03cb3..33c86c1a1720 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -1704,7 +1704,8 @@ static struct eeh_ops pnv_eeh_ops = {
 	.read_config            = pnv_eeh_read_config,
 	.write_config           = pnv_eeh_write_config,
 	.next_error		= pnv_eeh_next_error,
-	.restore_config		= pnv_eeh_restore_config
+	.restore_config		= pnv_eeh_restore_config,
+	.notify_resume		= NULL
 };
 
 #ifdef CONFIG_PCI_IOV
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index c4bc5dd0c6ec..1bae44f30b73 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -743,6 +743,93 @@ static int pseries_eeh_restore_config(struct pci_dn *pdn)
 	return ret;
 }
 
+#ifdef CONFIG_PCI_IOV
+int pseries_send_allow_unfreeze(struct pci_dn *pdn,
+				u16 *vf_pe_array, int cur_vfs)
+{
+	int rc;
+	int ibm_allow_unfreeze = rtas_token("ibm,open-sriov-allow-unfreeze");
+	unsigned long buid, addr;
+
+	addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+	buid = pdn->phb->buid;
+	spin_lock(&rtas_data_buf_lock);
+	memcpy(rtas_data_buf, vf_pe_array, RTAS_DATA_BUF_SIZE);
+	rc = rtas_call(ibm_allow_unfreeze, 5, 1, NULL,
+		       addr,
+		       BUID_HI(buid),
+		       BUID_LO(buid),
+		       rtas_data_buf, cur_vfs * sizeof(u16));
+	spin_unlock(&rtas_data_buf_lock);
+	if (rc)
+		pr_warn("%s: Failed to allow unfreeze for PHB#%x-PE#%lx, rc=%x\n",
+			__func__,
+			pdn->phb->global_number, addr, rc);
+	return rc;
+}
+
+static int pseries_call_allow_unfreeze(struct eeh_dev *edev)
+{
+	struct pci_dn *pdn, *tmp, *parent, *physfn_pdn;
+	int cur_vfs = 0, rc = 0, vf_index, bus, devfn;
+	u16 *vf_pe_array;
+
+	vf_pe_array = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+	if (!vf_pe_array)
+		return -ENOMEM;
+
+	if (edev->pdev->is_physfn) {
+		cur_vfs = pci_num_vf(edev->pdev);
+		pdn = eeh_dev_to_pdn(edev);
+		parent = pdn->parent;
+
+		for (vf_index = 0; vf_index < cur_vfs; vf_index++)
+			vf_pe_array[vf_index] =
+				cpu_to_be16(pdn->pe_num_map[vf_index]);
+		rc = pseries_send_allow_unfreeze(pdn, vf_pe_array, cur_vfs);
+		pdn->last_allow_rc = rc;
+		for (vf_index = 0; vf_index < cur_vfs; vf_index++) {
+			list_for_each_entry_safe(pdn, tmp, &parent->child_list,
+						 list) {
+				bus = pci_iov_virtfn_bus(edev->pdev, vf_index);
+				devfn = pci_iov_virtfn_devfn(edev->pdev,
+							     vf_index);
+				if (pdn->busno != bus ||
+				    pdn->devfn != devfn)
+					continue;
+				pdn->last_allow_rc = rc;
+			}
+		}
+	} else {
+		pdn = pci_get_pdn(edev->pdev);
+		vf_pe_array[0] = cpu_to_be16(pdn->pe_number);
+		physfn_pdn = pci_get_pdn(edev->physfn);
+		rc = pseries_send_allow_unfreeze(physfn_pdn, vf_pe_array, 1);
+		pdn->last_allow_rc = rc;
+	}
+
+	kfree(vf_pe_array);
+	return rc;
+}
+
+static int pseries_notify_resume(struct pci_dn *pdn)
+{
+	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+
+	if (!edev)
+		return -EEXIST;
+
+	if (rtas_token("ibm,open-sriov-allow-unfreeze")
+	    == RTAS_UNKNOWN_SERVICE)
+		return -EINVAL;
+
+	if (edev->pdev->is_physfn || edev->pdev->is_virtfn)
+		return pseries_call_allow_unfreeze(edev);
+
+	return 0;
+}
+#endif
+
 static struct eeh_ops pseries_eeh_ops = {
 	.name			= "pseries",
 	.init			= pseries_eeh_init,
@@ -758,7 +845,8 @@ static struct eeh_ops pseries_eeh_ops = {
 	.read_config		= pseries_eeh_read_config,
 	.write_config		= pseries_eeh_write_config,
 	.next_error		= NULL,
-	.restore_config		= pseries_eeh_restore_config
+	.restore_config		= pseries_eeh_restore_config,
+	.notify_resume		= pseries_notify_resume
 };
 
 /**
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v2 3/7] platforms/pseries: Set eeh_pe of EEH_PE_VF type
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly
In-Reply-To: <20171218223808.83928-1-bryantly@linux.vnet.ibm.com>

To correctly use EEH code one has to make
sure that the EEH_PE_VF is set for dynamic created
VFs. Therefore this patch allocates an eeh_pe of
eeh type EEH_PE_VF and associates PE with parent.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/pci-bridge.h        |  5 ++++-
 arch/powerpc/platforms/pseries/eeh_pseries.c | 13 ++++++++++++-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 9f66ddebb799..16d70740a76f 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -211,7 +211,10 @@ struct pci_dn {
 	unsigned int *pe_num_map;	/* PE# for the first VF PE or array */
 	bool    m64_single_mode;	/* Use M64 BAR in Single Mode */
 #define IODA_INVALID_M64        (-1)
-	int     (*m64_map)[PCI_SRIOV_NUM_BARS];
+	union {
+		int     (*m64_map)[PCI_SRIOV_NUM_BARS]; /*Only used in powernv */
+		int     last_allow_rc;	/* Only used in pSeries */
+	};
 #endif /* CONFIG_PCI_IOV */
 	int	mps;			/* Maximum Payload Size */
 	struct list_head child_list;
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index a671ef4f57f5..c4bc5dd0c6ec 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -58,6 +58,8 @@ static int ibm_configure_pe;
 void pseries_pcibios_bus_add_device(struct pci_dev *pdev)
 {
 	struct pci_dn *pdn = pci_get_pdn(pdev);
+	struct pci_dn *physfn_pdn;
+	struct eeh_dev *edev;
 
 	if (!pdev->is_virtfn)
 		return;
@@ -65,6 +67,14 @@ void pseries_pcibios_bus_add_device(struct pci_dev *pdev)
 	pdn->device_id  =  pdev->device;
 	pdn->vendor_id  =  pdev->vendor;
 	pdn->class_code =  pdev->class;
+	/* Last allow unfreeze return code used for retrieval
+	 * by user space in eeh-sysfs to show the last command
+	 * completion from platform
+	 */
+	pdn->last_allow_rc =  0;
+	physfn_pdn      =  pci_get_pdn(pdev->physfn);
+	pdn->pe_number  =  physfn_pdn->pe_num_map[pdn->vf_index];
+	edev = pdn_to_eeh_dev(pdn);
 
 	/*
 	 * The following operations will fail if VF's sysfs files
@@ -72,8 +82,9 @@ void pseries_pcibios_bus_add_device(struct pci_dev *pdev)
 	 */
 	eeh_add_device_early(pdn);
 	eeh_add_device_late(pdev);
+	edev->pe_config_addr =  (pdn->busno << 16) | (pdn->devfn << 8);
+	eeh_add_to_parent_pe(edev);
 	eeh_sysfs_add_device(pdev);
-
 }
 
 /*
-- 
2.14.3 (Apple Git-98)

^ permalink raw reply related

* [PATCH v1 0/7] SR-IOV Enablement on PowerVM
From: Bryant G. Ly @ 2017-12-18 22:38 UTC (permalink / raw)
  To: benh, paulus, mpe
  Cc: seroyer, jjalvare, alex.williamson, helgaas, aik, ruscur,
	linux-pci, linuxppc-dev, bodong, eli, saeedm, Bryant G. Ly

This patch series will enable SR-IOV on PowerVM. A specific set of
lids for PFW/PHYP is required. They are planned to release with
920 at the moment.

For IBM internal testers let me know of a system you want to test on
and we can put on the lids required or we can provide a system to run
the tests.

This patch depends on the three patches:
988fc3ba5653278a8c14d6ccf687371775930d2b
dae7253f9f78a731755ca20c66b2d2c40b86baea
608c0d8804ef3ca4cda8ec6ad914e47deb283d7b

v1 - Initial Patch
v2 - Addressed Alexey and Russell's comments

Bryant G. Ly (7):
  platform/pseries: Update VF config space after EEH
  powerpc/kernel: Add uevents in EEH error/resume
  platforms/pseries: Set eeh_pe of EEH_PE_VF type
  powerpc/kernel Add EEH operations to notify resume
  powerpc/kernel: Add EEH notify resume sysfs
  pseries/pci: Associate PEs to VFs in configure SR-IOV
  pseries/setup: Add Initialization of VF Bars

 arch/powerpc/include/asm/eeh.h               |   1 +
 arch/powerpc/include/asm/pci-bridge.h        |   5 +-
 arch/powerpc/include/asm/pci.h               |   2 +
 arch/powerpc/kernel/eeh_driver.c             |   9 +-
 arch/powerpc/kernel/eeh_sysfs.c              |  46 ++++++-
 arch/powerpc/kernel/pci_of_scan.c            |   2 +-
 arch/powerpc/platforms/powernv/eeh-powernv.c |   3 +-
 arch/powerpc/platforms/pseries/eeh_pseries.c | 192 ++++++++++++++++++++++++++-
 arch/powerpc/platforms/pseries/pci.c         | 156 +++++++++++++++++++++-
 arch/powerpc/platforms/pseries/setup.c       | 183 +++++++++++++++++++++++++
 10 files changed, 589 insertions(+), 10 deletions(-)

-- 
2.14.3 (Apple Git-98)

^ permalink raw reply

* Re: [PATCH v9 29/51] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
From: Dave Hansen @ 2017-12-18 22:28 UTC (permalink / raw)
  To: Ram Pai
  Cc: mpe, mingo, akpm, corbet, arnd, linuxppc-dev, linux-mm, x86,
	linux-arch, linux-doc, linux-kselftest, linux-kernel, benh,
	paulus, khandual, aneesh.kumar, bsingharora, hbabu, mhocko,
	bauerman, ebiederm
In-Reply-To: <20171218221850.GD5461@ram.oc3035372033.ibm.com>

On 12/18/2017 02:18 PM, Ram Pai wrote:
> b) minimum number of keys available to the application.
> 	if libraries consumes a few, they could provide a library
> 	interface to the application informing the number available to
> 	the application.  The library interface can leverage (b) to
> 	provide the information.

OK, let's see a real user of this including a few libraries.  Then we'll
put it in the kernel.

> c) types of disable-rights supported by keys.
> 	Helps the application to determine the types of disable-features
> 	available. This is helpful, otherwise the app has to 
> 	make pkey_alloc() call with the corresponding parameter set
> 	and see if it suceeds or fails. Painful from an application
> 	point of view, in my opinion.

Again, let's see a real-world use of this.  How does it look?  How does
an app "fall back" if it can't set a restriction the way it wants to?

Are we *sure* that such an interface makes sense?  For instance, will it
be possible for some keys to be execute-disable while other are only
write-disable?

> I think on x86 you look for some hardware registers to determine which
> hardware features are enabled by the kernel.

No, we use CPUID.  It's a part of the ISA that's designed for
enumerating CPU and (sometimes) OS support for CPU features.

> We do not have generic support for something like that on ppc.
> The kernel looks at the device tree to determine what hardware features
> are available. But does not have mechanism to tell the hardware to track
> which of its features are currently enabled/used by the kernel; atleast
> not for the memory-key feature.

Bummer.  You're missing out.

But, you could still do this with a syscall.  "Hey, kernel, do you
support this feature?"

^ permalink raw reply

* Re: [PATCH v4 00/11] ASoC: fsl_ssi: Clean up - coding style level
From: Caleb Crome @ 2017-12-18 22:19 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Nicolin Chen, Mark Brown, linux-kernel, linuxppc-dev, alsa-devel,
	Liam Girdwood, Fabio Estevam, mail, Arnaud Mouiche, lukma,
	Sascha Hauer
In-Reply-To: <4e69ef31-3aa6-66ea-331b-8a7472a66a15@tabi.org>

On Sun, Dec 17, 2017 at 7:13 PM, Timur Tabi <timur@tabi.org> wrote:
>
> On 12/17/17 8:51 PM, Nicolin Chen wrote:
>>
>> Nicolin Chen (11):
>>    ASoC: fsl_ssi: Rename fsl_ssi_private to fsl_ssi
>>    ASoC: fsl_ssi: Cache pdev->dev pointer
>>    ASoC: fsl_ssi: Refine all comments
>>    ASoC: fsl_ssi: Rename registers and fields macros
>>    ASoC: fsl_ssi: Refine indentations and wrappings
>>    ASoC: fsl_ssi: Refine printk outputs
>>    ASoC: fsl_ssi: Rename cpu_dai parameter to dai
>>    ASoC: fsl_ssi: Rename scr_val to scr
>>    ASoC: fsl_ssi: Replace fsl_ssi_rxtx_reg_val with fsl_ssi_regvals
>>    ASoC: fsl_ssi: Rename i2smode to i2s_net
>>    ASoC: fsl_ssi: Define ternary macros to simplify code
>
>
> Acked-by: Timur Tabi <timur@tabi.org>


I'm re-setting up my loopback test to try to verify these most recent changes.

I'm starting with the for-next branch at
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git (which
is a 4.15 numbered kernel).

The basic setup is using a wandboard with a TX pin tied directly to an
RX pin do test if what is sent is what is received, using Arnaud's
tester here: https://github.com/amouiche/atest

Unfortunately, it doesn't pass the loopback test, even before these
patches.  I'm not actively developing on this platform at the moment,
and my brain has been out of kernel development for quite a while.

I'm getting channel slips again.

output from atest:

warn:   11a0 11a1 1160 11a3 11a4 11a5 11a6 11a7
warn: Valid frame after 1 invalid frames
warn:   11c0 11c1 11c2 11c3 11c4 11c5 11c6 11c7
warn: first invalid frame while expecting frame 0x00a0
warn:   13e7 1400 1401 1402 1403 1404 1405 1404
warn:   1407 1420 1421 1422 1423 1424 1425 1426
warn:   1427 1440 1441 1442 1443 1444 1445 1484
warn:   1447 1460 1461 1462 1463 1464 1465 1466

Those last 4 lines are the channel slips -- the least significant
nibble should be the channel number:  i.e. should go 0, 1, 2, 3, 4, 5,
6, 7.

Ugh, so it's basically quite broken again -- before these patches.
I guess I need to go backwards in time and see what rev re-broke it.
I don't really have time to dig too deep on this again.

I'd be happy to provide the hardware to anybody that can diagnose and
debug this more quickly than I can.  I'm very inefficient at kernel
drivers I think.   My day job is acoustical and electrical
engineering.

Here's what the hardware looks like for anybody that's interested.
Just a single wire loopback on the wandboard header.

https://ibb.co/d2rfzm

-Caleb

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox