[RFC,part1,1/7] ACPI: Make ACPI core running without PCI on ARM64

Message ID 1386088611-2801-2-git-send-email-hanjun.guo@linaro.org
State New
Headers show

Commit Message

Hanjun Guo Dec. 3, 2013, 4:36 p.m.
Not all the ARM64 targets that are using ACPI have PCI, so introduce
some stub functions to make ACPI core run without CONFIG_PCI on ARM64.

Since ACPI on X86 and IA64 depends on PCI, it will not break X86 and
IA64 with this patch.

Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
Signed-off-by: Al Stone <al.stone@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Makefile          |    2 +-
 drivers/acpi/internal.h        |    5 +++++
 drivers/acpi/osl.c             |   16 ++++++++++++++
 drivers/acpi/reboot.c          |   47 +++++++++++++++++++++++++++++-----------
 drivers/pnp/pnpacpi/rsparser.c |    2 ++
 5 files changed, 58 insertions(+), 14 deletions(-)

Comments

Matthew Garrett Dec. 3, 2013, 4:41 p.m. | #1
Given the number of #ifdefs you're adding, wouldn't it make more sense 
to just add stub functions to include/linux/pci.h?
Alan Cox Dec. 3, 2013, 4:47 p.m. | #2
> diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
> index a6c77e8b..89a181f 100644
> --- a/drivers/acpi/reboot.c
> +++ b/drivers/acpi/reboot.c
> @@ -3,12 +3,43 @@
>  #include <linux/acpi.h>
>  #include <acpi/reboot.h>
>  
> +/*
> + * There are some rare cases in the ARM world with PCI is not one
> + * of the buses available to us, even though we use ACPI.

Can we have a comment that is easier to understand here and perhaps a
better function name ?

> + */
> +#ifdef CONFIG_PCI
> +static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
> +{
> +	struct pci_bus *bus0;
> +	unsigned int devfn;
> +
> +	/* The reset register can only live on bus 0. */
> +	bus0 = pci_find_bus(0, 0);
> +	if (!bus0)
> +		return;

So if you can't find the PCI eg because we have no PCI on the device you
return silently, but


> +static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
> +{
> +	pr_warn("Resetting with ACPI PCI RESET_REG failed, PCI is disabled\n");
> +	return;
> +}

the same system without CONFIG_PCI makes a noise.

What happens when you want to build a single kernel which works on both
PCI and non PCI systems. Surely the behaviour should be the same.

The other question I'd ask is given the nature of some of these bits
would it be better to have an acpi/pci.c which holds the PCI bits ?

> +		acpi_reset_with_writing_pci_config(rr->address, reset_value);
>  		break;
>  
>  	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
> diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
> index 167f3d0..5804e77 100644
> --- a/drivers/pnp/pnpacpi/rsparser.c
> +++ b/drivers/pnp/pnpacpi/rsparser.c
> @@ -113,8 +113,10 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
>  
>  static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
>  {
> +#ifdef CONFIG_PCI
>  	if (!(r->flags & IORESOURCE_DISABLED))
>  		pcibios_penalize_isa_irq(r->start, 1);

Probably better avoid PCI ifdefs all over the place. Any reason the
includes for the PCI layer can't provide this as a dummy on a non-PCI
system ?

Alan
Hanjun Guo Dec. 4, 2013, 2:08 p.m. | #3
On 2013年12月04日 00:41, Matthew Garrett wrote:
> Given the number of #ifdefs you're adding, wouldn't it make more sense
> to just add stub functions to include/linux/pci.h?

Thanks for the suggestion :)

I can add stub functions in include/linux/pci.h for raw_pci_read()/
raw_pci_write(), then can remove #ifdefs for acpi_os_read/write_pci_configuration().

Thanks
Hanjun

>
Hanjun Guo Dec. 4, 2013, 2:15 p.m. | #4
On 2013年12月04日 00:47, One Thousand Gnomes wrote:
>> diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
>> index a6c77e8b..89a181f 100644
>> --- a/drivers/acpi/reboot.c
>> +++ b/drivers/acpi/reboot.c
>> @@ -3,12 +3,43 @@
>>   #include <linux/acpi.h>
>>   #include <acpi/reboot.h>
>>   
>> +/*
>> + * There are some rare cases in the ARM world with PCI is not one
>> + * of the buses available to us, even though we use ACPI.
> Can we have a comment that is easier to understand here and perhaps a
> better function name ?

ok, how about "Not all the ARM/ARM64 platforms with CONFIG_PCI enabled, introduce
stub function here in case of !CONFIG_PCI when using ACPI" ?

I will discuss with Graeme for a better function name


>
>> + */
>> +#ifdef CONFIG_PCI
>> +static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
>> +{
>> +	struct pci_bus *bus0;
>> +	unsigned int devfn;
>> +
>> +	/* The reset register can only live on bus 0. */
>> +	bus0 = pci_find_bus(0, 0);
>> +	if (!bus0)
>> +		return;
> So if you can't find the PCI eg because we have no PCI on the device you
> return silently, but
>
>
>> +static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
>> +{
>> +	pr_warn("Resetting with ACPI PCI RESET_REG failed, PCI is disabled\n");
>> +	return;
>> +}
> the same system without CONFIG_PCI makes a noise.
>
> What happens when you want to build a single kernel which works on both
> PCI and non PCI systems. Surely the behaviour should be the same.

Good point, thanks for the guidance, will update in next version.


>
> The other question I'd ask is given the nature of some of these bits
> would it be better to have an acpi/pci.c which holds the PCI bits ?

Sorry, I'm confused here, which PCI bits?


>
>> +		acpi_reset_with_writing_pci_config(rr->address, reset_value);
>>   		break;
>>   
>>   	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
>> diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
>> index 167f3d0..5804e77 100644
>> --- a/drivers/pnp/pnpacpi/rsparser.c
>> +++ b/drivers/pnp/pnpacpi/rsparser.c
>> @@ -113,8 +113,10 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
>>   
>>   static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
>>   {
>> +#ifdef CONFIG_PCI
>>   	if (!(r->flags & IORESOURCE_DISABLED))
>>   		pcibios_penalize_isa_irq(r->start, 1);
> Probably better avoid PCI ifdefs all over the place. Any reason the
> includes for the PCI layer can't provide this as a dummy on a non-PCI
> system ?

Agreed, I will introduce arch\arm64\include\asm\pci.h to cover pcibios_penalize_isa_irq()
as ARM did, then #ifdef here can be removed.

Thanks
Hanjun
Arnd Bergmann Dec. 5, 2013, 10:04 p.m. | #5
On Wednesday 04 December 2013, Hanjun Guo wrote:
> On 2013年12月04日 00:41, Matthew Garrett wrote:
> > Given the number of #ifdefs you're adding, wouldn't it make more sense
> > to just add stub functions to include/linux/pci.h?
> 
> Thanks for the suggestion :)
> 
> I can add stub functions in include/linux/pci.h for raw_pci_read()/
> raw_pci_write(), then can remove #ifdefs for acpi_os_read/write_pci_configuration().

Actually I wonder about the usefulness of this patch in either form: Since ACPI
on ARM64 is only for servers, I would very much expect them to always come with
PCI, either physical host bridges with attached devices, or logical PCI functions
used to describe the on-SoC I/O devices. Even in case of virtual machines, you'd
normally use PCI as the method to communicate data about the virtio channels.

Can you name a realistic use-case where you'd want ACPI but not PCI?

	Arnd
Tomasz Nowicki Dec. 6, 2013, 3:04 p.m. | #6
On 05.12.2013 23:04, Arnd Bergmann wrote:
> On Wednesday 04 December 2013, Hanjun Guo wrote:
>> On 2013年12月04日 00:41, Matthew Garrett wrote:
>>> Given the number of #ifdefs you're adding, wouldn't it make more sense
>>> to just add stub functions to include/linux/pci.h?
>>
>> Thanks for the suggestion :)
>>
>> I can add stub functions in include/linux/pci.h for raw_pci_read()/
>> raw_pci_write(), then can remove #ifdefs for acpi_os_read/write_pci_configuration().
>
> Actually I wonder about the usefulness of this patch in either form: Since ACPI
> on ARM64 is only for servers, I would very much expect them to always come with
> PCI, either physical host bridges with attached devices, or logical PCI functions
> used to describe the on-SoC I/O devices. Even in case of virtual machines, you'd
> normally use PCI as the method to communicate data about the virtio channels.
>
> Can you name a realistic use-case where you'd want ACPI but not PCI?

Yes you can describe SoC I/O devices using logical PCI functions only if 
they are on PCI, correct me if I am wrong. Also, devices can be placed 
only on IOMEM (like for ARM SoC) and it is hard to predict which way 
vendors chose. So way don't let it be configurable? ACPI spec says 
nothing like PCI is needed for ACPI, AFAIK.

Tomasz
Arnd Bergmann Dec. 6, 2013, 5:23 p.m. | #7
On Friday 06 December 2013, Tomasz Nowicki wrote:
> On 05.12.2013 23:04, Arnd Bergmann wrote:
> > On Wednesday 04 December 2013, Hanjun Guo wrote:
> >> On 2013年12月04日 00:41, Matthew Garrett wrote:
> >>> Given the number of #ifdefs you're adding, wouldn't it make more sense
> >>> to just add stub functions to include/linux/pci.h?
> >>
> >> Thanks for the suggestion :)
> >>
> >> I can add stub functions in include/linux/pci.h for raw_pci_read()/
> >> raw_pci_write(), then can remove #ifdefs for acpi_os_read/write_pci_configuration().
> >
> > Actually I wonder about the usefulness of this patch in either form: Since ACPI
> > on ARM64 is only for servers, I would very much expect them to always come with
> > PCI, either physical host bridges with attached devices, or logical PCI functions
> > used to describe the on-SoC I/O devices. Even in case of virtual machines, you'd
> > normally use PCI as the method to communicate data about the virtio channels.
> >
> > Can you name a realistic use-case where you'd want ACPI but not PCI?
> 
> Yes you can describe SoC I/O devices using logical PCI functions only if 
> they are on PCI, correct me if I am wrong. Also, devices can be placed 
> only on IOMEM (like for ARM SoC) and it is hard to predict which way 
> vendors chose. So way don't let it be configurable? ACPI spec says 
> nothing like PCI is needed for ACPI, AFAIK.

You are right that today's ARM SoCs basically never use PCI to describe
internal devices (IIRC VIA VT8500 is an exception, but their PCI was
just a software fabrication).

However, when we're talking about ACPI on ARM64, that is nothing like classic
ARM SoCs: As Jon Masters mentioned, this is about new server hardware following
a (still secret, but hopefully not much longer) hardware specification that is
explicitly designed to allow interoperability between vendors, so they
must have put some thought into how to make the hardware discoverable. It
seems that they are modeling things after how it's done on x86, and the
only sensible way to have discoverable hardware there is PCI. This is
also what all x86 SoCs do.

	Arnd
Rob Herring Dec. 9, 2013, 11:34 p.m. | #8
On Thu, Dec 5, 2013 at 4:04 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 04 December 2013, Hanjun Guo wrote:
>> On 2013年12月04日 00:41, Matthew Garrett wrote:
>> > Given the number of #ifdefs you're adding, wouldn't it make more sense
>> > to just add stub functions to include/linux/pci.h?
>>
>> Thanks for the suggestion :)
>>
>> I can add stub functions in include/linux/pci.h for raw_pci_read()/
>> raw_pci_write(), then can remove #ifdefs for acpi_os_read/write_pci_configuration().
>
> Actually I wonder about the usefulness of this patch in either form: Since ACPI
> on ARM64 is only for servers, I would very much expect them to always come with
> PCI, either physical host bridges with attached devices, or logical PCI functions
> used to describe the on-SoC I/O devices. Even in case of virtual machines, you'd
> normally use PCI as the method to communicate data about the virtio channels.
>
> Can you name a realistic use-case where you'd want ACPI but not PCI?

Calxeda h/w. Yes, we do have PCI, but it is optional.

Rob

Patch

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 0331f91..d8cebe3 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -38,7 +38,7 @@  acpi-y				+= acpi_processor.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
-acpi-y				+= pci_root.o pci_link.o pci_irq.o
+acpi-$(CONFIG_PCI)		+= pci_root.o pci_link.o pci_irq.o
 acpi-$(CONFIG_X86_INTEL_LPSS)	+= acpi_lpss.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= power.o
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index b125fdb..b1ef8fa 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -26,8 +26,13 @@ 
 acpi_status acpi_os_initialize1(void);
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
+#ifdef CONFIG_PCI
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
+#else
+static inline void acpi_pci_root_init(void) {}
+static inline void acpi_pci_link_init(void) {}
+#endif /* CONFIG_PCI */
 void acpi_processor_init(void);
 void acpi_platform_init(void);
 int acpi_sysfs_init(void);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c543626..6434045 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1016,6 +1016,7 @@  acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
 	return AE_OK;
 }
 
+#ifdef CONFIG_PCI
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
 			       u64 *value, u32 width)
@@ -1074,6 +1075,21 @@  acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
 
 	return (result ? AE_ERROR : AE_OK);
 }
+#else
+acpi_status
+acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
+				u64 *value, u32 width)
+{
+	return AE_ERROR;
+}
+
+acpi_status
+acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
+				u64 value, u32 width)
+{
+	return AE_ERROR;
+}
+#endif /* CONFIG_PCI */
 
 static void acpi_os_execute_deferred(struct work_struct *work)
 {
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index a6c77e8b..89a181f 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -3,12 +3,43 @@ 
 #include <linux/acpi.h>
 #include <acpi/reboot.h>
 
+/*
+ * There are some rare cases in the ARM world with PCI is not one
+ * of the buses available to us, even though we use ACPI.
+ */
+#ifdef CONFIG_PCI
+static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
+{
+	struct pci_bus *bus0;
+	unsigned int devfn;
+
+	/* The reset register can only live on bus 0. */
+	bus0 = pci_find_bus(0, 0);
+	if (!bus0)
+		return;
+
+	/* Form PCI device/function pair. */
+	devfn = PCI_DEVFN((address >> 32) & 0xffff,
+			(address >> 16) & 0xffff);
+	pr_debug("Resetting with ACPI PCI RESET_REG.\n");
+	/* Write the value that resets us. */
+	pci_bus_write_config_byte(bus0, devfn,
+			(address & 0xffff), reset_value);
+
+	return;
+}
+#else
+static void acpi_reset_with_writing_pci_config(u64 address, u8 reset_value)
+{
+	pr_warn("Resetting with ACPI PCI RESET_REG failed, PCI is disabled\n");
+	return;
+}
+#endif
+
 void acpi_reboot(void)
 {
 	struct acpi_generic_address *rr;
-	struct pci_bus *bus0;
 	u8 reset_value;
-	unsigned int devfn;
 
 	if (acpi_disabled)
 		return;
@@ -32,17 +63,7 @@  void acpi_reboot(void)
 	 * on a device on bus 0. */
 	switch (rr->space_id) {
 	case ACPI_ADR_SPACE_PCI_CONFIG:
-		/* The reset register can only live on bus 0. */
-		bus0 = pci_find_bus(0, 0);
-		if (!bus0)
-			return;
-		/* Form PCI device/function pair. */
-		devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
-				  (rr->address >> 16) & 0xffff);
-		printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.");
-		/* Write the value that resets us. */
-		pci_bus_write_config_byte(bus0, devfn,
-				(rr->address & 0xffff), reset_value);
+		acpi_reset_with_writing_pci_config(rr->address, reset_value);
 		break;
 
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 167f3d0..5804e77 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -113,8 +113,10 @@  static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
 
 static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
 {
+#ifdef CONFIG_PCI
 	if (!(r->flags & IORESOURCE_DISABLED))
 		pcibios_penalize_isa_irq(r->start, 1);
+#endif
 
 	pnp_add_resource(dev, r);
 }