Patchwork [Karmic] SRU: PCI/cardbus: Add a fixup hook and fix powerpc

login
register
mail settings
Submitter Stefan Bader
Date Jan. 19, 2010, 11:48 a.m.
Message ID <1263901701-16182-1-git-send-email-stefan.bader@canonical.com>
Download mbox | patch
Permalink /patch/43186/
State Accepted
Delegated to: Stefan Bader
Headers show

Comments

Stefan Bader - Jan. 19, 2010, 11:48 a.m.
SRU Justication:

Impact: On powerpc, the cardbus code needs to run through fixup code,
otherwise the kernel will crash with inserted cards.

Fix: The patch, backported from upstream, will create a fixup function
which is doing nothing on all architectures but powerpc. And for powerpc
it will call the required fixup code.
For Lucid this has been forwarded to stable@kernel.org, but the 2.6.31.y
support ended now.

Testcase: see bug report.

From 8a76c709711ef4d555baa1ba540f45a6c6d8b440 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Wed, 9 Dec 2009 17:52:13 +1100
Subject: [PATCH] PCI/cardbus: Add a fixup hook and fix powerpc

BugLink: http://bugs.launchpad.net/bugs/455723

commit 2d1c861871d767153538a77c498752b36d4bb4b8 upstream

The cardbus code creates PCI devices without ever going through the
necessary fixup bits and pieces that normal PCI devices go through.

There's in fact a commented out call to pcibios_fixup_bus() in there,
it's commented because ... it doesn't work.

I could make pcibios_fixup_bus() do the right thing on powerpc easily
but I felt it cleaner instead to provide a specific hook pci_fixup_cardbus
for which a weak empty implementation is provided by the PCI core.

This fixes cardbus on powerbooks and probably all other PowerPC
platforms which was broken completely for ever on some platforms and
since 2.6.31 on others such as PowerBooks when we made the DMA ops
mandatory (since those are setup by the fixups).

Acked-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/powerpc/kernel/pci-common.c |   13 +++++++++++++
 drivers/pci/pci.c                |    5 +++++
 drivers/pcmcia/cardbus.c         |    2 +-
 include/linux/pci.h              |    3 +++
 4 files changed, 22 insertions(+), 1 deletions(-)
Andy Whitcroft - Jan. 27, 2010, 10:38 a.m.
On Tue, Jan 19, 2010 at 12:48:21PM +0100, Stefan Bader wrote:
> SRU Justication:
> 
> Impact: On powerpc, the cardbus code needs to run through fixup code,
> otherwise the kernel will crash with inserted cards.
> 
> Fix: The patch, backported from upstream, will create a fixup function
> which is doing nothing on all architectures but powerpc. And for powerpc
> it will call the required fixup code.
> For Lucid this has been forwarded to stable@kernel.org, but the 2.6.31.y
> support ended now.
> 
> Testcase: see bug report.
> 
> From 8a76c709711ef4d555baa1ba540f45a6c6d8b440 Mon Sep 17 00:00:00 2001
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Date: Wed, 9 Dec 2009 17:52:13 +1100
> Subject: [PATCH] PCI/cardbus: Add a fixup hook and fix powerpc
> 
> BugLink: http://bugs.launchpad.net/bugs/455723
> 
> commit 2d1c861871d767153538a77c498752b36d4bb4b8 upstream
> 
> The cardbus code creates PCI devices without ever going through the
> necessary fixup bits and pieces that normal PCI devices go through.
> 
> There's in fact a commented out call to pcibios_fixup_bus() in there,
> it's commented because ... it doesn't work.
> 
> I could make pcibios_fixup_bus() do the right thing on powerpc easily
> but I felt it cleaner instead to provide a specific hook pci_fixup_cardbus
> for which a weak empty implementation is provided by the PCI core.
> 
> This fixes cardbus on powerbooks and probably all other PowerPC
> platforms which was broken completely for ever on some platforms and
> since 2.6.31 on others such as PowerBooks when we made the DMA ops
> mandatory (since those are setup by the fixups).
> 
> Acked-by: Dominik Brodowski <linux@dominikbrodowski.net>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  arch/powerpc/kernel/pci-common.c |   13 +++++++++++++
>  drivers/pci/pci.c                |    5 +++++
>  drivers/pcmcia/cardbus.c         |    2 +-
>  include/linux/pci.h              |    3 +++
>  4 files changed, 22 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index e8dfdbd..cadbed6 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -1107,6 +1107,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
>  	list_for_each_entry(dev, &bus->devices, bus_list) {
>  		struct dev_archdata *sd = &dev->dev.archdata;
>  
> +		/* Cardbus can call us to add new devices to a bus, so ignore
> +		 * those who are already fully discovered
> +		 */
> +		if (dev->is_added)
> +			continue;
> +
>  		/* Setup OF node pointer in archdata */
>  		sd->of_node = pci_device_to_OF_node(dev);
>  
> @@ -1147,6 +1153,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
>  }
>  EXPORT_SYMBOL(pcibios_fixup_bus);
>  
> +void __devinit pci_fixup_cardbus(struct pci_bus *bus)
> +{
> +	/* Now fixup devices on that bus */
> +	pcibios_setup_bus_devices(bus);
> +}
> +
> +
>  static int skip_isa_ioresource_align(struct pci_dev *dev)
>  {
>  	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 4e4c295..6477722 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -2723,6 +2723,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
>  	return 1;
>  }
>  
> +void __weak pci_fixup_cardbus(struct pci_bus *bus)
> +{
> +}
> +EXPORT_SYMBOL(pci_fixup_cardbus);
> +
>  static int __init pci_setup(char *str)
>  {
>  	while (str) {
> diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
> index db77e1f..5c26793 100644
> --- a/drivers/pcmcia/cardbus.c
> +++ b/drivers/pcmcia/cardbus.c
> @@ -214,7 +214,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
>  	unsigned int max, pass;
>  
>  	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
> -//	pcibios_fixup_bus(bus);
> +	pci_fixup_cardbus(bus);
>  
>  	max = bus->secondary;
>  	for (pass = 0; pass < 2; pass++)
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index f5c7cd3..2547515 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -564,6 +564,9 @@ void pcibios_align_resource(void *, struct resource *, resource_size_t,
>  				resource_size_t);
>  void pcibios_update_irq(struct pci_dev *, int irq);
>  
> +/* Weak but can be overriden by arch */
> +void pci_fixup_cardbus(struct pci_bus *);
> +
>  /* Generic PCI functions used internally */
>  
>  extern struct pci_bus *pci_find_bus(int domain, int busnr);

Looks to only effect a change on powerpc.  Seems ok to me.

Acked-by: Andy Whitcroft <apw@canonical.com>

-apw
Leann Ogasawara - Jan. 27, 2010, 6:01 p.m.
On Wed, 2010-01-27 at 10:38 +0000, Andy Whitcroft wrote:
> On Tue, Jan 19, 2010 at 12:48:21PM +0100, Stefan Bader wrote:
> > SRU Justication:
> > 
> > Impact: On powerpc, the cardbus code needs to run through fixup code,
> > otherwise the kernel will crash with inserted cards.
> > 
> > Fix: The patch, backported from upstream, will create a fixup function
> > which is doing nothing on all architectures but powerpc. And for powerpc
> > it will call the required fixup code.
> > For Lucid this has been forwarded to stable@kernel.org, but the 2.6.31.y
> > support ended now.
> > 
> > Testcase: see bug report.
> > 
> > From 8a76c709711ef4d555baa1ba540f45a6c6d8b440 Mon Sep 17 00:00:00 2001
> > From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > Date: Wed, 9 Dec 2009 17:52:13 +1100
> > Subject: [PATCH] PCI/cardbus: Add a fixup hook and fix powerpc
> > 
> > BugLink: http://bugs.launchpad.net/bugs/455723
> > 
> > commit 2d1c861871d767153538a77c498752b36d4bb4b8 upstream
> > 
> > The cardbus code creates PCI devices without ever going through the
> > necessary fixup bits and pieces that normal PCI devices go through.
> > 
> > There's in fact a commented out call to pcibios_fixup_bus() in there,
> > it's commented because ... it doesn't work.
> > 
> > I could make pcibios_fixup_bus() do the right thing on powerpc easily
> > but I felt it cleaner instead to provide a specific hook pci_fixup_cardbus
> > for which a weak empty implementation is provided by the PCI core.
> > 
> > This fixes cardbus on powerbooks and probably all other PowerPC
> > platforms which was broken completely for ever on some platforms and
> > since 2.6.31 on others such as PowerBooks when we made the DMA ops
> > mandatory (since those are setup by the fixups).
> > 
> > Acked-by: Dominik Brodowski <linux@dominikbrodowski.net>
> > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
> > Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > ---
> >  arch/powerpc/kernel/pci-common.c |   13 +++++++++++++
> >  drivers/pci/pci.c                |    5 +++++
> >  drivers/pcmcia/cardbus.c         |    2 +-
> >  include/linux/pci.h              |    3 +++
> >  4 files changed, 22 insertions(+), 1 deletions(-)
> > 
> > diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> > index e8dfdbd..cadbed6 100644
> > --- a/arch/powerpc/kernel/pci-common.c
> > +++ b/arch/powerpc/kernel/pci-common.c
> > @@ -1107,6 +1107,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
> >  	list_for_each_entry(dev, &bus->devices, bus_list) {
> >  		struct dev_archdata *sd = &dev->dev.archdata;
> >  
> > +		/* Cardbus can call us to add new devices to a bus, so ignore
> > +		 * those who are already fully discovered
> > +		 */
> > +		if (dev->is_added)
> > +			continue;
> > +
> >  		/* Setup OF node pointer in archdata */
> >  		sd->of_node = pci_device_to_OF_node(dev);
> >  
> > @@ -1147,6 +1153,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
> >  }
> >  EXPORT_SYMBOL(pcibios_fixup_bus);
> >  
> > +void __devinit pci_fixup_cardbus(struct pci_bus *bus)
> > +{
> > +	/* Now fixup devices on that bus */
> > +	pcibios_setup_bus_devices(bus);
> > +}
> > +
> > +
> >  static int skip_isa_ioresource_align(struct pci_dev *dev)
> >  {
> >  	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index 4e4c295..6477722 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -2723,6 +2723,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
> >  	return 1;
> >  }
> >  
> > +void __weak pci_fixup_cardbus(struct pci_bus *bus)
> > +{
> > +}
> > +EXPORT_SYMBOL(pci_fixup_cardbus);
> > +
> >  static int __init pci_setup(char *str)
> >  {
> >  	while (str) {
> > diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
> > index db77e1f..5c26793 100644
> > --- a/drivers/pcmcia/cardbus.c
> > +++ b/drivers/pcmcia/cardbus.c
> > @@ -214,7 +214,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
> >  	unsigned int max, pass;
> >  
> >  	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
> > -//	pcibios_fixup_bus(bus);
> > +	pci_fixup_cardbus(bus);
> >  
> >  	max = bus->secondary;
> >  	for (pass = 0; pass < 2; pass++)
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index f5c7cd3..2547515 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -564,6 +564,9 @@ void pcibios_align_resource(void *, struct resource *, resource_size_t,
> >  				resource_size_t);
> >  void pcibios_update_irq(struct pci_dev *, int irq);
> >  
> > +/* Weak but can be overriden by arch */
> > +void pci_fixup_cardbus(struct pci_bus *);
> > +
> >  /* Generic PCI functions used internally */
> >  
> >  extern struct pci_bus *pci_find_bus(int domain, int busnr);
> 
> Looks to only effect a change on powerpc.  Seems ok to me.
> 
> Acked-by: Andy Whitcroft <apw@canonical.com>

Looks fine to me as well.

Acked-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Stefan Bader - Feb. 9, 2010, 3:34 p.m.
applied and pushed

Patch

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index e8dfdbd..cadbed6 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1107,6 +1107,12 @@  void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct dev_archdata *sd = &dev->dev.archdata;
 
+		/* Cardbus can call us to add new devices to a bus, so ignore
+		 * those who are already fully discovered
+		 */
+		if (dev->is_added)
+			continue;
+
 		/* Setup OF node pointer in archdata */
 		sd->of_node = pci_device_to_OF_node(dev);
 
@@ -1147,6 +1153,13 @@  void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void __devinit pci_fixup_cardbus(struct pci_bus *bus)
+{
+	/* Now fixup devices on that bus */
+	pcibios_setup_bus_devices(bus);
+}
+
+
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
 	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 4e4c295..6477722 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2723,6 +2723,11 @@  int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
 	return 1;
 }
 
+void __weak pci_fixup_cardbus(struct pci_bus *bus)
+{
+}
+EXPORT_SYMBOL(pci_fixup_cardbus);
+
 static int __init pci_setup(char *str)
 {
 	while (str) {
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index db77e1f..5c26793 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -214,7 +214,7 @@  int __ref cb_alloc(struct pcmcia_socket * s)
 	unsigned int max, pass;
 
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
-//	pcibios_fixup_bus(bus);
+	pci_fixup_cardbus(bus);
 
 	max = bus->secondary;
 	for (pass = 0; pass < 2; pass++)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f5c7cd3..2547515 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -564,6 +564,9 @@  void pcibios_align_resource(void *, struct resource *, resource_size_t,
 				resource_size_t);
 void pcibios_update_irq(struct pci_dev *, int irq);
 
+/* Weak but can be overriden by arch */
+void pci_fixup_cardbus(struct pci_bus *);
+
 /* Generic PCI functions used internally */
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);