Author: ema
Date: Wed Aug  1 16:26:06 2007
New Revision: 9242

Log:
[sparc] Add patch to fix PCI config space accesses on sun4u

Added:
   dists/sid/linux-2.6/debian/patches/bugfix/sparc/sun4u-pci-config-space.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/4

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog        (original)
+++ dists/sid/linux-2.6/debian/changelog        Wed Aug  1 16:26:06 2007
@@ -9,6 +9,9 @@
   [ Martin Michlmayr ]
   * [powerpc] Fix PS/2 keyboard detection on Pegasos (closes: #435378).
 
+  [ Emanuele Rocca ]
+  * [sparc] Add patch to fix PCI config space accesses on sun4u.
+
  -- dann frazier <[EMAIL PROTECTED]>  Mon, 30 Jul 2007 11:23:31 -0600
 
 linux-2.6 (2.6.22-3) unstable; urgency=low

Added: 
dists/sid/linux-2.6/debian/patches/bugfix/sparc/sun4u-pci-config-space.patch
==============================================================================
--- (empty file)
+++ 
dists/sid/linux-2.6/debian/patches/bugfix/sparc/sun4u-pci-config-space.patch    
    Wed Aug  1 16:26:06 2007
@@ -0,0 +1,210 @@
+commit cff2c41772272f70524486f99991d0102dee0640
+Author: David S. Miller <[EMAIL PROTECTED]>
+Date:   Wed Jul 25 23:30:16 2007 -0700
+
+    [SPARC64]: Fix sun4u PCI config space accesses on sun4u.
+    
+    Don't provide fake PCI config space for sun4u.
+    
+    Also, put back the funny host controller space handling that
+    at least Sabre needs.  You have to read PCI host controller
+    registers at their nature size otherwise you get zeros instead
+    of correct values.
+    
+    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
+
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+index 55ad1b8..77449a0 100644
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -422,10 +422,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info 
*pbm,
+       dev->multifunction = 0;         /* maybe a lie? */
+ 
+       if (host_controller) {
+-              dev->vendor = 0x108e;
+-              dev->device = 0x8000;
+-              dev->subsystem_vendor = 0x0000;
+-              dev->subsystem_device = 0x0000;
++              if (tlb_type != hypervisor) {
++                      pci_read_config_word(dev, PCI_VENDOR_ID,
++                                           &dev->vendor);
++                      pci_read_config_word(dev, PCI_DEVICE_ID,
++                                           &dev->device);
++              } else {
++                      dev->vendor = PCI_VENDOR_ID_SUN;
++                      dev->device = 0x80f0;
++              }
+               dev->cfg_size = 256;
+               dev->class = PCI_CLASS_BRIDGE_HOST << 8;
+               sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+@@ -818,7 +823,7 @@ int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
+ {
+       static u8 fake_pci_config[] = {
+               0x8e, 0x10, /* Vendor: 0x108e (Sun) */
+-              0x00, 0x80, /* Device: 0x8000 (PBM) */
++              0xf0, 0x80, /* Device: 0x80f0 (Fire) */
+               0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
+               0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
+               0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
+diff --git a/arch/sparc64/kernel/pci_common.c 
b/arch/sparc64/kernel/pci_common.c
+index 4249214..2f61c4b 100644
+--- a/arch/sparc64/kernel/pci_common.c
++++ b/arch/sparc64/kernel/pci_common.c
+@@ -44,6 +44,67 @@ static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
+       return (void *) (pbm->config_space | bus | devfn | reg);
+ }
+ 
++/* At least on Sabre, it is necessary to access all PCI host controller
++ * registers at their natural size, otherwise zeros are returned.
++ * Strange but true, and I see no language in the UltraSPARC-IIi
++ * programmer's manual that mentions this even indirectly.
++ */
++static int sun4u_read_pci_cfg_host(struct pci_pbm_info *pbm,
++                                 unsigned char bus, unsigned int devfn,
++                                 int where, int size, u32 *value)
++{
++      u32 tmp32, *addr;
++      u16 tmp16;
++      u8 tmp8;
++
++      addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
++      if (!addr)
++              return PCIBIOS_SUCCESSFUL;
++
++      switch (size) {
++      case 1:
++              if (where < 8) {
++                      unsigned long align = (unsigned long) addr;
++
++                      align &= ~1;
++                      pci_config_read16((u16 *)align, &tmp16);
++                      if (where & 1)
++                              *value = tmp16 >> 8;
++                      else
++                              *value = tmp16 & 0xff;
++              } else {
++                      pci_config_read8((u8 *)addr, &tmp8);
++                      *value = (u32) tmp8;
++              }
++              break;
++
++      case 2:
++              if (where < 8) {
++                      pci_config_read16((u16 *)addr, &tmp16);
++                      *value = (u32) tmp16;
++              } else {
++                      pci_config_read8((u8 *)addr, &tmp8);
++                      *value = (u32) tmp8;
++                      pci_config_read8(((u8 *)addr) + 1, &tmp8);
++                      *value |= ((u32) tmp8) << 8;
++              }
++              break;
++
++      case 4:
++              tmp32 = 0xffffffff;
++              sun4u_read_pci_cfg_host(pbm, bus, devfn,
++                                      where, 2, &tmp32);
++              *value = tmp32;
++
++              tmp32 = 0xffffffff;
++              sun4u_read_pci_cfg_host(pbm, bus, devfn,
++                                      where + 2, 2, &tmp32);
++              *value |= tmp32 << 16;
++              break;
++      }
++      return PCIBIOS_SUCCESSFUL;
++}
++
+ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+                             int where, int size, u32 *value)
+ {
+@@ -53,10 +114,6 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, 
unsigned int devfn,
+       u16 tmp16;
+       u8 tmp8;
+ 
+-      if (bus_dev == pbm->pci_bus && devfn == 0x00)
+-              return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
+-                                                  size, value);
+-
+       switch (size) {
+       case 1:
+               *value = 0xff;
+@@ -69,6 +126,10 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, 
unsigned int devfn,
+               break;
+       }
+ 
++      if (!bus_dev->number && !PCI_SLOT(devfn))
++              return sun4u_read_pci_cfg_host(pbm, bus, devfn, where,
++                                             size, value);
++
+       addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+       if (!addr)
+               return PCIBIOS_SUCCESSFUL;
+@@ -101,6 +162,53 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, 
unsigned int devfn,
+       return PCIBIOS_SUCCESSFUL;
+ }
+ 
++static int sun4u_write_pci_cfg_host(struct pci_pbm_info *pbm,
++                                  unsigned char bus, unsigned int devfn,
++                                  int where, int size, u32 value)
++{
++      u32 *addr;
++
++      addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
++      if (!addr)
++              return PCIBIOS_SUCCESSFUL;
++
++      switch (size) {
++      case 1:
++              if (where < 8) {
++                      unsigned long align = (unsigned long) addr;
++                      u16 tmp16;
++
++                      align &= ~1;
++                      pci_config_read16((u16 *)align, &tmp16);
++                      if (where & 1) {
++                              tmp16 &= 0x00ff;
++                              tmp16 |= value << 8;
++                      } else {
++                              tmp16 &= 0xff00;
++                              tmp16 |= value;
++                      }
++                      pci_config_write16((u16 *)align, tmp16);
++              } else
++                      pci_config_write8((u8 *)addr, value);
++              break;
++      case 2:
++              if (where < 8) {
++                      pci_config_write16((u16 *)addr, value);
++              } else {
++                      pci_config_write8((u8 *)addr, value & 0xff);
++                      pci_config_write8(((u8 *)addr) + 1, value >> 8);
++              }
++              break;
++      case 4:
++              sun4u_write_pci_cfg_host(pbm, bus, devfn,
++                                       where, 2, value & 0xffff);
++              sun4u_write_pci_cfg_host(pbm, bus, devfn,
++                                       where + 2, 2, value >> 16);
++              break;
++      }
++      return PCIBIOS_SUCCESSFUL;
++}
++
+ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+                              int where, int size, u32 value)
+ {
+@@ -108,9 +216,10 @@ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, 
unsigned int devfn,
+       unsigned char bus = bus_dev->number;
+       u32 *addr;
+ 
+-      if (bus_dev == pbm->pci_bus && devfn == 0x00)
+-              return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
+-                                                   size, value);
++      if (!bus_dev->number && !PCI_SLOT(devfn))
++              return sun4u_write_pci_cfg_host(pbm, bus, devfn, where,
++                                              size, value);
++
+       addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+       if (!addr)
+               return PCIBIOS_SUCCESSFUL;

Modified: dists/sid/linux-2.6/debian/patches/series/4
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/4 (original)
+++ dists/sid/linux-2.6/debian/patches/series/4 Wed Aug  1 16:26:06 2007
@@ -27,3 +27,4 @@
 + 
features/powerpc/efika/12626_mpx5200_uart_drop_port_lock_across_tty_flip_buffer_call.patch
 + bugfix/hppa/use-generic-compat_sys_getdents.patch
 + bugfix/powerpc/i8042-pegasos.patch
++ bugfix/sparc/sun4u-pci-config-space.patch

_______________________________________________
Kernel-svn-changes mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/kernel-svn-changes

Reply via email to