diff mbox

[V5,07/15] pci, acpi: Provide generic way to assign bus domain number.

Message ID 1455630825-27253-8-git-send-email-tn@semihalf.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomasz Nowicki Feb. 16, 2016, 1:53 p.m. UTC
As we now have valid PCI host bridge device reference we can
introduce code that is going to find its bus domain number using
ACPI _SEG method.

Note that _SEG method is optional, therefore _SEG absence means
that all PCI buses belong to domain 0.

While at it, for the sake of code clarity we put ACPI and DT domain
assign methods into the corresponding helpers.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Tested-by: Duc Dang <dhdang@apm.com>
Tested-by: Dongdong Liu <liudongdong3@huawei.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Graeme Gregory <graeme.gregory@linaro.org>
Tested-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/acpi/pci_root.c  | 18 ++++++++++++++++++
 drivers/pci/pci.c        | 11 +++++++++--
 include/linux/pci-acpi.h |  2 ++
 3 files changed, 29 insertions(+), 2 deletions(-)

Comments

Jayachandran Chandrashekaran Nair Feb. 17, 2016, 1:44 p.m. UTC | #1
Tomasz, Lorenzo,

On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
> As we now have valid PCI host bridge device reference we can
> introduce code that is going to find its bus domain number using
> ACPI _SEG method.
>
> Note that _SEG method is optional, therefore _SEG absence means
> that all PCI buses belong to domain 0.
>
> While at it, for the sake of code clarity we put ACPI and DT domain
> assign methods into the corresponding helpers.

In my patchset, I had a slightly different and I think better approach for
this without calling the _SEG method again. Please see
http://www.spinics.net/lists/arm-kernel/msg478167.html
at the last part of http://www.spinics.net/lists/arm-kernel/msg478169.html

JC.
Tomasz Nowicki Feb. 17, 2016, 2:07 p.m. UTC | #2
On 17.02.2016 14:44, Jayachandran Chandrashekaran Nair wrote:
> Tomasz, Lorenzo,
>
> On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki<tn@semihalf.com>  wrote:
>> >As we now have valid PCI host bridge device reference we can
>> >introduce code that is going to find its bus domain number using
>> >ACPI _SEG method.
>> >
>> >Note that _SEG method is optional, therefore _SEG absence means
>> >that all PCI buses belong to domain 0.
>> >
>> >While at it, for the sake of code clarity we put ACPI and DT domain
>> >assign methods into the corresponding helpers.
> In my patchset, I had a slightly different and I think better approach for
> this without calling the _SEG method again. Please see
> http://www.spinics.net/lists/arm-kernel/msg478167.html
> at the last part ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html

Relying on NULL parent device to make decision on boot method is really 
ugly way. This may hit us again once we want to obtain another firmware 
specific info e.g. numa node. IMO we need to fix it this way.

Tomasz
Jayachandran Chandrashekaran Nair Feb. 17, 2016, 2:21 p.m. UTC | #3
On Wed, Feb 17, 2016 at 7:37 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
> On 17.02.2016 14:44, Jayachandran Chandrashekaran Nair wrote:
>>
>> Tomasz, Lorenzo,
>>
>> On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki<tn@semihalf.com>  wrote:
>>>
>>> >As we now have valid PCI host bridge device reference we can
>>> >introduce code that is going to find its bus domain number using
>>> >ACPI _SEG method.
>>> >
>>> >Note that _SEG method is optional, therefore _SEG absence means
>>> >that all PCI buses belong to domain 0.
>>> >
>>> >While at it, for the sake of code clarity we put ACPI and DT domain
>>> >assign methods into the corresponding helpers.
>>
>> In my patchset, I had a slightly different and I think better approach for
>> this without calling the _SEG method again. Please see
>> http://www.spinics.net/lists/arm-kernel/msg478167.html
>> at the last part ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html
>
> Relying on NULL parent device to make decision on boot method is really ugly
> way. This may hit us again once we want to obtain another firmware specific
> info e.g. numa node. IMO we need to fix it this way.

I am not relying on NULL there, in the current code parent is NULL
in case of ACPI, and the check is needed not to crash (unless that
has changed).

The main part was the macro acpi_pci_get_segment() and the use
of acpi_pci_root_info from sysdata to do this.

JC.
Tomasz Nowicki Feb. 17, 2016, 3:05 p.m. UTC | #4
On 17.02.2016 15:21, Jayachandran Chandrashekaran Nair wrote:
> On Wed, Feb 17, 2016 at 7:37 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
>> On 17.02.2016 14:44, Jayachandran Chandrashekaran Nair wrote:
>>>
>>> Tomasz, Lorenzo,
>>>
>>> On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki<tn@semihalf.com>  wrote:
>>>>
>>>>> As we now have valid PCI host bridge device reference we can
>>>>> introduce code that is going to find its bus domain number using
>>>>> ACPI _SEG method.
>>>>>
>>>>> Note that _SEG method is optional, therefore _SEG absence means
>>>>> that all PCI buses belong to domain 0.
>>>>>
>>>>> While at it, for the sake of code clarity we put ACPI and DT domain
>>>>> assign methods into the corresponding helpers.
>>>
>>> In my patchset, I had a slightly different and I think better approach for
>>> this without calling the _SEG method again. Please see
>>> http://www.spinics.net/lists/arm-kernel/msg478167.html
>>> at the last part ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html
>>
>> Relying on NULL parent device to make decision on boot method is really ugly
>> way. This may hit us again once we want to obtain another firmware specific
>> info e.g. numa node. IMO we need to fix it this way.
>
> I am not relying on NULL there, in the current code parent is NULL
> in case of ACPI, and the check is needed not to crash (unless that
> has changed).

This series passes down valid parent, see [PATCH V5 06/15].

>
> The main part was the macro acpi_pci_get_segment() and the use
> of acpi_pci_root_info from sysdata to do this.

Since we can obtain related firmware specific data from valid parent 
device (without defining another accessors), I do not see the point to 
use sysdata. Let me know your opinion.

Tomasz
Jayachandran Chandrashekaran Nair Feb. 17, 2016, 3:21 p.m. UTC | #5
On Wed, Feb 17, 2016 at 8:35 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
> On 17.02.2016 15:21, Jayachandran Chandrashekaran Nair wrote:
>>
>> On Wed, Feb 17, 2016 at 7:37 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
>>>
>>> On 17.02.2016 14:44, Jayachandran Chandrashekaran Nair wrote:
>>>>
>>>>
>>>> Tomasz, Lorenzo,
>>>>
>>>> On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki<tn@semihalf.com>  wrote:
>>>>>
>>>>>
>>>>>> As we now have valid PCI host bridge device reference we can
>>>>>> introduce code that is going to find its bus domain number using
>>>>>> ACPI _SEG method.
>>>>>>
>>>>>> Note that _SEG method is optional, therefore _SEG absence means
>>>>>> that all PCI buses belong to domain 0.
>>>>>>
>>>>>> While at it, for the sake of code clarity we put ACPI and DT domain
>>>>>> assign methods into the corresponding helpers.
>>>>
>>>>
>>>> In my patchset, I had a slightly different and I think better approach
>>>> for
>>>> this without calling the _SEG method again. Please see
>>>> http://www.spinics.net/lists/arm-kernel/msg478167.html
>>>> at the last part
>>>> ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html
>>>
>>>
>>> Relying on NULL parent device to make decision on boot method is really
>>> ugly
>>> way. This may hit us again once we want to obtain another firmware
>>> specific
>>> info e.g. numa node. IMO we need to fix it this way.
>>
>>
>> I am not relying on NULL there, in the current code parent is NULL
>> in case of ACPI, and the check is needed not to crash (unless that
>> has changed).
>
>
> This series passes down valid parent, see [PATCH V5 06/15].
>
>>
>> The main part was the macro acpi_pci_get_segment() and the use
>> of acpi_pci_root_info from sysdata to do this.
>
>
> Since we can obtain related firmware specific data from valid parent device
> (without defining another accessors), I do not see the point to use sysdata.
> Let me know your opinion.

In the patch, you use the parent info and call _SEG method again.
The segment information is available in the ->root->segment of
acpi_pci_root_info if you setup the sysdata like in my patch

JC.
Tomasz Nowicki Feb. 17, 2016, 3:35 p.m. UTC | #6
On 17.02.2016 16:21, Jayachandran Chandrashekaran Nair wrote:
> On Wed, Feb 17, 2016 at 8:35 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
>> On 17.02.2016 15:21, Jayachandran Chandrashekaran Nair wrote:
>>>
>>> On Wed, Feb 17, 2016 at 7:37 PM, Tomasz Nowicki <tn@semihalf.com> wrote:
>>>>
>>>> On 17.02.2016 14:44, Jayachandran Chandrashekaran Nair wrote:
>>>>>
>>>>>
>>>>> Tomasz, Lorenzo,
>>>>>
>>>>> On Tue, Feb 16, 2016 at 7:23 PM, Tomasz Nowicki<tn@semihalf.com>  wrote:
>>>>>>
>>>>>>
>>>>>>> As we now have valid PCI host bridge device reference we can
>>>>>>> introduce code that is going to find its bus domain number using
>>>>>>> ACPI _SEG method.
>>>>>>>
>>>>>>> Note that _SEG method is optional, therefore _SEG absence means
>>>>>>> that all PCI buses belong to domain 0.
>>>>>>>
>>>>>>> While at it, for the sake of code clarity we put ACPI and DT domain
>>>>>>> assign methods into the corresponding helpers.
>>>>>
>>>>>
>>>>> In my patchset, I had a slightly different and I think better approach
>>>>> for
>>>>> this without calling the _SEG method again. Please see
>>>>> http://www.spinics.net/lists/arm-kernel/msg478167.html
>>>>> at the last part
>>>>> ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html
>>>>
>>>>
>>>> Relying on NULL parent device to make decision on boot method is really
>>>> ugly
>>>> way. This may hit us again once we want to obtain another firmware
>>>> specific
>>>> info e.g. numa node. IMO we need to fix it this way.
>>>
>>>
>>> I am not relying on NULL there, in the current code parent is NULL
>>> in case of ACPI, and the check is needed not to crash (unless that
>>> has changed).
>>
>>
>> This series passes down valid parent, see [PATCH V5 06/15].
>>
>>>
>>> The main part was the macro acpi_pci_get_segment() and the use
>>> of acpi_pci_root_info from sysdata to do this.
>>
>>
>> Since we can obtain related firmware specific data from valid parent device
>> (without defining another accessors), I do not see the point to use sysdata.
>> Let me know your opinion.
>
> In the patch, you use the parent info and call _SEG method again.
> The segment information is available in the ->root->segment of
> acpi_pci_root_info if you setup the sysdata like in my patch

I know it is in sysdata->root->segment, but the way it is passed down is 
wrong. sysdata is the pointer to unknown content (void *) so we need to 
validate it before we can use it. If we merge this patch we can remove 
first _SEG call.

Tomasz
Lorenzo Pieralisi Feb. 17, 2016, 5:45 p.m. UTC | #7
Guys,

On Wed, Feb 17, 2016 at 04:35:30PM +0100, Tomasz Nowicki wrote:

[...]

> >>>>>In my patchset, I had a slightly different and I think better approach
> >>>>>for
> >>>>>this without calling the _SEG method again. Please see
> >>>>>http://www.spinics.net/lists/arm-kernel/msg478167.html
> >>>>>at the last part
> >>>>>ofhttp://www.spinics.net/lists/arm-kernel/msg478169.html
> >>>>
> >>>>
> >>>>Relying on NULL parent device to make decision on boot method is really
> >>>>ugly
> >>>>way. This may hit us again once we want to obtain another firmware
> >>>>specific
> >>>>info e.g. numa node. IMO we need to fix it this way.
> >>>
> >>>
> >>>I am not relying on NULL there, in the current code parent is NULL
> >>>in case of ACPI, and the check is needed not to crash (unless that
> >>>has changed).
> >>
> >>
> >>This series passes down valid parent, see [PATCH V5 06/15].
> >>
> >>>
> >>>The main part was the macro acpi_pci_get_segment() and the use
> >>>of acpi_pci_root_info from sysdata to do this.
> >>
> >>
> >>Since we can obtain related firmware specific data from valid parent device
> >>(without defining another accessors), I do not see the point to use sysdata.
> >>Let me know your opinion.
> >
> >In the patch, you use the parent info and call _SEG method again.
> >The segment information is available in the ->root->segment of
> >acpi_pci_root_info if you setup the sysdata like in my patch
> 
> I know it is in sysdata->root->segment, but the way it is passed
> down is wrong. sysdata is the pointer to unknown content (void *) so
> we need to validate it before we can use it. If we merge this patch
> we can remove first _SEG call.

I personally do not think there is such a significant difference, both
solutions have pros and cons, it is worth keeping in mind though
that reading _SEG again to set the bus domain number works only if
the value we stash in acpi_pci_root.segment is not overridden, if it
is (ie see x86 - agreed that's to fix a FW bug) we have a disconnect.

On the other hand Tomasz's code allows removing some IA64 code in the
process (code that sets the bridge companion, so part of the patch
should be kept regardless).

So, there are two things to do:

- Assign the bridge companion in PCI core code
- Decide where to get the domain number from (acpi_pci_root.segment vs
  calling _SEG again). At present they are equivalent so I do not see
  any compelling reason to change this patch.

Side note: there is already a function (pci_domain_nr()) that you
can implement in ACPI PCI host generic (by deselecting
PCI_DOMAINS_GENERIC if ACPI) so there is no need for acpi_pci_get_segment()
in case we have to override _SEG value in the future, at present
there is no need, comments appreciated.

Lorenzo
diff mbox

Patch

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c2bd6dd..3b284dc 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -419,6 +419,24 @@  out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
+int acpi_pci_bus_domain_nr(struct device *parent)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(parent);
+	unsigned long long segment = 0;
+	acpi_status status;
+
+	/*
+	 * If _SEG method does not exist, following ACPI spec (6.5.6)
+	 * all PCI buses belong to domain 0.
+	 */
+	status = acpi_evaluate_integer(acpi_dev->handle, METHOD_NAME__SEG, NULL,
+				       &segment);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+		dev_err(&acpi_dev->dev, "can't evaluate _SEG\n");
+
+	return segment;
+}
+
 static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
 {
 	u32 support, control, requested;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 602eb42..d6c768e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,7 @@ 
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/pci-acpi.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -4769,7 +4770,7 @@  int pci_get_new_domain_nr(void)
 }
 
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+static int of_pci_bus_domain_nr(struct device *parent)
 {
 	static int use_dt_domains = -1;
 	int domain = of_get_pci_domain_nr(parent->of_node);
@@ -4811,7 +4812,13 @@  void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 		domain = -1;
 	}
 
-	bus->domain_nr = domain;
+	return domain;
+}
+
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+	bus->domain_nr = acpi_disabled ? of_pci_bus_domain_nr(parent) :
+					 acpi_pci_bus_domain_nr(parent);
 }
 #endif
 #endif
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 94d8f38..b4f87ba9 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -22,6 +22,7 @@  static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
 {
 	return acpi_remove_pm_notifier(dev);
 }
+extern int acpi_pci_bus_domain_nr(struct device *parent);
 extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
 
 static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
@@ -143,6 +144,7 @@  extern struct list_head pci_mmcfg_list;
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
+static inline int acpi_pci_bus_domain_nr(struct device *parent) { return -1; }
 #endif	/* CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_APEI