diff mbox series

[v8,2/7] PCI: Introduce shpchp_is_native()

Message ID 20180528124756.78512-3-mika.westerberg@linux.intel.com
State Accepted
Delegated to: Bjorn Helgaas
Headers show
Series PCI: Fixes and cleanups for native PCIe, SHPC and ACPI hotplug | expand

Commit Message

Mika Westerberg May 28, 2018, 12:47 p.m. UTC
In the same way we do for pciehp, introduce a new function
shpchp_is_native() that returns true whether the bridge should be
handled by the native SHCP driver. Then convert the driver to use this
function.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpi_pcihp.c  |  4 ++--
 drivers/pci/hotplug/shpchp_core.c |  2 --
 drivers/pci/pci-acpi.c            | 21 +++++++++++++++++++++
 include/linux/pci_hotplug.h       |  2 ++
 4 files changed, 25 insertions(+), 4 deletions(-)

Comments

Rafael J. Wysocki May 29, 2018, 9:06 a.m. UTC | #1
On Monday, May 28, 2018 2:47:51 PM CEST Mika Westerberg wrote:
> In the same way we do for pciehp, introduce a new function
> shpchp_is_native() that returns true whether the bridge should be
> handled by the native SHCP driver. Then convert the driver to use this
> function.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/pci/hotplug/acpi_pcihp.c  |  4 ++--
>  drivers/pci/hotplug/shpchp_core.c |  2 --
>  drivers/pci/pci-acpi.c            | 21 +++++++++++++++++++++
>  include/linux/pci_hotplug.h       |  2 ++
>  4 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
> index 597d22aeefc1..3979f89b250a 100644
> --- a/drivers/pci/hotplug/acpi_pcihp.c
> +++ b/drivers/pci/hotplug/acpi_pcihp.c
> @@ -83,11 +83,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
>  	 * OSHP within the scope of the hotplug controller and its parents,
>  	 * up to the host bridge under which this controller exists.
>  	 */
> -	host = pci_find_host_bridge(pdev->bus);
> -	if (host->native_shpc_hotplug)
> +	if (shpchp_is_native(pdev))
>  		return 0;
>  
>  	/* If _OSC exists, we should not evaluate OSHP */
> +	host = pci_find_host_bridge(pdev->bus);
>  	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
>  	if (root->osc_support_set)
>  		goto no_control;
> diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
> index 47decc9b3bb3..0f3711404c2b 100644
> --- a/drivers/pci/hotplug/shpchp_core.c
> +++ b/drivers/pci/hotplug/shpchp_core.c
> @@ -275,8 +275,6 @@ static int is_shpc_capable(struct pci_dev *dev)
>  	if (dev->vendor == PCI_VENDOR_ID_AMD &&
>  	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
>  		return 1;
> -	if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
> -		return 0;
>  	if (acpi_get_hp_hw_control_from_firmware(dev))
>  		return 0;
>  	return 1;
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 52b8434d4d6e..bb83be0d0e5b 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -394,6 +394,27 @@ bool pciehp_is_native(struct pci_dev *bridge)
>  	return host->native_pcie_hotplug;
>  }
>  
> +/**
> + * shpchp_is_native - Check whether a hotplug port is handled by the OS
> + * @bridge: Hotplug port to check
> + *
> + * Returns true if the given @bridge is handled by the native SHPC hotplug
> + * driver.
> + */
> +bool shpchp_is_native(struct pci_dev *bridge)
> +{
> +	const struct pci_host_bridge *host;
> +
> +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> +		return false;
> +
> +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> +		return false;
> +
> +	host = pci_find_host_bridge(bridge->bus);
> +	return host->native_shpc_hotplug;
> +}
> +
>  /**
>   * pci_acpi_wake_bus - Root bus wakeup notification fork function.
>   * @context: Device wakeup context.
> diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
> index 1f5c935eb0de..4c378368215c 100644
> --- a/include/linux/pci_hotplug.h
> +++ b/include/linux/pci_hotplug.h
> @@ -164,6 +164,7 @@ struct hotplug_params {
>  int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
>  bool pciehp_is_native(struct pci_dev *bridge);
>  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
> +bool shpchp_is_native(struct pci_dev *bridge);
>  int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
>  int acpi_pci_detect_ejectable(acpi_handle handle);
>  #else
> @@ -178,5 +179,6 @@ static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
>  	return 0;
>  }
>  static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; }
> +static inline bool shpchp_is_native(struct pci_dev *bridge) { return true; }
>  #endif
>  #endif
>
Andy Shevchenko May 29, 2018, 4:33 p.m. UTC | #2
On Mon, 2018-05-28 at 15:47 +0300, Mika Westerberg wrote:
> In the same way we do for pciehp, introduce a new function
> shpchp_is_native() that returns true whether the bridge should be
> handled by the native SHCP driver. Then convert the driver to use this
> function.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/pci/hotplug/acpi_pcihp.c  |  4 ++--
>  drivers/pci/hotplug/shpchp_core.c |  2 --
>  drivers/pci/pci-acpi.c            | 21 +++++++++++++++++++++
>  include/linux/pci_hotplug.h       |  2 ++
>  4 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/acpi_pcihp.c
> b/drivers/pci/hotplug/acpi_pcihp.c
> index 597d22aeefc1..3979f89b250a 100644
> --- a/drivers/pci/hotplug/acpi_pcihp.c
> +++ b/drivers/pci/hotplug/acpi_pcihp.c
> @@ -83,11 +83,11 @@ int acpi_get_hp_hw_control_from_firmware(struct
> pci_dev *pdev)
>  	 * OSHP within the scope of the hotplug controller and its
> parents,
>  	 * up to the host bridge under which this controller exists.
>  	 */
> -	host = pci_find_host_bridge(pdev->bus);
> -	if (host->native_shpc_hotplug)
> +	if (shpchp_is_native(pdev))
>  		return 0;
>  
>  	/* If _OSC exists, we should not evaluate OSHP */
> +	host = pci_find_host_bridge(pdev->bus);
>  	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
>  	if (root->osc_support_set)
>  		goto no_control;
> diff --git a/drivers/pci/hotplug/shpchp_core.c
> b/drivers/pci/hotplug/shpchp_core.c
> index 47decc9b3bb3..0f3711404c2b 100644
> --- a/drivers/pci/hotplug/shpchp_core.c
> +++ b/drivers/pci/hotplug/shpchp_core.c
> @@ -275,8 +275,6 @@ static int is_shpc_capable(struct pci_dev *dev)
>  	if (dev->vendor == PCI_VENDOR_ID_AMD &&
>  	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
>  		return 1;
> -	if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
> -		return 0;
>  	if (acpi_get_hp_hw_control_from_firmware(dev))
>  		return 0;
>  	return 1;
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 52b8434d4d6e..bb83be0d0e5b 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -394,6 +394,27 @@ bool pciehp_is_native(struct pci_dev *bridge)
>  	return host->native_pcie_hotplug;
>  }
>  
> +/**
> + * shpchp_is_native - Check whether a hotplug port is handled by the
> OS
> + * @bridge: Hotplug port to check
> + *
> + * Returns true if the given @bridge is handled by the native SHPC
> hotplug
> + * driver.
> + */
> +bool shpchp_is_native(struct pci_dev *bridge)
> +{
> +	const struct pci_host_bridge *host;
> +
> +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> +		return false;
> +
> +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> +		return false;
> +
> +	host = pci_find_host_bridge(bridge->bus);
> +	return host->native_shpc_hotplug;
> +}
> +
>  /**
>   * pci_acpi_wake_bus - Root bus wakeup notification fork function.
>   * @context: Device wakeup context.
> diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
> index 1f5c935eb0de..4c378368215c 100644
> --- a/include/linux/pci_hotplug.h
> +++ b/include/linux/pci_hotplug.h
> @@ -164,6 +164,7 @@ struct hotplug_params {
>  int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params
> *hpp);
>  bool pciehp_is_native(struct pci_dev *bridge);
>  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
> +bool shpchp_is_native(struct pci_dev *bridge);
>  int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle
> handle);
>  int acpi_pci_detect_ejectable(acpi_handle handle);
>  #else
> @@ -178,5 +179,6 @@ static inline int
> acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
>  	return 0;
>  }
>  static inline bool pciehp_is_native(struct pci_dev *bridge) { return
> true; }
> +static inline bool shpchp_is_native(struct pci_dev *bridge) { return
> true; }
>  #endif
>  #endif
Bjorn Helgaas May 30, 2018, 8:23 p.m. UTC | #3
[+cc David]

On Mon, May 28, 2018 at 03:47:51PM +0300, Mika Westerberg wrote:
> In the same way we do for pciehp, introduce a new function
> shpchp_is_native() that returns true whether the bridge should be
> handled by the native SHCP driver. Then convert the driver to use this
> function.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/pci/hotplug/acpi_pcihp.c  |  4 ++--
>  drivers/pci/hotplug/shpchp_core.c |  2 --
>  drivers/pci/pci-acpi.c            | 21 +++++++++++++++++++++
>  include/linux/pci_hotplug.h       |  2 ++
>  4 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
> index 597d22aeefc1..3979f89b250a 100644
> --- a/drivers/pci/hotplug/acpi_pcihp.c
> +++ b/drivers/pci/hotplug/acpi_pcihp.c
> @@ -83,11 +83,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
>  	 * OSHP within the scope of the hotplug controller and its parents,
>  	 * up to the host bridge under which this controller exists.
>  	 */
> -	host = pci_find_host_bridge(pdev->bus);
> -	if (host->native_shpc_hotplug)
> +	if (shpchp_is_native(pdev))
>  		return 0;
>  
>  	/* If _OSC exists, we should not evaluate OSHP */
> +	host = pci_find_host_bridge(pdev->bus);
>  	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
>  	if (root->osc_support_set)
>  		goto no_control;
> diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
> index 47decc9b3bb3..0f3711404c2b 100644
> --- a/drivers/pci/hotplug/shpchp_core.c
> +++ b/drivers/pci/hotplug/shpchp_core.c
> @@ -275,8 +275,6 @@ static int is_shpc_capable(struct pci_dev *dev)
>  	if (dev->vendor == PCI_VENDOR_ID_AMD &&
>  	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
>  		return 1;
> -	if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
> -		return 0;
>  	if (acpi_get_hp_hw_control_from_firmware(dev))
>  		return 0;
>  	return 1;
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 52b8434d4d6e..bb83be0d0e5b 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -394,6 +394,27 @@ bool pciehp_is_native(struct pci_dev *bridge)
>  	return host->native_pcie_hotplug;
>  }
>  
> +/**
> + * shpchp_is_native - Check whether a hotplug port is handled by the OS
> + * @bridge: Hotplug port to check
> + *
> + * Returns true if the given @bridge is handled by the native SHPC hotplug
> + * driver.
> + */
> +bool shpchp_is_native(struct pci_dev *bridge)
> +{
> +	const struct pci_host_bridge *host;
> +
> +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> +		return false;
> +
> +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> +		return false;
> +
> +	host = pci_find_host_bridge(bridge->bus);
> +	return host->native_shpc_hotplug;
> +}

This is sort-of-but-not-exactly the same as is_shpc_capable().

For PCI_DEVICE_ID_AMD_GOLAM_7450, is_shpc_capable() will return true
and shpchp will claim the device, but shpchp_is_native() will return
false because there's no SHPC capability.

At least that's my interpretation of the AMD GOLAM stuff.  I don't
have a spec for it, but if GOLAM did have an SHPC capability, I assume
is_shpc_capable() would look for it *before* testing for GOLAM.

So I think these two things need to be reconciled somehow.  I
mentioned this before, but it was buried at the bottom of a long
email, sorry about that.

I wish we had a spec or details about the erratum.  It looks like
it's been there "forever": https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit/drivers/pci/hotplug/shpchp.h?id=c16b4b14d9806e639f4afefa2d651a857a212afe

But neither GOLAM (0x7450) nor POGO (0x7458) is in the PCI database at
https://pci-ids.ucw.cz/read/PC/1002, so who knows if those chips ever
even saw the light of day.  I'll cc the author of

  53044f357448 ("[PATCH] PCI Hotplug: shpchp: AMD POGO errata fix")

But that was 12 years ago, so the email address may not even work any
more.

>  /**
>   * pci_acpi_wake_bus - Root bus wakeup notification fork function.
>   * @context: Device wakeup context.
> diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
> index 1f5c935eb0de..4c378368215c 100644
> --- a/include/linux/pci_hotplug.h
> +++ b/include/linux/pci_hotplug.h
> @@ -164,6 +164,7 @@ struct hotplug_params {
>  int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
>  bool pciehp_is_native(struct pci_dev *bridge);
>  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
> +bool shpchp_is_native(struct pci_dev *bridge);
>  int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
>  int acpi_pci_detect_ejectable(acpi_handle handle);
>  #else
> @@ -178,5 +179,6 @@ static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
>  	return 0;
>  }
>  static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; }
> +static inline bool shpchp_is_native(struct pci_dev *bridge) { return true; }
>  #endif
>  #endif
> -- 
> 2.17.0
>
Bjorn Helgaas May 30, 2018, 9:55 p.m. UTC | #4
[-cc David, his email bounced]

On Wed, May 30, 2018 at 03:23:43PM -0500, Bjorn Helgaas wrote:
> [+cc David]
> 
> On Mon, May 28, 2018 at 03:47:51PM +0300, Mika Westerberg wrote:
> > In the same way we do for pciehp, introduce a new function
> > shpchp_is_native() that returns true whether the bridge should be
> > handled by the native SHCP driver. Then convert the driver to use this
> > function.
> > 
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > ---
> >  drivers/pci/hotplug/acpi_pcihp.c  |  4 ++--
> >  drivers/pci/hotplug/shpchp_core.c |  2 --
> >  drivers/pci/pci-acpi.c            | 21 +++++++++++++++++++++
> >  include/linux/pci_hotplug.h       |  2 ++
> >  4 files changed, 25 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
> > index 597d22aeefc1..3979f89b250a 100644
> > --- a/drivers/pci/hotplug/acpi_pcihp.c
> > +++ b/drivers/pci/hotplug/acpi_pcihp.c
> > @@ -83,11 +83,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
> >  	 * OSHP within the scope of the hotplug controller and its parents,
> >  	 * up to the host bridge under which this controller exists.
> >  	 */
> > -	host = pci_find_host_bridge(pdev->bus);
> > -	if (host->native_shpc_hotplug)
> > +	if (shpchp_is_native(pdev))
> >  		return 0;
> >  
> >  	/* If _OSC exists, we should not evaluate OSHP */
> > +	host = pci_find_host_bridge(pdev->bus);
> >  	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
> >  	if (root->osc_support_set)
> >  		goto no_control;
> > diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
> > index 47decc9b3bb3..0f3711404c2b 100644
> > --- a/drivers/pci/hotplug/shpchp_core.c
> > +++ b/drivers/pci/hotplug/shpchp_core.c
> > @@ -275,8 +275,6 @@ static int is_shpc_capable(struct pci_dev *dev)
> >  	if (dev->vendor == PCI_VENDOR_ID_AMD &&
> >  	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
> >  		return 1;
> > -	if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
> > -		return 0;
> >  	if (acpi_get_hp_hw_control_from_firmware(dev))
> >  		return 0;
> >  	return 1;
> > diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> > index 52b8434d4d6e..bb83be0d0e5b 100644
> > --- a/drivers/pci/pci-acpi.c
> > +++ b/drivers/pci/pci-acpi.c
> > @@ -394,6 +394,27 @@ bool pciehp_is_native(struct pci_dev *bridge)
> >  	return host->native_pcie_hotplug;
> >  }
> >  
> > +/**
> > + * shpchp_is_native - Check whether a hotplug port is handled by the OS
> > + * @bridge: Hotplug port to check
> > + *
> > + * Returns true if the given @bridge is handled by the native SHPC hotplug
> > + * driver.
> > + */
> > +bool shpchp_is_native(struct pci_dev *bridge)
> > +{
> > +	const struct pci_host_bridge *host;
> > +
> > +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> > +		return false;
> > +
> > +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> > +		return false;
> > +
> > +	host = pci_find_host_bridge(bridge->bus);
> > +	return host->native_shpc_hotplug;
> > +}
> 
> This is sort-of-but-not-exactly the same as is_shpc_capable().
> 
> For PCI_DEVICE_ID_AMD_GOLAM_7450, is_shpc_capable() will return true
> and shpchp will claim the device, but shpchp_is_native() will return
> false because there's no SHPC capability.
> 
> At least that's my interpretation of the AMD GOLAM stuff.  I don't
> have a spec for it, but if GOLAM did have an SHPC capability, I assume
> is_shpc_capable() would look for it *before* testing for GOLAM.
> 
> So I think these two things need to be reconciled somehow.  I
> mentioned this before, but it was buried at the bottom of a long
> email, sorry about that.
> 
> I wish we had a spec or details about the erratum.  It looks like
> it's been there "forever": https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit/drivers/pci/hotplug/shpchp.h?id=c16b4b14d9806e639f4afefa2d651a857a212afe
> 
> But neither GOLAM (0x7450) nor POGO (0x7458) is in the PCI database at
> https://pci-ids.ucw.cz/read/PC/1002, so who knows if those chips ever
> even saw the light of day.  I'll cc the author of
> 
>   53044f357448 ("[PATCH] PCI Hotplug: shpchp: AMD POGO errata fix")
> 
> But that was 12 years ago, so the email address may not even work any
> more.
> 
> >  /**
> >   * pci_acpi_wake_bus - Root bus wakeup notification fork function.
> >   * @context: Device wakeup context.
> > diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
> > index 1f5c935eb0de..4c378368215c 100644
> > --- a/include/linux/pci_hotplug.h
> > +++ b/include/linux/pci_hotplug.h
> > @@ -164,6 +164,7 @@ struct hotplug_params {
> >  int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
> >  bool pciehp_is_native(struct pci_dev *bridge);
> >  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
> > +bool shpchp_is_native(struct pci_dev *bridge);
> >  int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
> >  int acpi_pci_detect_ejectable(acpi_handle handle);
> >  #else
> > @@ -178,5 +179,6 @@ static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
> >  	return 0;
> >  }
> >  static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; }
> > +static inline bool shpchp_is_native(struct pci_dev *bridge) { return true; }
> >  #endif
> >  #endif
> > -- 
> > 2.17.0
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mika Westerberg May 31, 2018, 6:58 a.m. UTC | #5
On Wed, May 30, 2018 at 03:23:43PM -0500, Bjorn Helgaas wrote:
> > +{
> > +	const struct pci_host_bridge *host;
> > +
> > +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> > +		return false;
> > +
> > +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> > +		return false;
> > +
> > +	host = pci_find_host_bridge(bridge->bus);
> > +	return host->native_shpc_hotplug;
> > +}
> 
> This is sort-of-but-not-exactly the same as is_shpc_capable().
> 
> For PCI_DEVICE_ID_AMD_GOLAM_7450, is_shpc_capable() will return true
> and shpchp will claim the device, but shpchp_is_native() will return
> false because there's no SHPC capability.
> 
> At least that's my interpretation of the AMD GOLAM stuff.  I don't
> have a spec for it, but if GOLAM did have an SHPC capability, I assume
> is_shpc_capable() would look for it *before* testing for GOLAM.

Most probably it did not have SHPC capability because I find it hard to
explain the check otherwise.

> So I think these two things need to be reconciled somehow.  I
> mentioned this before, but it was buried at the bottom of a long
> email, sorry about that.

No it wasn't. I read it and did exactly what you wanted. Now there is no
duplication in these two functions. is_shpc_capable() calls
acpi_get_hp_hw_control_from_firmware() which calls shpchp_is_native().
In fact I don't think is_shpc_capable() warrants to exist at all and it
should be removed (but in another separate cleanup patch).

> I wish we had a spec or details about the erratum.  It looks like
> it's been there "forever": https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit/drivers/pci/hotplug/shpchp.h?id=c16b4b14d9806e639f4afefa2d651a857a212afe
> 
> But neither GOLAM (0x7450) nor POGO (0x7458) is in the PCI database at
> https://pci-ids.ucw.cz/read/PC/1002, so who knows if those chips ever
> even saw the light of day.  I'll cc the author of
> 
>   53044f357448 ("[PATCH] PCI Hotplug: shpchp: AMD POGO errata fix")
> 
> But that was 12 years ago, so the email address may not even work any
> more.

Ín any case even if somehow the original patch from 2006 was wrong, I
don't have absolutely any idea why it needs to be fixed now in this
patch series? Given that there are two real fixes in this series that
fix real issues on real contemporary hardware, I don't really understand
why you are stalling them. Yes, it is good to do cleanups because it
makes the code easier to understand and thus more maintainable but
that's something typically not priorized as high as fixes for real
problems.

These fixes have been out there since february virtually unchanged, so
you would think they have had enough review already. If not please point
out what exactly I need to fix and I'll do that. Otherwise please
consider taking the series for v4.18.
Bjorn Helgaas May 31, 2018, 1:12 p.m. UTC | #6
On Thu, May 31, 2018 at 09:58:52AM +0300, Mika Westerberg wrote:
> On Wed, May 30, 2018 at 03:23:43PM -0500, Bjorn Helgaas wrote:
> > > +{
> > > +	const struct pci_host_bridge *host;
> > > +
> > > +	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
> > > +		return false;
> > > +
> > > +	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
> > > +		return false;
> > > +
> > > +	host = pci_find_host_bridge(bridge->bus);
> > > +	return host->native_shpc_hotplug;
> > > +}
> > 
> > This is sort-of-but-not-exactly the same as is_shpc_capable().
> > 
> > For PCI_DEVICE_ID_AMD_GOLAM_7450, is_shpc_capable() will return true
> > and shpchp will claim the device, but shpchp_is_native() will return
> > false because there's no SHPC capability.
> > 
> > At least that's my interpretation of the AMD GOLAM stuff.  I don't
> > have a spec for it, but if GOLAM did have an SHPC capability, I assume
> > is_shpc_capable() would look for it *before* testing for GOLAM.
> 
> Most probably it did not have SHPC capability because I find it hard to
> explain the check otherwise.
> 
> > So I think these two things need to be reconciled somehow.  I
> > mentioned this before, but it was buried at the bottom of a long
> > email, sorry about that.
> 
> No it wasn't. I read it and did exactly what you wanted. Now there is no
> duplication in these two functions. is_shpc_capable() calls
> acpi_get_hp_hw_control_from_firmware() which calls shpchp_is_native().
> In fact I don't think is_shpc_capable() warrants to exist at all and it
> should be removed (but in another separate cleanup patch).

Maybe I'm reading your patches wrong.  It looks to me like shpchp will
claim GOLAM_7450, which means shpchp will register slots, program the
SHPC, handle hotplug interrupts, etc.

But since shpchp_is_native() returns false, acpiphp thinks *it* should
handle hotplug.  For example, I think that given some ACPI
prerequisites (_EJ0/_RMV/etc), both will call pci_hp_register():

  shpc_probe
    is_shpc_capable             # true for GOLAM_7450
    init_slots
      pci_hp_register

  acpi_pci_add_slots
    acpiphp_enumerate_slots
      acpi_walk_namespace(..., acpiphp_add_context)
        acpiphp_add_context
          hotplug_is_native     # false for GOLAM_7450
          acpiphp_register_hotplug_slot
            pci_hp_register

It is true that the same situation occurred before your patches, since
acpiphp_add_context() only checked pciehp_is_native().  In fact, with
the existing code, shpchp and acpiphp could both try to manage *any*
SHPC, not just GOLAM_7450.

I think the current series fixes 99% of that problem and it seems like
we should try to do that last 1% at the same time so the SHPC code
makes more sense.

Bjorn
Mika Westerberg May 31, 2018, 1:51 p.m. UTC | #7
On Thu, May 31, 2018 at 08:12:02AM -0500, Bjorn Helgaas wrote:
> Maybe I'm reading your patches wrong.  It looks to me like shpchp will
> claim GOLAM_7450, which means shpchp will register slots, program the
> SHPC, handle hotplug interrupts, etc.
> 
> But since shpchp_is_native() returns false, acpiphp thinks *it* should
> handle hotplug.  For example, I think that given some ACPI
> prerequisites (_EJ0/_RMV/etc), both will call pci_hp_register():
> 
>   shpc_probe
>     is_shpc_capable             # true for GOLAM_7450
>     init_slots
>       pci_hp_register
> 
>   acpi_pci_add_slots
>     acpiphp_enumerate_slots
>       acpi_walk_namespace(..., acpiphp_add_context)
>         acpiphp_add_context
>           hotplug_is_native     # false for GOLAM_7450
>           acpiphp_register_hotplug_slot
>             pci_hp_register
> 
> It is true that the same situation occurred before your patches, since
> acpiphp_add_context() only checked pciehp_is_native().  In fact, with
> the existing code, shpchp and acpiphp could both try to manage *any*
> SHPC, not just GOLAM_7450.
> 
> I think the current series fixes 99% of that problem and it seems like
> we should try to do that last 1% at the same time so the SHPC code
> makes more sense.

Would the following fix the last 1% for you? Applies on top of this
patch.

diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 9675ab757323..516e4835019c 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -105,7 +105,6 @@ struct controller {
 };
 
 /* Define AMD SHPC ID  */
-#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450
 #define PCI_DEVICE_ID_AMD_POGO_7458	0x7458
 
 /* AMD PCI-X bridge registers */
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 0f3711404c2b..e91be287f292 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -270,22 +270,12 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 	return 0;
 }
 
-static int is_shpc_capable(struct pci_dev *dev)
-{
-	if (dev->vendor == PCI_VENDOR_ID_AMD &&
-	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
-		return 1;
-	if (acpi_get_hp_hw_control_from_firmware(dev))
-		return 0;
-	return 1;
-}
-
 static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int rc;
 	struct controller *ctrl;
 
-	if (!is_shpc_capable(pdev))
+	if (acpi_get_hp_hw_control_from_firmware(pdev))
 		return -ENODEV;
 
 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index bbc4ea70505a..fd1c0ee33805 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -408,6 +408,14 @@ bool shpchp_is_native(struct pci_dev *bridge)
 	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
 		return false;
 
+	/*
+	 * It is assumed that AMD GOLAM chips support SHPC but they do not
+	 * have SHPC capability.
+	 */
+	if (bridge->vendor == PCI_VENDOR_ID_AMD &&
+	    bridge->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
+		return true;
+
 	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
 		return false;
 
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 883cb7bf78aa..5aace6cca0d7 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -561,6 +561,7 @@
 #define PCI_DEVICE_ID_AMD_OPUS_7443	0x7443
 #define PCI_DEVICE_ID_AMD_VIPER_7443	0x7443
 #define PCI_DEVICE_ID_AMD_OPUS_7445	0x7445
+#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450
 #define PCI_DEVICE_ID_AMD_8111_PCI	0x7460
 #define PCI_DEVICE_ID_AMD_8111_LPC	0x7468
 #define PCI_DEVICE_ID_AMD_8111_IDE	0x7469
Bjorn Helgaas May 31, 2018, 4:55 p.m. UTC | #8
On Thu, May 31, 2018 at 04:51:17PM +0300, Mika Westerberg wrote:
> On Thu, May 31, 2018 at 08:12:02AM -0500, Bjorn Helgaas wrote:
> > Maybe I'm reading your patches wrong.  It looks to me like shpchp will
> > claim GOLAM_7450, which means shpchp will register slots, program the
> > SHPC, handle hotplug interrupts, etc.
> > 
> > But since shpchp_is_native() returns false, acpiphp thinks *it* should
> > handle hotplug.  For example, I think that given some ACPI
> > prerequisites (_EJ0/_RMV/etc), both will call pci_hp_register():
> > 
> >   shpc_probe
> >     is_shpc_capable             # true for GOLAM_7450
> >     init_slots
> >       pci_hp_register
> > 
> >   acpi_pci_add_slots
> >     acpiphp_enumerate_slots
> >       acpi_walk_namespace(..., acpiphp_add_context)
> >         acpiphp_add_context
> >           hotplug_is_native     # false for GOLAM_7450
> >           acpiphp_register_hotplug_slot
> >             pci_hp_register
> > 
> > It is true that the same situation occurred before your patches, since
> > acpiphp_add_context() only checked pciehp_is_native().  In fact, with
> > the existing code, shpchp and acpiphp could both try to manage *any*
> > SHPC, not just GOLAM_7450.
> > 
> > I think the current series fixes 99% of that problem and it seems like
> > we should try to do that last 1% at the same time so the SHPC code
> > makes more sense.
> 
> Would the following fix the last 1% for you? Applies on top of this
> patch.

Yes, that's exactly what I was looking for!  Thanks!

> diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
> index 9675ab757323..516e4835019c 100644
> --- a/drivers/pci/hotplug/shpchp.h
> +++ b/drivers/pci/hotplug/shpchp.h
> @@ -105,7 +105,6 @@ struct controller {
>  };
>  
>  /* Define AMD SHPC ID  */
> -#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450
>  #define PCI_DEVICE_ID_AMD_POGO_7458	0x7458
>  
>  /* AMD PCI-X bridge registers */
> diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
> index 0f3711404c2b..e91be287f292 100644
> --- a/drivers/pci/hotplug/shpchp_core.c
> +++ b/drivers/pci/hotplug/shpchp_core.c
> @@ -270,22 +270,12 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
>  	return 0;
>  }
>  
> -static int is_shpc_capable(struct pci_dev *dev)
> -{
> -	if (dev->vendor == PCI_VENDOR_ID_AMD &&
> -	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
> -		return 1;
> -	if (acpi_get_hp_hw_control_from_firmware(dev))
> -		return 0;
> -	return 1;
> -}
> -
>  static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>  {
>  	int rc;
>  	struct controller *ctrl;
>  
> -	if (!is_shpc_capable(pdev))
> +	if (acpi_get_hp_hw_control_from_firmware(pdev))
>  		return -ENODEV;
>  
>  	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index bbc4ea70505a..fd1c0ee33805 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -408,6 +408,14 @@ bool shpchp_is_native(struct pci_dev *bridge)
>  	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
>  		return false;
>  
> +	/*
> +	 * It is assumed that AMD GOLAM chips support SHPC but they do not
> +	 * have SHPC capability.
> +	 */
> +	if (bridge->vendor == PCI_VENDOR_ID_AMD &&
> +	    bridge->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
> +		return true;
> +
>  	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
>  		return false;
>  
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 883cb7bf78aa..5aace6cca0d7 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -561,6 +561,7 @@
>  #define PCI_DEVICE_ID_AMD_OPUS_7443	0x7443
>  #define PCI_DEVICE_ID_AMD_VIPER_7443	0x7443
>  #define PCI_DEVICE_ID_AMD_OPUS_7445	0x7445
> +#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450
>  #define PCI_DEVICE_ID_AMD_8111_PCI	0x7460
>  #define PCI_DEVICE_ID_AMD_8111_LPC	0x7468
>  #define PCI_DEVICE_ID_AMD_8111_IDE	0x7469
Mika Westerberg June 1, 2018, 9:27 a.m. UTC | #9
On Thu, May 31, 2018 at 11:55:56AM -0500, Bjorn Helgaas wrote:
> On Thu, May 31, 2018 at 04:51:17PM +0300, Mika Westerberg wrote:
> > On Thu, May 31, 2018 at 08:12:02AM -0500, Bjorn Helgaas wrote:
> > > Maybe I'm reading your patches wrong.  It looks to me like shpchp will
> > > claim GOLAM_7450, which means shpchp will register slots, program the
> > > SHPC, handle hotplug interrupts, etc.
> > > 
> > > But since shpchp_is_native() returns false, acpiphp thinks *it* should
> > > handle hotplug.  For example, I think that given some ACPI
> > > prerequisites (_EJ0/_RMV/etc), both will call pci_hp_register():
> > > 
> > >   shpc_probe
> > >     is_shpc_capable             # true for GOLAM_7450
> > >     init_slots
> > >       pci_hp_register
> > > 
> > >   acpi_pci_add_slots
> > >     acpiphp_enumerate_slots
> > >       acpi_walk_namespace(..., acpiphp_add_context)
> > >         acpiphp_add_context
> > >           hotplug_is_native     # false for GOLAM_7450
> > >           acpiphp_register_hotplug_slot
> > >             pci_hp_register
> > > 
> > > It is true that the same situation occurred before your patches, since
> > > acpiphp_add_context() only checked pciehp_is_native().  In fact, with
> > > the existing code, shpchp and acpiphp could both try to manage *any*
> > > SHPC, not just GOLAM_7450.
> > > 
> > > I think the current series fixes 99% of that problem and it seems like
> > > we should try to do that last 1% at the same time so the SHPC code
> > > makes more sense.
> > 
> > Would the following fix the last 1% for you? Applies on top of this
> > patch.
> 
> Yes, that's exactly what I was looking for!  Thanks!

Great. Do you want me to update this patch accordingly or will you do
that yourself?
Bjorn Helgaas June 1, 2018, 1:25 p.m. UTC | #10
On Fri, Jun 01, 2018 at 12:27:10PM +0300, Mika Westerberg wrote:
> On Thu, May 31, 2018 at 11:55:56AM -0500, Bjorn Helgaas wrote:
> > On Thu, May 31, 2018 at 04:51:17PM +0300, Mika Westerberg wrote:
> > > On Thu, May 31, 2018 at 08:12:02AM -0500, Bjorn Helgaas wrote:
> > > > Maybe I'm reading your patches wrong.  It looks to me like shpchp will
> > > > claim GOLAM_7450, which means shpchp will register slots, program the
> > > > SHPC, handle hotplug interrupts, etc.
> > > > 
> > > > But since shpchp_is_native() returns false, acpiphp thinks *it* should
> > > > handle hotplug.  For example, I think that given some ACPI
> > > > prerequisites (_EJ0/_RMV/etc), both will call pci_hp_register():
> > > > 
> > > >   shpc_probe
> > > >     is_shpc_capable             # true for GOLAM_7450
> > > >     init_slots
> > > >       pci_hp_register
> > > > 
> > > >   acpi_pci_add_slots
> > > >     acpiphp_enumerate_slots
> > > >       acpi_walk_namespace(..., acpiphp_add_context)
> > > >         acpiphp_add_context
> > > >           hotplug_is_native     # false for GOLAM_7450
> > > >           acpiphp_register_hotplug_slot
> > > >             pci_hp_register
> > > > 
> > > > It is true that the same situation occurred before your patches, since
> > > > acpiphp_add_context() only checked pciehp_is_native().  In fact, with
> > > > the existing code, shpchp and acpiphp could both try to manage *any*
> > > > SHPC, not just GOLAM_7450.
> > > > 
> > > > I think the current series fixes 99% of that problem and it seems like
> > > > we should try to do that last 1% at the same time so the SHPC code
> > > > makes more sense.
> > > 
> > > Would the following fix the last 1% for you? Applies on top of this
> > > patch.
> > 
> > Yes, that's exactly what I was looking for!  Thanks!
> 
> Great. Do you want me to update this patch accordingly or will you do
> that yourself?

No need, I squashed it in already.
diff mbox series

Patch

diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 597d22aeefc1..3979f89b250a 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -83,11 +83,11 @@  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
 	 * OSHP within the scope of the hotplug controller and its parents,
 	 * up to the host bridge under which this controller exists.
 	 */
-	host = pci_find_host_bridge(pdev->bus);
-	if (host->native_shpc_hotplug)
+	if (shpchp_is_native(pdev))
 		return 0;
 
 	/* If _OSC exists, we should not evaluate OSHP */
+	host = pci_find_host_bridge(pdev->bus);
 	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
 	if (root->osc_support_set)
 		goto no_control;
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 47decc9b3bb3..0f3711404c2b 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -275,8 +275,6 @@  static int is_shpc_capable(struct pci_dev *dev)
 	if (dev->vendor == PCI_VENDOR_ID_AMD &&
 	    dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
 		return 1;
-	if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
-		return 0;
 	if (acpi_get_hp_hw_control_from_firmware(dev))
 		return 0;
 	return 1;
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 52b8434d4d6e..bb83be0d0e5b 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -394,6 +394,27 @@  bool pciehp_is_native(struct pci_dev *bridge)
 	return host->native_pcie_hotplug;
 }
 
+/**
+ * shpchp_is_native - Check whether a hotplug port is handled by the OS
+ * @bridge: Hotplug port to check
+ *
+ * Returns true if the given @bridge is handled by the native SHPC hotplug
+ * driver.
+ */
+bool shpchp_is_native(struct pci_dev *bridge)
+{
+	const struct pci_host_bridge *host;
+
+	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
+		return false;
+
+	if (!pci_find_capability(bridge, PCI_CAP_ID_SHPC))
+		return false;
+
+	host = pci_find_host_bridge(bridge->bus);
+	return host->native_shpc_hotplug;
+}
+
 /**
  * pci_acpi_wake_bus - Root bus wakeup notification fork function.
  * @context: Device wakeup context.
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 1f5c935eb0de..4c378368215c 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -164,6 +164,7 @@  struct hotplug_params {
 int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
 bool pciehp_is_native(struct pci_dev *bridge);
 int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
+bool shpchp_is_native(struct pci_dev *bridge);
 int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
 int acpi_pci_detect_ejectable(acpi_handle handle);
 #else
@@ -178,5 +179,6 @@  static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
 	return 0;
 }
 static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; }
+static inline bool shpchp_is_native(struct pci_dev *bridge) { return true; }
 #endif
 #endif