Hi Max and Debian Kernel Team Thanks for all the testing, Max!
To the kernel team: Is there any chance you could upload a kernel with Max's patch? The relevant parts are already in the upstream kernel. The other part is a revert of a commit in the upstream kernel which is incompatible with the X server in lenny. See the bug log for more details. Is there another upload of linux-2.6 planned before the release of lenny or do you plan to release with -9? As this affects a major part of all SPARC machines, I really think this is release critical and the bug severity should be upgraded again. If you don't disagree strongly I will upgrade it in the next days. Gaudenz On Tue, Nov 04, 2008 at 11:20:09PM +0300, Max Dmitrichenko wrote: > Ok! > > I've rolled back to the lenny's X.org and applied both patches to the > kernel. It works! > > The final patch which incorporates both patches against 2.6.26.6 (i.e. > sid's current kernel) is attached. > > -- > Max > diff -urpN linux-source-2.6.26/arch/sparc64/kernel/pci.c > linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci.c > --- linux-source-2.6.26/arch/sparc64/kernel/pci.c 2008-10-18 > 14:33:11.000000000 +0400 > +++ linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci.c 2008-11-04 > 18:15:31.000000000 +0300 > @@ -350,7 +350,8 @@ static void pci_parse_of_addrs(struct of > > 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,28 +390,43 @@ struct pci_dev *of_create_pci_dev(struct > dev->devfn = devfn; > dev->multifunction = 0; /* maybe a lie? */ > > - dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); > - dev->device = of_getintprop_default(node, "device-id", 0xffff); > - dev->subsystem_vendor = > - of_getintprop_default(node, "subsystem-vendor-id", 0); > - dev->subsystem_device = > - of_getintprop_default(node, "subsystem-id", 0); > - > - dev->cfg_size = pci_cfg_space_size(dev); > - > - /* We can't actually use the firmware value, we have > - * to read what is in the register right now. One > - * reason is that in the case of IDE interfaces the > - * firmware can sample the value before the the IDE > - * interface is programmed into native mode. > - */ > - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); > - dev->class = class >> 8; > - dev->revision = class & 0xff; > - > - sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), > - dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); > + 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 = > + of_getintprop_default(node, "subsystem-vendor-id", 0); > + dev->subsystem_device = > + of_getintprop_default(node, "subsystem-id", 0); > + > + dev->cfg_size = pci_cfg_space_size(dev); > + > + /* We can't actually use the firmware value, we have > + * to read what is in the register right now. One > + * reason is that in the case of IDE interfaces the > + * firmware can sample the value before the the IDE > + * interface is programmed into native mode. > + */ > + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); > + dev->class = class >> 8; > + dev->revision = class & 0xff; > > + 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,21 +441,26 @@ struct pci_dev *of_create_pci_dev(struct > dev->current_state = 4; /* unknown power state */ > dev->error_state = pci_channel_io_normal; > > - if (!strcmp(node->name, "pci")) { > - /* a PCI-PCI bridge */ > + if (host_controller) { > dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; > dev->rom_base_reg = PCI_ROM_ADDRESS1; > - } else if (!strcmp(type, "cardbus")) { > - dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; > + dev->irq = PCI_IRQ_NONE; > } else { > - dev->hdr_type = PCI_HEADER_TYPE_NORMAL; > - dev->rom_base_reg = PCI_ROM_ADDRESS; > + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { > + /* a PCI-PCI bridge */ > + dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; > + dev->rom_base_reg = PCI_ROM_ADDRESS1; > + } else if (!strcmp(type, "cardbus")) { > + dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; > + } else { > + dev->hdr_type = PCI_HEADER_TYPE_NORMAL; > + dev->rom_base_reg = PCI_ROM_ADDRESS; > > - dev->irq = sd->op->irqs[0]; > - if (dev->irq == 0xffffffff) > - dev->irq = PCI_IRQ_NONE; > + dev->irq = sd->op->irqs[0]; > + 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(st > 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_o > 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_ > 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); > @@ -1017,6 +1081,7 @@ static int __pci_mmap_make_offset(struct > > for (i = 0; i <= PCI_ROM_RESOURCE; i++) { > struct resource *rp = &pdev->resource[i]; > + resource_size_t aligned_end; > > /* Active? */ > if (!rp->flags) > @@ -1034,8 +1099,15 @@ static int __pci_mmap_make_offset(struct > 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; > } > > diff -urpN linux-source-2.6.26/arch/sparc64/kernel/pci_common.c > linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci_common.c > --- linux-source-2.6.26/arch/sparc64/kernel/pci_common.c 2008-07-14 > 01:51:29.000000000 +0400 > +++ linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci_common.c > 2008-11-04 18:15:27.000000000 +0300 > @@ -264,6 +264,9 @@ static int sun4v_read_pci_cfg(struct pci > 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 pc > 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 -urpN linux-source-2.6.26/arch/sparc64/kernel/pci_impl.h > linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci_impl.h > --- linux-source-2.6.26/arch/sparc64/kernel/pci_impl.h 2008-07-14 > 01:51:29.000000000 +0400 > +++ linux-source-2.6.26.pci-fix/arch/sparc64/kernel/pci_impl.h > 2008-11-04 18:15:27.000000000 +0300 > @@ -167,6 +167,15 @@ extern void pci_get_pbm_props(struct pci > 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 > *); -- Ever tried. Ever failed. No matter. Try again. Fail again. Fail better. ~ Samuel Beckett ~ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]