[kernel] r12382 - in dists/sid/linux-2.6/debian: . patches/bugfix/sparc patches/series

Bastian Blank waldi at alioth.debian.org
Thu Nov 13 11:59:09 UTC 2008


Author: waldi
Date: Thu Nov 13 11:59:08 2008
New Revision: 12382

Log:
* [sparc] Reintroduce dummy PCI host controller to workaround broken X.org.
* [sparc] Fix size checks in PCI maps.

* debian/changelog: Update.
* debian/patches/bugfix/sparc/arch_pci_hostcontroller_workaround.patch,
  debian/patches/bugfix/sparc/arch_pci_map_align.patch: Add.
* debian/patches/series/11: Add new patches.


Added:
   dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_hostcontroller_workaround.patch
   dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_map_align.patch
   dists/sid/linux-2.6/debian/patches/series/11
Modified:
   dists/sid/linux-2.6/debian/changelog

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	(original)
+++ dists/sid/linux-2.6/debian/changelog	Thu Nov 13 11:59:08 2008
@@ -1,3 +1,10 @@
+linux-2.6 (2.6.26-11) UNRELEASED; urgency=low
+
+  * [sparc] Reintroduce dummy PCI host controller to workaround broken X.org.
+  * [sparc] Fix size checks in PCI maps.
+
+ -- Bastian Blank <waldi at debian.org>  Thu, 13 Nov 2008 12:44:45 +0100
+
 linux-2.6 (2.6.26-10) unstable; urgency=low
 
   [ dann frazier ]

Added: dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_hostcontroller_workaround.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_hostcontroller_workaround.patch	Thu Nov 13 11:59:08 2008
@@ -0,0 +1,181 @@
+Revert commit c26d3c0138970778fabe114df99dffb34a04b1d7
+
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+index 112b09f..dbf2fc2 100644
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -350,7 +350,8 @@ static void pci_parse_of_addrs(struct of_device *op,
+ 
+ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 				  struct device_node *node,
+-				  struct pci_bus *bus, int devfn)
++				  struct pci_bus *bus, int devfn,
++				  int host_controller)
+ {
+ 	struct dev_archdata *sd;
+ 	struct pci_dev *dev;
+@@ -389,6 +390,21 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 	dev->devfn = devfn;
+ 	dev->multifunction = 0;		/* maybe a lie? */
+ 
++	if (host_controller) {
++		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),
++			0x00, PCI_SLOT(devfn), PCI_FUNC(devfn));
++	} else {
+ 	dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
+ 	dev->device = of_getintprop_default(node, "device-id", 0xffff);
+ 	dev->subsystem_vendor =
+@@ -410,7 +426,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 
+ 	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ 		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+-
++	}
+ 	if (ofpci_verbose)
+ 		printk("    class: 0x%x device name: %s\n",
+ 		       dev->class, pci_name(dev));
+@@ -425,6 +441,11 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 	dev->current_state = 4;		/* unknown power state */
+ 	dev->error_state = pci_channel_io_normal;
+ 
++	if (host_controller) {
++		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
++		dev->rom_base_reg = PCI_ROM_ADDRESS1;
++		dev->irq = PCI_IRQ_NONE;
++	} else {
+ 	if (!strcmp(node->name, "pci")) {
+ 		/* a PCI-PCI bridge */
+ 		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+@@ -439,7 +460,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 		if (dev->irq == 0xffffffff)
+ 			dev->irq = PCI_IRQ_NONE;
+ 	}
+-
++	}
+ 	pci_parse_of_addrs(sd->op, node, dev);
+ 
+ 	if (ofpci_verbose)
+@@ -728,7 +749,7 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
+ 		prev_devfn = devfn;
+ 
+ 		/* create a new pci_dev for this device */
+-		dev = of_create_pci_dev(pbm, child, bus, devfn);
++		dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
+ 		if (!dev)
+ 			continue;
+ 		if (ofpci_verbose)
+@@ -775,9 +796,48 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
+ 		pci_bus_register_of_sysfs(child_bus);
+ }
+ 
++int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
++				 unsigned int devfn,
++				 int where, int size,
++				 u32 *value)
++{
++	static u8 fake_pci_config[] = {
++		0x8e, 0x10, /* Vendor: 0x108e (Sun) */
++		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 */
++		0x00, /* Cacheline: 0x00 */
++		0x40, /* Latency: 0x40 */
++		0x00, /* Header-Type: 0x00 normal */
++	};
++
++	*value = 0;
++	if (where >= 0 && where < sizeof(fake_pci_config) &&
++	    (where + size) >= 0 &&
++	    (where + size) < sizeof(fake_pci_config) &&
++	    size <= sizeof(u32)) {
++		while (size--) {
++			*value <<= 8;
++			*value |= fake_pci_config[where + size];
++		}
++	}
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
++				  unsigned int devfn,
++				  int where, int size,
++				  u32 value)
++{
++	return PCIBIOS_SUCCESSFUL;
++}
++
+ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
+ {
+ 	struct device_node *node = pbm->prom_node;
++	struct pci_dev *host_pdev;
+ 	struct pci_bus *bus;
+ 
+ 	printk("PCI: Scanning PBM %s\n", node->full_name);
+@@ -795,6 +855,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
+ 	bus->resource[0] = &pbm->io_space;
+ 	bus->resource[1] = &pbm->mem_space;
+ 
++	/* Create the dummy host bridge and link it in.  */
++	host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1);
++	bus->self = host_pdev;
++
+ 	pci_of_scan_bus(pbm, node, bus);
+ 	pci_bus_add_devices(bus);
+ 	pci_bus_register_of_sysfs(bus);
+diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
+index 19fa621..923e0bc 100644
+--- a/arch/sparc64/kernel/pci_common.c
++++ b/arch/sparc64/kernel/pci_common.c
+@@ -264,6 +264,9 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+ 	unsigned int func = PCI_FUNC(devfn);
+ 	unsigned long ret;
+ 
++	if (!bus && devfn == 0x00)
++		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
++						    size, value);
+ 	if (config_out_of_range(pbm, bus, devfn, where)) {
+ 		ret = ~0UL;
+ 	} else {
+@@ -297,6 +300,9 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+ 	unsigned int func = PCI_FUNC(devfn);
+ 	unsigned long ret;
+ 
++	if (!bus && devfn == 0x00)
++		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
++						     size, value);
+ 	if (config_out_of_range(pbm, bus, devfn, where)) {
+ 		/* Do nothing. */
+ 	} else {
+diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
+index c385d12..218bac4 100644
+--- a/arch/sparc64/kernel/pci_impl.h
++++ b/arch/sparc64/kernel/pci_impl.h
+@@ -167,6 +167,15 @@ extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
+ extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
+ extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
+ 
++extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
++					unsigned int devfn,
++					int where, int size,
++					u32 *value);
++extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
++					 unsigned int devfn,
++					 int where, int size,
++					 u32 value);
++
+ /* Error reporting support. */
+ extern void pci_scan_for_target_abort(struct pci_pbm_info *, struct pci_bus *);
+ extern void pci_scan_for_master_abort(struct pci_pbm_info *, struct pci_bus *);

Added: dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_map_align.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/sparc/arch_pci_map_align.patch	Thu Nov 13 11:59:08 2008
@@ -0,0 +1,48 @@
+commit 5769907ade8dda7002b304c03ef9e4ee5c1e0821
+Author: Max Dmitrichenko <dmitrmax at gmail.com>
+Date:   Sun Nov 2 00:34:10 2008 -0700
+
+    sparc64: Fix PCI resource mapping on sparc64
+    
+    There is a problem discovered in recent versions of ATI Mach64 driver
+    in X.org on sparc64 architecture. In short, the driver fails to mmap
+    MMIO aperture (PCI resource #2).
+    
+    I've found that kernel's __pci_mmap_make_offset() returns EINVAL. It
+    checks whether user attempts to mmap more than the resource length,
+    which is 0x1000 bytes in our case. But PAGE_SIZE on SPARC64 is 0x2000
+    and this is what actually is being mmaped. So __pci_mmap_make_offset()
+    failed for this PCI resource.
+    
+    Signed-off-by: Max Dmitrichenko <dmitrmax at gmail.com>
+    Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+index 242ac1c..bdb7c0a 100644
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -889,6 +889,7 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev,
+ 
+ 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ 		struct resource *rp = &pdev->resource[i];
++		resource_size_t aligned_end;
+ 
+ 		/* Active? */
+ 		if (!rp->flags)
+@@ -906,8 +907,15 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev,
+ 				continue;
+ 		}
+ 
++		/* Align the resource end to the next page address.
++		 * PAGE_SIZE intentionally added instead of (PAGE_SIZE - 1),
++		 * because actually we need the address of the next byte
++		 * after rp->end.
++		 */
++		aligned_end = (rp->end + PAGE_SIZE) & PAGE_MASK;
++
+ 		if ((rp->start <= user_paddr) &&
+-		    (user_paddr + user_size) <= (rp->end + 1UL))
++		    (user_paddr + user_size) <= aligned_end)
+ 			break;
+ 	}
+ 

Added: dists/sid/linux-2.6/debian/patches/series/11
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/series/11	Thu Nov 13 11:59:08 2008
@@ -0,0 +1,2 @@
++ bugfix/sparc/arch_pci_hostcontroller_workaround.patch
++ bugfix/sparc/arch_pci_map_align.patch



More information about the Kernel-svn-changes mailing list