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]

Reply via email to