diff mbox series

[v3,03/12] PCI: Move check for old Apple Thunderbolt controllers into a quirk

Message ID 20220211193250.1904843-4-mario.limonciello@amd.com (mailing list archive)
State Superseded
Headers show
Series Overhaul `is_thunderbolt` | expand

Commit Message

Mario Limonciello Feb. 11, 2022, 7:32 p.m. UTC
`pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
controller to indicate that D3 is possible.  As this is used solely
for older Apple systems, move it into a quirk that enumerates across
all Intel TBT controllers.

Suggested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 drivers/pci/pci.c    | 12 +++++-----
 drivers/pci/quirks.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 5 deletions(-)

Comments

Bjorn Helgaas Feb. 11, 2022, 9:35 p.m. UTC | #1
On Fri, Feb 11, 2022 at 01:32:41PM -0600, Mario Limonciello wrote:
> `pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
> controller to indicate that D3 is possible.  As this is used solely
> for older Apple systems, move it into a quirk that enumerates across
> all Intel TBT controllers.
> 
> Suggested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
>  drivers/pci/pci.c    | 12 +++++-----
>  drivers/pci/quirks.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 60 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 9ecce435fb3f..5002e214c9a6 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1064,7 +1064,13 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
>  	if (pci_use_mid_pm())
>  		return false;
>  
> -	return acpi_pci_bridge_d3(dev);
> +	if (acpi_pci_bridge_d3(dev))
> +		return true;
> +
> +	if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3"))
> +		return true;

Why do we need this?  acpi_pci_bridge_d3() already looks for
"HotPlugSupportInD3".

> +	return false;
>  }
>  
>  /**
> @@ -2954,10 +2960,6 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
>  		if (pci_bridge_d3_force)
>  			return true;
>  
> -		/* Even the oldest 2010 Thunderbolt controller supports D3. */
> -		if (bridge->is_thunderbolt)
> -			return true;
> -
>  		/* Platform might know better if the bridge supports D3 */
>  		if (platform_pci_bridge_d3(bridge))
>  			return true;
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 6d3c88edde00..aaf098ca7d54 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3756,6 +3756,59 @@ DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
>  			       quirk_apple_poweroff_thunderbolt);
>  #endif
>  
> +/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
> + * it in the ACPI tables

Wrap to fit in 80 columns like the rest of the file.  Also use the:

  /*
   * comment ...
   */

style if it's more than one line.

I don't think "as old as 2010" is helpful here -- I assume 2010 is
there because there *were* no Thunderbolt controllers before 2010, but
the code doesn't check any dates, so we basically assume all Apple
machines of any age with the listed controllers can do this.

> + */
> +static void quirk_apple_d3_thunderbolt(struct pci_dev *dev)
> +{
> +	struct property_entry properties[] = {
> +		PROPERTY_ENTRY_BOOL("HotPlugSupportInD3"),
> +		{},
> +	};
> +
> +	if (!x86_apple_machine)
> +		return;

The current code doesn't check x86_apple_machine, so this needs some
justification.  How do I know this works the same as before?

> +
> +	if (device_create_managed_software_node(&dev->dev, properties, NULL))
> +		pci_warn(dev, "could not add HotPlugSupportInD3 property");
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> +			quirk_apple_d3_thunderbolt);

The current code assumes *all* Thunderbolt controllers support D3, so
it would assume a controller released next year would support D3, but
this code would assume the opposite.  Are we supposed to add
everything to this list, or do newer machines supply
HotPlugSupportInD3, or ...?

How did you derive this list?  (Question for the commit log and/or
comments here.)

> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI,
> +			quirk_apple_d3_thunderbolt);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE,
> +			quirk_apple_d3_thunderbolt);
> +
>  /*
>   * Following are device-specific reset methods which can be used to
>   * reset a single function if other methods (e.g. FLR, PM D0->D3) are
> -- 
> 2.34.1
>
Mario Limonciello Feb. 11, 2022, 10:06 p.m. UTC | #2
On 2/11/2022 15:35, Bjorn Helgaas wrote:
> On Fri, Feb 11, 2022 at 01:32:41PM -0600, Mario Limonciello wrote:
>> `pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
>> controller to indicate that D3 is possible.  As this is used solely
>> for older Apple systems, move it into a quirk that enumerates across
>> all Intel TBT controllers.
>>
>> Suggested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> ---
>>   drivers/pci/pci.c    | 12 +++++-----
>>   drivers/pci/quirks.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 60 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 9ecce435fb3f..5002e214c9a6 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -1064,7 +1064,13 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
>>   	if (pci_use_mid_pm())
>>   		return false;
>>   
>> -	return acpi_pci_bridge_d3(dev);
>> +	if (acpi_pci_bridge_d3(dev))
>> +		return true;
>> +
>> +	if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3"))
>> +		return true;
> 
> Why do we need this?  acpi_pci_bridge_d3() already looks for
> "HotPlugSupportInD3".

The Apple machines don't have ACPI companion devices that specify this 
property.

I guess this probes a different question; can 
`device_property_read_bool` be used in `acpi_pci_bridge_d3` instead of:

	if (acpi_dev_get_property(adev, "HotPlugSupportInD3",
				   ACPI_TYPE_INTEGER, &obj) < 0)
		return false;

	return obj->integer.value == 1;

If so, then yeah this can probably be simplified.

> 
>> +	return false;
>>   }
>>   
>>   /**
>> @@ -2954,10 +2960,6 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
>>   		if (pci_bridge_d3_force)
>>   			return true;
>>   
>> -		/* Even the oldest 2010 Thunderbolt controller supports D3. */
>> -		if (bridge->is_thunderbolt)
>> -			return true;
>> -
>>   		/* Platform might know better if the bridge supports D3 */
>>   		if (platform_pci_bridge_d3(bridge))
>>   			return true;
>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>> index 6d3c88edde00..aaf098ca7d54 100644
>> --- a/drivers/pci/quirks.c
>> +++ b/drivers/pci/quirks.c
>> @@ -3756,6 +3756,59 @@ DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
>>   			       quirk_apple_poweroff_thunderbolt);
>>   #endif
>>   
>> +/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
>> + * it in the ACPI tables
> 
> Wrap to fit in 80 columns like the rest of the file.  Also use the:
> 
>    /*
>     * comment ...
>     */
> 
> style if it's more than one line.
> 
> I don't think "as old as 2010" is helpful here -- I assume 2010 is
> there because there *were* no Thunderbolt controllers before 2010, but
> the code doesn't check any dates, so we basically assume all Apple
> machines of any age with the listed controllers can do this.

The old comment was saying that, which is where I got it from.  Yeah, 
I'll update it.

> 
>> + */
>> +static void quirk_apple_d3_thunderbolt(struct pci_dev *dev)
>> +{
>> +	struct property_entry properties[] = {
>> +		PROPERTY_ENTRY_BOOL("HotPlugSupportInD3"),
>> +		{},
>> +	};
>> +
>> +	if (!x86_apple_machine)
>> +		return;
> 
> The current code doesn't check x86_apple_machine, so this needs some
> justification.  How do I know this works the same as before?

Mika and Lucas were saying the only reason for this codepath was Apple 
machines in the first place, which is where this idea came from.

Something specifically relevant is that the Apple machines use a SW 
connection manager, whereas everyone else up until USB4 devices use a 
firmware based connection manager with varying behaviors on generation 
(ICM).

> 
>> +
>> +	if (device_create_managed_software_node(&dev->dev, properties, NULL))
>> +		pci_warn(dev, "could not add HotPlugSupportInD3 property");
>> +}
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
>> +			quirk_apple_d3_thunderbolt);
> 
> The current code assumes *all* Thunderbolt controllers support D3, so
> it would assume a controller released next year would support D3, but
> this code would assume the opposite.  Are we supposed to add
> everything to this list, or do newer machines supply
> HotPlugSupportInD3, or ...?

This quirk is intended specifically for Apple, which has stopped making 
Intel machines with Intel TBT controllers.

So I don't believe the list should be growing any more, if anything it 
might need to shrink if I got too many models that weren't actually in 
Apple products.  Lucas probably needs to confirm that.

> 
> How did you derive this list?  (Question for the commit log and/or
> comments here.)

I went to pci_ids.h and got all the Thunderbolt controllers listed there.

> 
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI,
>> +			quirk_apple_d3_thunderbolt);
>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE,
>> +			quirk_apple_d3_thunderbolt);
>> +
>>   /*
>>    * Following are device-specific reset methods which can be used to
>>    * reset a single function if other methods (e.g. FLR, PM D0->D3) are
>> -- 
>> 2.34.1
>>
Lukas Wunner Feb. 13, 2022, 9:19 a.m. UTC | #3
On Fri, Feb 11, 2022 at 01:32:41PM -0600, Mario Limonciello wrote:
> `pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
> controller to indicate that D3 is possible.  As this is used solely
> for older Apple systems, move it into a quirk that enumerates across
> all Intel TBT controllers.

I'm not so sure if it is only needed on Apple systems.


> @@ -2954,10 +2960,6 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
>  		if (pci_bridge_d3_force)
>  			return true;
>  
> -		/* Even the oldest 2010 Thunderbolt controller supports D3. */
> -		if (bridge->is_thunderbolt)
> -			return true;
> -
>  		/* Platform might know better if the bridge supports D3 */
>  		if (platform_pci_bridge_d3(bridge))
>  			return true;

The fact that Thunderbolt PCIe ports support D3 is a property of those
devices.  It's not a property of the platform or a quirk of a particular
vendor.

Hence in my view the current location of the check (pci_bridge_d3_possible())
makes sense wheras the location you're moving it to does not.


> +/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
> + * it in the ACPI tables
> + */

Apple started shipping Thunderbolt in 2011.
Intel brought the first chips to market in 2010.

The date is meaningful at the code's current location in
pci_bridge_d3_possible() because a few lines further down
there's a 2015 BIOS cut-off date.

Microsoft came up with an ACPI property that BIOS vendors may set
so that Windows knows it may put a Thunderbolt controller into D3cold.
I'm not even sure if that property was ever officially adopted by the
ACPI spec or if it's just a Microsoft-defined "standard".

Apple had been using its own scheme to put Thunderbolt controllers
into D3cold when nothing is plugged in, about a decade before Microsoft
defined the ACPI property.

I'm not sure if other vendors came up with their own schemes to
power-manage Thunderbolt.  We may regress those with the present
patch.

Thanks,

Lukas
Lukas Wunner Feb. 13, 2022, 9:21 a.m. UTC | #4
On Sun, Feb 13, 2022 at 10:19:20AM +0100, Lukas Wunner wrote:
> Apple had been using its own scheme to put Thunderbolt controllers
> into D3cold when nothing is plugged in, about a decade before Microsoft
> defined the ACPI property.

I meant to say "half a decade", sorry.
Mika Westerberg Feb. 14, 2022, 7:15 a.m. UTC | #5
Hi,

On Fri, Feb 11, 2022 at 04:06:20PM -0600, Limonciello, Mario wrote:
> On 2/11/2022 15:35, Bjorn Helgaas wrote:
> > On Fri, Feb 11, 2022 at 01:32:41PM -0600, Mario Limonciello wrote:
> > > `pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
> > > controller to indicate that D3 is possible.  As this is used solely
> > > for older Apple systems, move it into a quirk that enumerates across
> > > all Intel TBT controllers.
> > > 
> > > Suggested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > > Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> > > ---
> > >   drivers/pci/pci.c    | 12 +++++-----
> > >   drivers/pci/quirks.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
> > >   2 files changed, 60 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > index 9ecce435fb3f..5002e214c9a6 100644
> > > --- a/drivers/pci/pci.c
> > > +++ b/drivers/pci/pci.c
> > > @@ -1064,7 +1064,13 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
> > >   	if (pci_use_mid_pm())
> > >   		return false;
> > > -	return acpi_pci_bridge_d3(dev);
> > > +	if (acpi_pci_bridge_d3(dev))
> > > +		return true;
> > > +
> > > +	if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3"))
> > > +		return true;
> > 
> > Why do we need this?  acpi_pci_bridge_d3() already looks for
> > "HotPlugSupportInD3".
> 
> The Apple machines don't have ACPI companion devices that specify this
> property.
> 
> I guess this probes a different question; can `device_property_read_bool` be
> used in `acpi_pci_bridge_d3` instead of:
> 
> 	if (acpi_dev_get_property(adev, "HotPlugSupportInD3",
> 				   ACPI_TYPE_INTEGER, &obj) < 0)
> 		return false;
> 
> 	return obj->integer.value == 1;
> 
> If so, then yeah this can probably be simplified.

Unfortunately the code in acpi_pci_bridge_d3() expects the device to
have an ACPI_COMPANION() which may not be the case with software nodes.

> > 
> > > +	return false;
> > >   }
> > >   /**
> > > @@ -2954,10 +2960,6 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
> > >   		if (pci_bridge_d3_force)
> > >   			return true;
> > > -		/* Even the oldest 2010 Thunderbolt controller supports D3. */
> > > -		if (bridge->is_thunderbolt)
> > > -			return true;
> > > -
> > >   		/* Platform might know better if the bridge supports D3 */
> > >   		if (platform_pci_bridge_d3(bridge))
> > >   			return true;
> > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > index 6d3c88edde00..aaf098ca7d54 100644
> > > --- a/drivers/pci/quirks.c
> > > +++ b/drivers/pci/quirks.c
> > > @@ -3756,6 +3756,59 @@ DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
> > >   			       quirk_apple_poweroff_thunderbolt);
> > >   #endif
> > > +/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
> > > + * it in the ACPI tables
> > 
> > Wrap to fit in 80 columns like the rest of the file.  Also use the:
> > 
> >    /*
> >     * comment ...
> >     */
> > 
> > style if it's more than one line.
> > 
> > I don't think "as old as 2010" is helpful here -- I assume 2010 is
> > there because there *were* no Thunderbolt controllers before 2010, but
> > the code doesn't check any dates, so we basically assume all Apple
> > machines of any age with the listed controllers can do this.
> 
> The old comment was saying that, which is where I got it from.  Yeah, I'll
> update it.
> 
> > 
> > > + */
> > > +static void quirk_apple_d3_thunderbolt(struct pci_dev *dev)
> > > +{
> > > +	struct property_entry properties[] = {
> > > +		PROPERTY_ENTRY_BOOL("HotPlugSupportInD3"),
> > > +		{},
> > > +	};
> > > +
> > > +	if (!x86_apple_machine)
> > > +		return;
> > 
> > The current code doesn't check x86_apple_machine, so this needs some
> > justification.  How do I know this works the same as before?
> 
> Mika and Lucas were saying the only reason for this codepath was Apple
> machines in the first place, which is where this idea came from.

Yes, that's the reason.

Nobody else is going to need this except Apple machines with Intel
Thunderbolt controller.

> Something specifically relevant is that the Apple machines use a SW
> connection manager, whereas everyone else up until USB4 devices use a
> firmware based connection manager with varying behaviors on generation
> (ICM).

Yup.

> > > +
> > > +	if (device_create_managed_software_node(&dev->dev, properties, NULL))
> > > +		pci_warn(dev, "could not add HotPlugSupportInD3 property");
> > > +}
> > > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> > > +			quirk_apple_d3_thunderbolt);
> > 
> > The current code assumes *all* Thunderbolt controllers support D3, so
> > it would assume a controller released next year would support D3, but
> > this code would assume the opposite.  Are we supposed to add
> > everything to this list, or do newer machines supply
> > HotPlugSupportInD3, or ...?
> 
> This quirk is intended specifically for Apple, which has stopped making
> Intel machines with Intel TBT controllers.
> 
> So I don't believe the list should be growing any more, if anything it might
> need to shrink if I got too many models that weren't actually in Apple
> products.  Lucas probably needs to confirm that.

Yes correct it won't be growing more.
Mika Westerberg Feb. 14, 2022, 7:23 a.m. UTC | #6
Hi Lukas,

On Sun, Feb 13, 2022 at 10:19:20AM +0100, Lukas Wunner wrote:
> On Fri, Feb 11, 2022 at 01:32:41PM -0600, Mario Limonciello wrote:
> > `pci_bridge_d3_possible` currently checks explicitly for a Thunderbolt
> > controller to indicate that D3 is possible.  As this is used solely
> > for older Apple systems, move it into a quirk that enumerates across
> > all Intel TBT controllers.
> 
> I'm not so sure if it is only needed on Apple systems.
> 
> 
> > @@ -2954,10 +2960,6 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
> >  		if (pci_bridge_d3_force)
> >  			return true;
> >  
> > -		/* Even the oldest 2010 Thunderbolt controller supports D3. */
> > -		if (bridge->is_thunderbolt)
> > -			return true;
> > -
> >  		/* Platform might know better if the bridge supports D3 */
> >  		if (platform_pci_bridge_d3(bridge))
> >  			return true;
> 
> The fact that Thunderbolt PCIe ports support D3 is a property of those
> devices.  It's not a property of the platform or a quirk of a particular
> vendor.

It is in fact platform specific. For instance the non-Apple systems
without "HotPlugSupportInD3" property have not been wired to support
entering/exiting D3 runtime so putting these ports into D3 may actually
lead into problems as we are in non-validated territory.

> Hence in my view the current location of the check (pci_bridge_d3_possible())
> makes sense wheras the location you're moving it to does not.
> 
> 
> > +/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
> > + * it in the ACPI tables
> > + */
> 
> Apple started shipping Thunderbolt in 2011.
> Intel brought the first chips to market in 2010.
> 
> The date is meaningful at the code's current location in
> pci_bridge_d3_possible() because a few lines further down
> there's a 2015 BIOS cut-off date.
> 
> Microsoft came up with an ACPI property that BIOS vendors may set
> so that Windows knows it may put a Thunderbolt controller into D3cold.
> I'm not even sure if that property was ever officially adopted by the
> ACPI spec or if it's just a Microsoft-defined "standard".

AFAIK It was invented by Intel Windows folks but Microsoft "documented"
it. We use the same property in ChromeOS (and therefore Linux) too so it
can be thought of as "de facto" way of declaring such port.
diff mbox series

Patch

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9ecce435fb3f..5002e214c9a6 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1064,7 +1064,13 @@  static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
 	if (pci_use_mid_pm())
 		return false;
 
-	return acpi_pci_bridge_d3(dev);
+	if (acpi_pci_bridge_d3(dev))
+		return true;
+
+	if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3"))
+		return true;
+
+	return false;
 }
 
 /**
@@ -2954,10 +2960,6 @@  bool pci_bridge_d3_possible(struct pci_dev *bridge)
 		if (pci_bridge_d3_force)
 			return true;
 
-		/* Even the oldest 2010 Thunderbolt controller supports D3. */
-		if (bridge->is_thunderbolt)
-			return true;
-
 		/* Platform might know better if the bridge supports D3 */
 		if (platform_pci_bridge_d3(bridge))
 			return true;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6d3c88edde00..aaf098ca7d54 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3756,6 +3756,59 @@  DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
 			       quirk_apple_poweroff_thunderbolt);
 #endif
 
+/* Apple machines as old as 2010 can do D3 with Thunderbolt controllers, but don't specify
+ * it in the ACPI tables
+ */
+static void quirk_apple_d3_thunderbolt(struct pci_dev *dev)
+{
+	struct property_entry properties[] = {
+		PROPERTY_ENTRY_BOOL("HotPlugSupportInD3"),
+		{},
+	};
+
+	if (!x86_apple_machine)
+		return;
+
+	if (device_create_managed_software_node(&dev->dev, properties, NULL))
+		pci_warn(dev, "could not add HotPlugSupportInD3 property");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI,
+			quirk_apple_d3_thunderbolt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE,
+			quirk_apple_d3_thunderbolt);
+
 /*
  * Following are device-specific reset methods which can be used to
  * reset a single function if other methods (e.g. FLR, PM D0->D3) are